1 package org
.argeo
.minidesktop
;
3 import java
.net
.InetAddress
;
4 import java
.net
.UnknownHostException
;
5 import java
.nio
.file
.Path
;
6 import java
.util
.Arrays
;
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
;
28 /** A very minimalistic desktop manager based on Java and Eclipse SWT. */
29 public class MiniDesktopManager
{
30 private Display display
;
32 private Shell rootShell
;
33 private Shell toolBarShell
;
34 private CTabFolder tabFolder
;
35 private int maxTabTitleLength
= 16;
37 private final boolean fullscreen
;
38 private final boolean stacking
;
40 public MiniDesktopManager(boolean fullscreen
, boolean stacking
) {
41 this.fullscreen
= fullscreen
;
42 this.stacking
= stacking
;
46 display
= Display
.getCurrent();
48 throw new IllegalStateException("Already a display " + display
);
49 display
= new Display();
54 rootShell
= new Shell(display
, SWT
.NO_TRIM
);
55 rootShell
.setFullScreen(true);
56 Rectangle bounds
= display
.getBounds();
57 rootShell
.setSize(bounds
.width
, bounds
.height
);
59 rootShell
= new Shell(display
, SWT
.SHELL_TRIM
);
60 Rectangle shellArea
= rootShell
.computeTrim(200, 200, 800, 480);
61 rootShell
.setSize(shellArea
.width
, shellArea
.height
);
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
));
70 toolBarShell
= new Shell(rootShell
, SWT
.NO_TRIM
| SWT
.ON_TOP
);
71 toolBar
= new ToolBar(toolBarShell
, SWT
.VERTICAL
| SWT
.FLAT
| SWT
.BORDER
);
74 toolBarArea
.setLayoutData(new GridData(toolBar
.getSize().x
, toolBar
.getSize().y
));
76 toolBar
= new ToolBar(toolBarArea
, SWT
.VERTICAL
| SWT
.FLAT
| SWT
.BORDER
);
78 toolBarArea
.setLayoutData(new GridData(SWT
.FILL
, SWT
.TOP
, false, false));
82 tabFolder
= new CTabFolder(rootShell
, SWT
.MULTI
);
83 tabFolder
.setLayoutData(new GridData(SWT
.FILL
, SWT
.FILL
, true, true));
85 Control background
= createBackground(tabFolder
);
86 CTabItem noCloseItem
= new CTabItem(tabFolder
, SWT
.NONE
);
87 noCloseItem
.setText("Home");
88 noCloseItem
.setControl(background
);
90 createBackground(rootShell
);
94 // rootShell.layout(true, true);
96 if (toolBarShell
!= null) {
97 toolBarShell
.setLocation(new Point(0, 0));
102 protected void createDock(ToolBar toolBar
) {
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
) {
110 protected void exitCalled() {
111 if (appContext
.shell
!= null)
112 appContext
.shell
.dispose();
113 if (appContext
.tabItem
!= null)
114 appContext
.tabItem
.dispose();
119 title
= System
.getProperty("user.name") + "@" + InetAddress
.getLocalHost().getHostName();
120 } catch (UnknownHostException e
) {
121 title
= System
.getProperty("user.name") + "@localhost";
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
);
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) {
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
);
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
) {
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());
170 addToolItem(toolBar
, display
.getSystemImage(SWT
.ICON_ERROR
), "Exit", () -> rootShell
.dispose());
175 protected String
tabTitle(String title
) {
176 return title
.length() > maxTabTitleLength ? title
.substring(0, maxTabTitleLength
) : title
;
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() {
186 public void widgetSelected(SelectionEvent e
) {
193 protected AppContext
createAppParent() {
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
);
201 Shell shell
= new Shell(rootShell
, SWT
.SHELL_TRIM
);
202 return new AppContext(shell
);
206 protected void openApp(AppContext appContext
) {
207 if (appContext
.shell
!= null) {
208 Shell shell
= (Shell
) appContext
.shell
;
210 shell
.setSize(new Point(800, 480));
212 if (appContext
.tabItem
!= null) {
213 tabFolder
.setSelection(appContext
.tabItem
);
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
;
224 protected void initBackground(Composite backgroundArea
) {
228 while (!rootShell
.isDisposed()) {
229 if (!display
.readAndDispatch())
234 public void dispose() {
235 if (!rootShell
.isDisposed())
239 protected boolean isFullscreen() {
243 protected boolean isStacking() {
247 protected Image
getIconForExt(String ext
) {
248 Program program
= Program
.findProgram(ext
);
250 return display
.getSystemImage(SWT
.ICON_INFORMATION
);
252 ImageData iconData
= program
.getImageData();
253 if (iconData
== null) {
254 return display
.getSystemImage(SWT
.ICON_INFORMATION
);
256 return new Image(display
, iconData
);
261 private static GridLayout
noSpaceGridLayout(GridLayout layout
) {
262 layout
.horizontalSpacing
= 0;
263 layout
.verticalSpacing
= 0;
264 layout
.marginWidth
= 0;
265 layout
.marginHeight
= 0;
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");
279 boolean fullscreen
= options
.contains("--fullscreen");
280 boolean stacking
= options
.contains("--stacking");
282 MiniDesktopManager desktopManager
= new MiniDesktopManager(fullscreen
, stacking
);
283 desktopManager
.init();
284 desktopManager
.run();
285 desktopManager
.dispose();
291 private CTabItem tabItem
;
293 public AppContext(Shell shell
) {
297 public AppContext(CTabItem tabItem
) {
298 this.tabItem
= tabItem
;
301 Composite
getAppParent() {
305 return (Composite
) tabItem
.getControl();
306 throw new IllegalStateException();