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