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