]> git.argeo.org Git - lgpl/argeo-commons.git/blob - swt/org.argeo.swt.minidesktop/src/org/argeo/minidesktop/MiniDesktopManager.java
Improve mini desktop clean up
[lgpl/argeo-commons.git] / swt / org.argeo.swt.minidesktop / src / org / argeo / minidesktop / MiniDesktopManager.java
1 package org.argeo.minidesktop;
2
3 import java.lang.management.ManagementFactory;
4 import java.net.InetAddress;
5 import java.net.UnknownHostException;
6 import java.nio.file.Path;
7 import java.util.Arrays;
8 import java.util.List;
9
10 import org.eclipse.swt.SWT;
11 import org.eclipse.swt.custom.CTabFolder;
12 import org.eclipse.swt.custom.CTabItem;
13 import org.eclipse.swt.events.SelectionAdapter;
14 import org.eclipse.swt.events.SelectionEvent;
15 import org.eclipse.swt.graphics.Color;
16 import org.eclipse.swt.graphics.Image;
17 import org.eclipse.swt.graphics.Point;
18 import org.eclipse.swt.graphics.Rectangle;
19 import org.eclipse.swt.layout.GridData;
20 import org.eclipse.swt.layout.GridLayout;
21 import org.eclipse.swt.widgets.Composite;
22 import org.eclipse.swt.widgets.Control;
23 import org.eclipse.swt.widgets.Display;
24 import org.eclipse.swt.widgets.Shell;
25 import org.eclipse.swt.widgets.ToolBar;
26 import org.eclipse.swt.widgets.ToolItem;
27
28 /** A very minimalistic desktop manager based on Java and Eclipse SWT. */
29 public class MiniDesktopManager {
30 private Display display;
31
32 private Shell rootShell;
33 private Shell toolBarShell;
34 private CTabFolder tabFolder;
35 private int maxTabTitleLength = 16;
36
37 private final boolean fullscreen;
38 private final boolean stacking;
39
40 private MiniDesktopImages images;
41
42 public MiniDesktopManager(boolean fullscreen, boolean stacking) {
43 this.fullscreen = fullscreen;
44 this.stacking = stacking;
45 }
46
47 public MiniDesktopManager() {
48 this(false, false);
49 }
50
51 public void start() {
52 init();
53 }
54
55 public void stop() {
56 dispose();
57 if (display != null) {
58 display.syncExec(() -> {
59 display.dispose();
60 display = null;
61 });
62 }
63 }
64
65 public void init() {
66 Display.setAppName("Mini SWT Desktop");
67 display = Display.getCurrent();
68 if (display != null)
69 throw new IllegalStateException("Already a display " + display);
70 display = Display.getDefault();
71
72 display.syncExec(() -> {
73 if (display.getTouchEnabled()) {
74 System.out.println("Touch enabled.");
75 }
76
77 images = new MiniDesktopImages(display);
78
79 int toolBarSize = 48;
80
81 if (isFullscreen()) {
82 rootShell = new Shell(display, SWT.NO_TRIM);
83 rootShell.setFullScreen(true);
84 Rectangle bounds = display.getBounds();
85 rootShell.setLocation(0, 0);
86 rootShell.setSize(bounds.width, bounds.height);
87 } else {
88 rootShell = new Shell(display, SWT.CLOSE | SWT.RESIZE);
89 Rectangle shellArea = rootShell.computeTrim(200, 200, 800, 480);
90 rootShell.setSize(shellArea.width, shellArea.height);
91 rootShell.setText(Display.getAppName());
92 rootShell.setImage(images.terminalIcon);
93 }
94
95 rootShell.setLayout(noSpaceGridLayout(new GridLayout(2, false)));
96 Composite toolBarArea = new Composite(rootShell, SWT.NONE);
97 toolBarArea.setLayoutData(new GridData(toolBarSize, rootShell.getSize().y));
98
99 ToolBar toolBar;
100 if (isFullscreen()) {
101 toolBarShell = new Shell(rootShell, SWT.NO_TRIM | SWT.ON_TOP);
102 toolBar = new ToolBar(toolBarShell, SWT.VERTICAL | SWT.FLAT | SWT.BORDER);
103 createDock(toolBar);
104 toolBarShell.pack();
105 toolBarArea.setLayoutData(new GridData(toolBar.getSize().x, toolBar.getSize().y));
106 } else {
107 toolBar = new ToolBar(toolBarArea, SWT.VERTICAL | SWT.FLAT | SWT.BORDER);
108 createDock(toolBar);
109 toolBarArea.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false));
110 }
111
112 if (isStacking()) {
113 tabFolder = new CTabFolder(rootShell, SWT.MULTI | SWT.BORDER | SWT.BOTTOM);
114 tabFolder.setLayout(noSpaceGridLayout(new GridLayout()));
115 tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
116
117 Color selectionBackground = display.getSystemColor(SWT.COLOR_LIST_SELECTION);
118 tabFolder.setSelectionBackground(selectionBackground);
119
120 // background
121 Control background = createBackground(tabFolder);
122 CTabItem homeTabItem = new CTabItem(tabFolder, SWT.NONE);
123 homeTabItem.setText("Home");
124 homeTabItem.setImage(images.homeIcon);
125 homeTabItem.setControl(background);
126 tabFolder.setFocus();
127 } else {
128 createBackground(rootShell);
129 }
130
131 rootShell.open();
132 // rootShell.layout(true, true);
133
134 if (toolBarShell != null) {
135 int toolBarShellY = (display.getBounds().height - toolBar.getSize().y) / 2;
136 toolBarShell.setLocation(0, toolBarShellY);
137 toolBarShell.open();
138 }
139
140 long jvmUptime = ManagementFactory.getRuntimeMXBean().getUptime();
141 System.out.println("SWT Mini Desktop Manager available in " + jvmUptime + " ms.");
142 });
143 }
144
145 protected void createDock(ToolBar toolBar) {
146 // Terminal
147 addToolItem(toolBar, images.terminalIcon, "Terminal", () -> {
148 String url = System.getProperty("user.home");
149 AppContext appContext = createAppParent(images.terminalIcon);
150 new MiniTerminal(appContext.getAppParent(), url) {
151
152 @Override
153 protected void exitCalled() {
154 if (appContext.shell != null)
155 appContext.shell.dispose();
156 if (appContext.tabItem != null)
157 appContext.tabItem.dispose();
158 }
159 };
160 String title;
161 try {
162 title = System.getProperty("user.name") + "@" + InetAddress.getLocalHost().getHostName();
163 } catch (UnknownHostException e) {
164 title = System.getProperty("user.name") + "@localhost";
165 }
166 if (appContext.shell != null)
167 appContext.shell.setText(title);
168 if (appContext.tabItem != null) {
169 appContext.tabItem.setText(tabTitle(title));
170 appContext.tabItem.setToolTipText(title);
171 }
172 openApp(appContext);
173 });
174
175 // Web browser
176 addToolItem(toolBar, images.browserIcon, "Browser", () -> {
177 String url = "https://start.duckduckgo.com/";
178 AppContext appContext = createAppParent(images.browserIcon);
179 new MiniBrowser(appContext.getAppParent(), url, false, false) {
180 @Override
181 public void titleChanged(String title) {
182 if (appContext.shell != null)
183 appContext.shell.setText(title);
184 if (appContext.tabItem != null) {
185 appContext.tabItem.setText(tabTitle(title));
186 appContext.tabItem.setToolTipText(title);
187 }
188 }
189 };
190 openApp(appContext);
191 });
192
193 // File explorer
194 addToolItem(toolBar, images.explorerIcon, "Explorer", () -> {
195 String url = System.getProperty("user.home");
196 AppContext appContext = createAppParent(images.explorerIcon);
197 new MiniExplorer(appContext.getAppParent(), url) {
198
199 @Override
200 protected void pathChanged(Path path) {
201 if (appContext.shell != null)
202 appContext.shell.setText(path.toString());
203 if (appContext.tabItem != null) {
204 appContext.tabItem.setText(path.getFileName().toString());
205 appContext.tabItem.setToolTipText(path.toString());
206 }
207 }
208 };
209 openApp(appContext);
210 });
211
212 // Separator
213 new ToolItem(toolBar, SWT.SEPARATOR);
214
215 // Exit
216 addToolItem(toolBar, images.exitIcon, "Exit", () -> rootShell.dispose());
217
218 toolBar.pack();
219 }
220
221 protected String tabTitle(String title) {
222 return title.length() > maxTabTitleLength ? title.substring(0, maxTabTitleLength) : title;
223 }
224
225 protected void addToolItem(ToolBar toolBar, Image icon, String name, Runnable action) {
226 ToolItem searchI = new ToolItem(toolBar, SWT.PUSH);
227 searchI.setImage(icon);
228 searchI.setToolTipText(name);
229 searchI.addSelectionListener(new SelectionAdapter() {
230
231 @Override
232 public void widgetSelected(SelectionEvent e) {
233 action.run();
234 }
235
236 });
237 }
238
239 protected AppContext createAppParent(Image icon) {
240 if (isStacking()) {
241 Composite appParent = new Composite(tabFolder, SWT.CLOSE);
242 appParent.setLayout(noSpaceGridLayout(new GridLayout()));
243 CTabItem item = new CTabItem(tabFolder, SWT.CLOSE);
244 item.setImage(icon);
245 item.setControl(appParent);
246 return new AppContext(item);
247 } else {
248 Shell shell = isFullscreen() ? new Shell(rootShell, SWT.SHELL_TRIM)
249 : new Shell(rootShell.getDisplay(), SWT.SHELL_TRIM);
250 shell.setImage(icon);
251 return new AppContext(shell);
252 }
253 }
254
255 protected void openApp(AppContext appContext) {
256 if (appContext.shell != null) {
257 Shell shell = (Shell) appContext.shell;
258 shell.open();
259 shell.setSize(new Point(800, 480));
260 }
261 if (appContext.tabItem != null) {
262 tabFolder.setFocus();
263 tabFolder.setSelection(appContext.tabItem);
264 }
265 }
266
267 protected Control createBackground(Composite parent) {
268 Composite backgroundArea = new Composite(parent, SWT.NONE);
269 backgroundArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
270 initBackground(backgroundArea);
271 return backgroundArea;
272 }
273
274 protected void initBackground(Composite backgroundArea) {
275 MiniHomePart homePart = new MiniHomePart() {
276
277 @Override
278 protected void fillAppsToolBar(ToolBar toolBar) {
279 createDock(toolBar);
280 }
281 };
282 homePart.createUiPart(backgroundArea, null);
283 }
284
285 public void run() {
286 while (!rootShell.isDisposed()) {
287 if (!display.readAndDispatch())
288 display.sleep();
289 }
290 }
291
292 public void dispose() {
293 if (!rootShell.isDisposed()) {
294 rootShell.getDisplay().syncExec(() -> {
295 rootShell.dispose();
296 });
297 }
298 }
299
300 protected boolean isFullscreen() {
301 return fullscreen;
302 }
303
304 protected boolean isStacking() {
305 return stacking;
306 }
307
308 protected Image getIconForExt(String ext) {
309 // Program program = Program.findProgram(ext);
310 // if (program == null)
311 return display.getSystemImage(SWT.ICON_INFORMATION);
312
313 // ImageData iconData = program.getImageData();
314 // if (iconData == null) {
315 // return display.getSystemImage(SWT.ICON_INFORMATION);
316 // } else {
317 // return new Image(display, iconData);
318 // }
319
320 }
321
322 private static GridLayout noSpaceGridLayout(GridLayout layout) {
323 layout.horizontalSpacing = 0;
324 layout.verticalSpacing = 0;
325 layout.marginWidth = 0;
326 layout.marginHeight = 0;
327 return layout;
328 }
329
330 public static void main(String[] args) {
331 List<String> options = Arrays.asList(args);
332 if (options.contains("--help")) {
333 System.out.println("Usage: java " + MiniDesktopManager.class.getName().replace('.', '/') + " [OPTION]");
334 System.out.println("A minimalistic desktop manager based on Java and Eclipse SWT.");
335 System.out.println(" --fullscreen : take control of the whole screen (default is to run in a window)");
336 System.out.println(" --stacking : open apps as tabs (default is to create new windows)");
337 System.out.println(" --help : print this help and exit");
338 System.exit(1);
339 }
340 boolean fullscreen = options.contains("--fullscreen");
341 boolean stacking = options.contains("--stacking");
342
343 MiniDesktopManager desktopManager = new MiniDesktopManager(fullscreen, stacking);
344 desktopManager.init();
345 desktopManager.run();
346 desktopManager.dispose();
347 System.exit(0);
348 }
349
350 class AppContext {
351 private Shell shell;
352 private CTabItem tabItem;
353
354 public AppContext(Shell shell) {
355 this.shell = shell;
356 }
357
358 public AppContext(CTabItem tabItem) {
359 this.tabItem = tabItem;
360 }
361
362 Composite getAppParent() {
363 if (shell != null)
364 return shell;
365 if (tabItem != null)
366 return (Composite) tabItem.getControl();
367 throw new IllegalStateException();
368 }
369 }
370 }