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