1 package org
.argeo
.swt
.desktop
;
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
;
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
;
29 /** A very minimalistic desktop manager based on Java and Eclipse SWT. */
30 public class MiniDesktopManager
{
31 private Display display
;
33 private Shell rootShell
;
34 private Shell toolBarShell
;
35 private CTabFolder tabFolder
;
36 private int maxTabTitleLength
= 16;
38 private final boolean fullscreen
;
39 private final boolean stacking
;
41 public MiniDesktopManager(boolean fullscreen
, boolean stacking
) {
42 this.fullscreen
= fullscreen
;
43 this.stacking
= stacking
;
47 display
= Display
.getCurrent();
49 throw new IllegalStateException("Already a display " + display
);
50 display
= new Display();
55 rootShell
= new Shell(display
, SWT
.NO_TRIM
);
56 rootShell
.setFullScreen(true);
57 Rectangle bounds
= display
.getBounds();
59 rootShell
.setSize(bounds
.width
, bounds
.height
);
61 rootShell
= new Shell(display
, SWT
.SHELL_TRIM
);
62 Rectangle shellArea
= rootShell
.computeTrim(200, 200, 800, 480);
63 rootShell
.setSize(shellArea
.width
, shellArea
.height
);
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
));
72 toolBarShell
= new Shell(rootShell
, SWT
.NO_TRIM
| SWT
.ON_TOP
);
73 toolBar
= new ToolBar(toolBarShell
, SWT
.VERTICAL
| SWT
.FLAT
| SWT
.BORDER
);
76 toolBarArea
.setLayoutData(new GridData(toolBar
.getSize().x
, toolBar
.getSize().y
));
78 toolBar
= new ToolBar(toolBarArea
, SWT
.VERTICAL
| SWT
.FLAT
| SWT
.BORDER
);
80 toolBarArea
.setLayoutData(new GridData(SWT
.FILL
, SWT
.TOP
, false, false));
84 tabFolder
= new CTabFolder(rootShell
, SWT
.MULTI
);
85 tabFolder
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
87 Control background
= createBackground(tabFolder
);
88 CTabItem noCloseItem
= new CTabItem(tabFolder
, SWT
.NONE
);
89 noCloseItem
.setText("Home");
90 noCloseItem
.setControl(background
);
92 createBackground(rootShell
);
96 // rootShell.layout(true, true);
98 if (toolBarShell
!= null) {
99 toolBarShell
.setLocation(new Point(0, 0));
104 protected void createDock(ToolBar toolBar
) {
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
) {
112 protected void exitCalled() {
113 if (appContext
.shell
!= null)
114 appContext
.shell
.dispose();
115 if (appContext
.tabItem
!= null)
116 appContext
.tabItem
.dispose();
121 title
= System
.getProperty("user.name") + "@" + InetAddress
.getLocalHost().getHostName();
122 } catch (UnknownHostException e
) {
123 title
= System
.getProperty("user.name") + "@localhost";
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
);
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
) {
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
);
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
) {
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());
172 addToolItem(toolBar
, display
.getSystemImage(SWT
.ICON_ERROR
), "Exit", () -> rootShell
.dispose());
177 protected String
tabTitle(String title
) {
178 return title
.length() > maxTabTitleLength ? title
.substring(0, maxTabTitleLength
) : title
;
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() {
188 public void widgetSelected(SelectionEvent e
) {
195 protected AppContext
createAppParent() {
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
);
203 Shell shell
= new Shell(rootShell
, SWT
.SHELL_TRIM
);
204 return new AppContext(shell
);
208 protected void openApp(AppContext appContext
) {
209 if (appContext
.shell
!= null) {
210 Shell shell
= (Shell
) appContext
.shell
;
212 shell
.setSize(new Point(800, 480));
214 if (appContext
.tabItem
!= null) {
215 tabFolder
.setSelection(appContext
.tabItem
);
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
;
226 protected void initBackground(Composite backgroundArea
) {
227 MiniDesktopLayer desktopLayer
= new MiniDesktopLayer();
228 desktopLayer
.init(backgroundArea
, Paths
.get(System
.getProperty("user.dir")));
232 while (!rootShell
.isDisposed()) {
233 if (!display
.readAndDispatch())
238 public void dispose() {
239 if (!rootShell
.isDisposed())
243 protected boolean isFullscreen() {
247 protected boolean isStacking() {
251 protected Image
getIconForExt(String ext
) {
252 Program program
= Program
.findProgram(ext
);
254 return display
.getSystemImage(SWT
.ICON_INFORMATION
);
256 ImageData iconData
= program
.getImageData();
257 if (iconData
== null) {
258 return display
.getSystemImage(SWT
.ICON_INFORMATION
);
260 return new Image(display
, iconData
);
265 private static GridLayout
noSpaceGridLayout(GridLayout layout
) {
266 layout
.horizontalSpacing
= 0;
267 layout
.verticalSpacing
= 0;
268 layout
.marginWidth
= 0;
269 layout
.marginHeight
= 0;
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");
283 boolean fullscreen
= options
.contains("--fullscreen");
284 boolean stacking
= options
.contains("--stacking");
286 MiniDesktopManager desktopManager
= new MiniDesktopManager(fullscreen
, stacking
);
287 desktopManager
.init();
288 desktopManager
.run();
289 desktopManager
.dispose();
295 private CTabItem tabItem
;
297 public AppContext(Shell shell
) {
301 public AppContext(CTabItem tabItem
) {
302 this.tabItem
= tabItem
;
305 Composite
getAppParent() {
309 return (Composite
) tabItem
.getControl();
310 throw new IllegalStateException();