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