First working mini desktop manager.
authorMathieu Baudier <mbaudier@argeo.org>
Sun, 19 Apr 2020 05:46:24 +0000 (07:46 +0200)
committerMathieu Baudier <mbaudier@argeo.org>
Sun, 19 Apr 2020 05:46:24 +0000 (07:46 +0200)
rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/CmsDesktopManager.java [deleted file]
rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/DesktopLayer.java [deleted file]
rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniBrowser.java
rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniDesktopLayer.java [new file with mode: 0644]
rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniDesktopManager.java [new file with mode: 0644]
rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniExplorer.java
rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniTerminal.java

diff --git a/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/CmsDesktopManager.java b/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/CmsDesktopManager.java
deleted file mode 100644 (file)
index 737fdef..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-package org.argeo.cms.desktop;
-
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Point;
-import org.eclipse.swt.graphics.Rectangle;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Shell;
-import org.eclipse.swt.widgets.ToolBar;
-import org.eclipse.swt.widgets.ToolItem;
-
-public class CmsDesktopManager {
-       private Display display;
-
-       private Shell rootShell;
-       private Shell toolBarShell;
-
-       public void init() {
-               display = Display.getCurrent();
-               if (display != null)
-                       throw new IllegalStateException("Already a display " + display);
-               display = new Display();
-
-               int toolBarSize = 48;
-
-               if (isFullScreen()) {
-                       rootShell = new Shell(display, SWT.NO_TRIM);
-                       // rootShell.setMaximized(true);
-                       rootShell.setFullScreen(true);
-                       Rectangle bounds = display.getBounds();
-
-                       rootShell.setSize(bounds.width, bounds.height);
-//                     Point realSize = rootShell.getSize();
-//                     rootShell.setBounds(bounds);
-//                     Rectangle realBounds = rootShell.getBounds();
-               } else {
-                       rootShell = new Shell(display, SWT.SHELL_TRIM);
-                       Rectangle shellArea = rootShell.computeTrim(200, 200, 800, 480);
-                       rootShell.setSize(shellArea.width, shellArea.height);
-               }
-
-               rootShell.setLayout(new GridLayout(2, false));
-               Composite toolBarArea = new Composite(rootShell, SWT.NONE);
-               toolBarArea.setLayoutData(new GridData(toolBarSize, rootShell.getSize().y));
-
-               ToolBar toolBar;
-               if (isFullScreen()) {
-                       toolBarShell = new Shell(rootShell, SWT.NO_TRIM | SWT.ON_TOP);
-                       toolBar = new ToolBar(toolBarShell, SWT.VERTICAL | SWT.FLAT | SWT.BORDER);
-                       createDock(toolBar);
-                       toolBarShell.pack();
-                       toolBarArea.setLayoutData(new GridData(toolBar.getSize().x, toolBar.getSize().y));
-               } else {
-                       toolBar = new ToolBar(toolBarArea, SWT.VERTICAL | SWT.FLAT | SWT.BORDER);
-                       createDock(toolBar);
-                       toolBarArea.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
-               }
-
-               Composite backgroundArea = new Composite(rootShell, SWT.NONE);
-               backgroundArea.setLayout(new GridLayout(6, true));
-               DesktopLayer desktopLayer = new DesktopLayer();
-               desktopLayer.init(backgroundArea);
-               rootShell.open();
-               // rootShell.layout(true, true);
-
-               if (toolBarShell != null) {
-                       toolBarShell.setLocation(new Point(0, 0));
-                       toolBarShell.open();
-               }
-       }
-
-       protected void createDock(ToolBar toolBar) {
-
-               // toolBar.setLocation(clientArea.x, clientArea.y);
-
-               ToolItem closeI = new ToolItem(toolBar, SWT.PUSH);
-               closeI.setImage(display.getSystemImage(SWT.ICON_ERROR));
-               closeI.setToolTipText("Close");
-               closeI.addSelectionListener(new SelectionAdapter() {
-
-                       @Override
-                       public void widgetSelected(SelectionEvent e) {
-                               rootShell.dispose();
-                       }
-
-               });
-
-               ToolItem searchI = new ToolItem(toolBar, SWT.PUSH);
-               searchI.setImage(display.getSystemImage(SWT.ICON_QUESTION));
-               searchI.setToolTipText("Search");
-               searchI.addSelectionListener(new SelectionAdapter() {
-
-                       @Override
-                       public void widgetSelected(SelectionEvent e) {
-                               // rootShell.dispose();
-                       }
-
-               });
-               // toolBar.setSize(48, toolBar.getSize().y);
-               toolBar.pack();
-       }
-
-       public void run() {
-               while (!rootShell.isDisposed()) {
-                       if (!display.readAndDispatch())
-                               display.sleep();
-               }
-       }
-
-       public void dispose() {
-               if (!rootShell.isDisposed())
-                       rootShell.dispose();
-       }
-
-       protected boolean isFullScreen() {
-               return true;
-       }
-
-       public static void main(String[] args) {
-               CmsDesktopManager desktopManager = new CmsDesktopManager();
-               desktopManager.init();
-               // Runtime.getRuntime().addShutdownHook(new Thread(() ->
-               // desktopManager.dispose(), "Dispose desktop manager"));
-               desktopManager.run();
-               desktopManager.dispose();
-       }
-
-}
diff --git a/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/DesktopLayer.java b/rcp/org.argeo.cms.desktop/src/org/argeo/cms/desktop/DesktopLayer.java
deleted file mode 100644 (file)
index 0565e73..0000000
+++ /dev/null
@@ -1,96 +0,0 @@
-package org.argeo.cms.desktop;
-
-import java.io.IOException;
-import java.nio.file.DirectoryStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-
-import org.apache.commons.io.FilenameUtils;
-import org.eclipse.swt.SWT;
-import org.eclipse.swt.events.SelectionAdapter;
-import org.eclipse.swt.events.SelectionEvent;
-import org.eclipse.swt.graphics.Image;
-import org.eclipse.swt.graphics.ImageData;
-import org.eclipse.swt.layout.GridData;
-import org.eclipse.swt.layout.GridLayout;
-import org.eclipse.swt.program.Program;
-import org.eclipse.swt.widgets.Button;
-import org.eclipse.swt.widgets.Composite;
-import org.eclipse.swt.widgets.Control;
-import org.eclipse.swt.widgets.Display;
-import org.eclipse.swt.widgets.Label;
-
-public class DesktopLayer {
-       // TODO make it configurable
-       private Path desktopDir = Paths.get(System.getProperty("user.home"), "tmp");
-
-       public void init(Composite parentShell) {
-//             Decorations shell = new Decorations(parentShell, SWT.CLOSE);
-//             shell.setLayoutData(new GridData(GridData.FILL_BOTH));
-               createUi(parentShell, desktopDir);
-               // shell.open();
-       }
-
-       public Control createUi(Composite parent, Path context) {
-               // parent.setLayout(new FillLayout());
-               try {
-                       DirectoryStream<Path> ds = Files.newDirectoryStream(context);
-                       ds.forEach((path) -> createIcon(parent, path));
-               } catch (IOException e) {
-                       // TODO Auto-generated catch block
-                       e.printStackTrace();
-               }
-               return parent;
-
-       }
-
-       protected void createIcon(Composite parent, Path path) {
-               String ext = FilenameUtils.getExtension(path.getFileName().toString());
-               Program program = Program.findProgram(ext);
-               if (program == null) {
-                       createDefaultIcon(parent, path);
-                       return;
-               }
-
-               Display display = parent.getDisplay();
-               ImageData iconData = program.getImageData();
-
-               Image iconImage;
-               if (iconData == null) {
-                       iconImage = display.getSystemImage(SWT.ICON_INFORMATION);
-                       iconData = iconImage.getImageData();
-               } else {
-                       iconImage = new Image(display, iconData);
-               }
-
-               Composite icon = new Composite(parent, SWT.NONE);
-               icon.setLayoutData(new GridData(48, 72));
-               icon.setLayout(new GridLayout());
-               // Button
-               Button iconB = new Button(icon, SWT.FLAT);
-               iconB.setImage(iconImage);
-               // iconB.setLayoutData(new GridData(iconData.width, iconData.height));
-               iconB.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
-               iconB.addSelectionListener(new SelectionAdapter() {
-
-                       @Override
-                       public void widgetSelected(SelectionEvent e) {
-                               program.execute(path.toString());
-                       }
-
-               });
-               // Label
-               Label iconL = new Label(icon, SWT.WRAP);
-               iconL.setText(path.getFileName().toString());
-               iconL.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
-       }
-
-       protected void createDefaultIcon(Composite parent, Path path) {
-               Composite icon = new Composite(parent, SWT.NONE);
-               icon.setLayout(new GridLayout());
-               Label iconL = new Label(icon, SWT.NONE);
-               iconL.setText(path.getFileName().toString());
-               iconL.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));
-       }
-}
index 4b41207fc646a28178e4266c4bdd1e617ea77254..d0ac4ee368facf84d1080c88ca675813d5ab8cc4 100644 (file)
@@ -1,8 +1,5 @@
 package org.argeo.swt.desktop;
 
-import java.util.Observable;
-import java.util.function.BiFunction;
-
 import org.eclipse.swt.SWT;
 import org.eclipse.swt.browser.Browser;
 import org.eclipse.swt.browser.LocationAdapter;
@@ -20,99 +17,87 @@ import org.eclipse.swt.widgets.Shell;
 import org.eclipse.swt.widgets.Text;
 
 /** A minimalistic web browser based on {@link Browser}. */
-public class MiniBrowser implements BiFunction<Composite, MiniBrowser.Context, Control> {
-       @Override
-       public Control apply(Composite parent, MiniBrowser.Context context) {
-               parent.setLayout(new GridLayout());
-               Control toolBar = createToolBar(parent, context);
+public class MiniBrowser {
+       private Browser browser;
+       private Text addressT;
+
+       public MiniBrowser(Composite composite, String url) {
+               createUi(composite);
+               setUrl(url);
+       }
+
+       public Control createUi(Composite parent) {
+               parent.setLayout(noSpaceGridLayout(new GridLayout()));
+               Control toolBar = createToolBar(parent);
                toolBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
-               Control body = createBody(parent, context);
+               Control body = createBody(parent);
                body.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
                return body;
        }
 
-       public Control createToolBar(Composite parent, MiniBrowser.Context context) {
+       public Control createToolBar(Composite parent) {
                Composite toolBar = new Composite(parent, SWT.NONE);
                toolBar.setLayout(new FillLayout());
-               Text addressT = new Text(toolBar, SWT.SINGLE | SWT.BORDER);
+               addressT = new Text(toolBar, SWT.SINGLE);
                addressT.addSelectionListener(new SelectionAdapter() {
 
                        @Override
                        public void widgetDefaultSelected(SelectionEvent e) {
-                               String url = addressT.getText().trim();
-                               context.setUrl(url);
+                               setUrl(addressT.getText().trim());
                        }
                });
-               context.addObserver((o, v) -> addressT.setText(((Context) o).getUrl().toString()));
                return toolBar;
        }
 
-       public Control createBody(Composite parent, MiniBrowser.Context context) {
-               Browser browser = new Browser(parent, SWT.NONE);
+       public Control createBody(Composite parent) {
+               browser = new Browser(parent, SWT.NONE);
                browser.addLocationListener(new LocationAdapter() {
-                       @Override
-                       public void changing(LocationEvent event) {
-//                             if (event.top && !context.getUrl().equals(event.location))
-//                                     context.setUrl(event.location);
-                       }
-
                        @Override
                        public void changed(LocationEvent event) {
-                               if (event.top && !context.getUrl().equals(event.location))
-                                       context.setUrl(event.location);
+                               addressT.setText(event.location);
                        }
 
                });
-               browser.addTitleListener(e -> context.setTitle(e.title));
-               context.addObserver((o, v) -> {
-                       String url = ((Context) o).getUrl();
-                       if (url != null && !url.equals(browser.getUrl()))
-                               browser.setUrl(url.toString());
-               });
+               browser.addTitleListener(e -> titleChanged(e.title));
                return browser;
        }
 
-       /** The observable context of this web browser. */
-       public static class Context extends Observable {
-               private String url;
-               private String title = "";
-
-               public void setUrl(String url) {
-                       this.url = url;
-                       System.out.println(url);
-                       setChanged();
-                       notifyObservers(url);
-               }
-
-               public String getUrl() {
-                       return url;
-               }
+       void setUrl(String url) {
+               if (browser != null && url != null && !url.equals(browser.getUrl()))
+                       browser.setUrl(url.toString());
+       }
 
-               public String getTitle() {
-                       return title;
-               }
+       /** Called when URL changed; to be overridden, does nothing by default. */
+       protected void urlChanged(String url) {
+       }
 
-               public void setTitle(String title) {
-                       this.title = title;
-                       setChanged();
-                       notifyObservers(title);
-               }
+       /** Called when title changed; to be overridden, does nothing by default. */
+       protected void titleChanged(String title) {
+       }
 
+       private static GridLayout noSpaceGridLayout(GridLayout layout) {
+               layout.horizontalSpacing = 0;
+               layout.verticalSpacing = 0;
+               layout.marginWidth = 0;
+               layout.marginHeight = 0;
+               return layout;
        }
 
        public static void main(String[] args) {
                Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent();
                Shell shell = new Shell(display, SWT.SHELL_TRIM);
 
-               MiniBrowser miniBrowser = new MiniBrowser();
-               MiniBrowser.Context context = new MiniBrowser.Context();
-               miniBrowser.apply(shell, context);
-               context.addObserver((o, v) -> shell.setText(((Context) o).getTitle()));
-               String url = args.length > 0 ? args[0] : "http://www.argeo.org";
-               context.setUrl(url);
+               String url = args.length > 0 ? args[0] : "https://duckduckgo.com/";
+               new MiniBrowser(shell, url) {
 
+                       @Override
+                       protected void titleChanged(String title) {
+                               shell.setText(title);
+                       }
+               };
                shell.open();
                shell.setSize(new Point(800, 480));
+
                while (!shell.isDisposed()) {
                        if (!display.readAndDispatch())
                                display.sleep();
diff --git a/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniDesktopLayer.java b/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniDesktopLayer.java
new file mode 100644 (file)
index 0000000..f53e6a3
--- /dev/null
@@ -0,0 +1,83 @@
+package org.argeo.swt.desktop;
+
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.layout.RowData;
+import org.eclipse.swt.layout.RowLayout;
+import org.eclipse.swt.program.Program;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+
+/** Implementation of an active desktop with icons. */
+public class MiniDesktopLayer {
+       public void init(Composite parent, Path context) {
+               parent.setLayout(new RowLayout());
+               try {
+                       DirectoryStream<Path> ds = Files.newDirectoryStream(context);
+                       ds.forEach((path) -> createIcon(parent, path));
+               } catch (IOException e) {
+                       e.printStackTrace();
+               }
+       }
+
+       protected void createIcon(Composite parent, Path path) {
+               String fileName = path.getFileName().toString();
+               String ext = fileName.substring(fileName.lastIndexOf('.') + 1);
+               Program program = Program.findProgram(ext);
+               if (program == null) {
+                       createDefaultIcon(parent, path);
+                       return;
+               }
+
+               Display display = parent.getDisplay();
+               ImageData iconData = program.getImageData();
+
+               Image iconImage;
+               if (iconData == null) {
+                       iconImage = null;
+               } else {
+                       iconImage = new Image(display, iconData);
+               }
+
+               Composite icon = new Composite(parent, SWT.BORDER);
+               icon.setLayoutData(new RowData(48, 72));
+               icon.setLayout(new GridLayout());
+               // Button
+               Button iconB = new Button(icon, SWT.FLAT);
+               iconB.setImage(iconImage);
+               // iconB.setLayoutData(new GridData(iconData.width, iconData.height));
+               iconB.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
+               iconB.addSelectionListener(new SelectionAdapter() {
+
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               program.execute(path.toString());
+                       }
+
+               });
+               // Label
+               Label iconL = new Label(icon, SWT.WRAP);
+               iconL.setText(path.getFileName().toString());
+               iconL.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
+       }
+
+       protected void createDefaultIcon(Composite parent, Path path) {
+               Composite icon = new Composite(parent, SWT.NONE);
+               icon.setLayout(new GridLayout());
+               Label iconL = new Label(icon, SWT.NONE);
+               iconL.setText(path.getFileName().toString());
+               iconL.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, true));
+       }
+}
diff --git a/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniDesktopManager.java b/rcp/org.argeo.eclipse.ui.rcp/src/org/argeo/swt/desktop/MiniDesktopManager.java
new file mode 100644 (file)
index 0000000..0973f70
--- /dev/null
@@ -0,0 +1,313 @@
+package org.argeo.swt.desktop;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.CTabFolder;
+import org.eclipse.swt.custom.CTabItem;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.program.Program;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.ToolBar;
+import org.eclipse.swt.widgets.ToolItem;
+
+/** A very minimalistic desktop manager based on Java and Eclipse SWT. */
+public class MiniDesktopManager {
+       private Display display;
+
+       private Shell rootShell;
+       private Shell toolBarShell;
+       private CTabFolder tabFolder;
+       private int maxTabTitleLength = 16;
+
+       private final boolean fullscreen;
+       private final boolean stacking;
+
+       public MiniDesktopManager(boolean fullscreen, boolean stacking) {
+               this.fullscreen = fullscreen;
+               this.stacking = stacking;
+       }
+
+       public void init() {
+               display = Display.getCurrent();
+               if (display != null)
+                       throw new IllegalStateException("Already a display " + display);
+               display = new Display();
+
+               int toolBarSize = 48;
+
+               if (isFullscreen()) {
+                       rootShell = new Shell(display, SWT.NO_TRIM);
+                       rootShell.setFullScreen(true);
+                       Rectangle bounds = display.getBounds();
+
+                       rootShell.setSize(bounds.width, bounds.height);
+               } else {
+                       rootShell = new Shell(display, SWT.SHELL_TRIM);
+                       Rectangle shellArea = rootShell.computeTrim(200, 200, 800, 480);
+                       rootShell.setSize(shellArea.width, shellArea.height);
+               }
+
+               rootShell.setLayout(noSpaceGridLayout(new GridLayout(2, false)));
+               Composite toolBarArea = new Composite(rootShell, SWT.NONE);
+               toolBarArea.setLayoutData(new GridData(toolBarSize, rootShell.getSize().y));
+
+               ToolBar toolBar;
+               if (isFullscreen()) {
+                       toolBarShell = new Shell(rootShell, SWT.NO_TRIM | SWT.ON_TOP);
+                       toolBar = new ToolBar(toolBarShell, SWT.VERTICAL | SWT.FLAT | SWT.BORDER);
+                       createDock(toolBar);
+                       toolBarShell.pack();
+                       toolBarArea.setLayoutData(new GridData(toolBar.getSize().x, toolBar.getSize().y));
+               } else {
+                       toolBar = new ToolBar(toolBarArea, SWT.VERTICAL | SWT.FLAT | SWT.BORDER);
+                       createDock(toolBar);
+                       toolBarArea.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+               }
+
+               if (isStacking()) {
+                       tabFolder = new CTabFolder(rootShell, SWT.MULTI);
+                       tabFolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+                       // background
+                       Control background = createBackground(tabFolder);
+                       CTabItem noCloseItem = new CTabItem(tabFolder, SWT.NONE);
+                       noCloseItem.setText("Home");
+                       noCloseItem.setControl(background);
+               } else {
+                       createBackground(rootShell);
+               }
+
+               rootShell.open();
+               // rootShell.layout(true, true);
+
+               if (toolBarShell != null) {
+                       toolBarShell.setLocation(new Point(0, 0));
+                       toolBarShell.open();
+               }
+       }
+
+       protected void createDock(ToolBar toolBar) {
+               // Terminal
+               addToolItem(toolBar, display.getSystemImage(SWT.ICON_INFORMATION), "Terminal", () -> {
+                       String url = System.getProperty("user.home");
+                       AppContext appContext = createAppParent();
+                       new MiniTerminal(appContext.getAppParent(), url) {
+
+                               @Override
+                               protected void exitCalled() {
+                                       if (appContext.shell != null)
+                                               appContext.shell.dispose();
+                                       if (appContext.tabItem != null)
+                                               appContext.tabItem.dispose();
+                               }
+                       };
+                       String title;
+                       try {
+                               title = System.getProperty("user.name") + "@" + InetAddress.getLocalHost().getHostName();
+                       } catch (UnknownHostException e) {
+                               title = System.getProperty("user.name") + "@localhost";
+                       }
+                       if (appContext.shell != null)
+                               appContext.shell.setText(title);
+                       if (appContext.tabItem != null) {
+                               appContext.tabItem.setText(tabTitle(title));
+                               appContext.tabItem.setToolTipText(title);
+                       }
+                       openApp(appContext);
+               });
+
+               // Web browser
+               addToolItem(toolBar, display.getSystemImage(SWT.ICON_QUESTION), "Browser", () -> {
+                       String url = "https://duckduckgo.com/";
+                       AppContext appContext = createAppParent();
+                       new MiniBrowser(appContext.getAppParent(), url) {
+                               @Override
+                               protected void titleChanged(String title) {
+                                       if (appContext.shell != null)
+                                               appContext.shell.setText(title);
+                                       if (appContext.tabItem != null) {
+                                               appContext.tabItem.setText(tabTitle(title));
+                                               appContext.tabItem.setToolTipText(title);
+                                       }
+                               }
+                       };
+                       openApp(appContext);
+               });
+
+               // File explorer
+               addToolItem(toolBar, display.getSystemImage(SWT.ICON_WARNING), "Explorer", () -> {
+                       String url = System.getProperty("user.home");
+                       AppContext appContext = createAppParent();
+                       new MiniExplorer(appContext.getAppParent(), url) {
+
+                               @Override
+                               protected void pathChanged(Path path) {
+                                       if (appContext.shell != null)
+                                               appContext.shell.setText(path.toString());
+                                       if (appContext.tabItem != null) {
+                                               appContext.tabItem.setText(path.getFileName().toString());
+                                               appContext.tabItem.setToolTipText(path.toString());
+                                       }
+                               }
+                       };
+                       openApp(appContext);
+               });
+
+               // Exit
+               addToolItem(toolBar, display.getSystemImage(SWT.ICON_ERROR), "Exit", () -> rootShell.dispose());
+
+               toolBar.pack();
+       }
+
+       protected String tabTitle(String title) {
+               return title.length() > maxTabTitleLength ? title.substring(0, maxTabTitleLength) : title;
+       }
+
+       protected void addToolItem(ToolBar toolBar, Image icon, String name, Runnable action) {
+               ToolItem searchI = new ToolItem(toolBar, SWT.PUSH);
+               searchI.setImage(icon);
+               searchI.setToolTipText(name);
+               searchI.addSelectionListener(new SelectionAdapter() {
+
+                       @Override
+                       public void widgetSelected(SelectionEvent e) {
+                               action.run();
+                       }
+
+               });
+       }
+
+       protected AppContext createAppParent() {
+               if (isStacking()) {
+                       Composite appParent = new Composite(tabFolder, SWT.NONE);
+                       appParent.setLayout(noSpaceGridLayout(new GridLayout()));
+                       CTabItem item = new CTabItem(tabFolder, SWT.CLOSE);
+                       item.setControl(appParent);
+                       return new AppContext(item);
+               } else {
+                       Shell shell = new Shell(rootShell, SWT.SHELL_TRIM);
+                       return new AppContext(shell);
+               }
+       }
+
+       protected void openApp(AppContext appContext) {
+               if (appContext.shell != null) {
+                       Shell shell = (Shell) appContext.shell;
+                       shell.open();
+                       shell.setSize(new Point(800, 480));
+               }
+               if (appContext.tabItem != null) {
+                       tabFolder.setSelection(appContext.tabItem);
+               }
+       }
+
+       protected Control createBackground(Composite parent) {
+               Composite backgroundArea = new Composite(parent, SWT.NONE);
+               backgroundArea.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+               initBackground(backgroundArea);
+               return backgroundArea;
+       }
+
+       protected void initBackground(Composite backgroundArea) {
+               MiniDesktopLayer desktopLayer = new MiniDesktopLayer();
+               desktopLayer.init(backgroundArea, Paths.get(System.getProperty("user.dir")));
+       }
+
+       public void run() {
+               while (!rootShell.isDisposed()) {
+                       if (!display.readAndDispatch())
+                               display.sleep();
+               }
+       }
+
+       public void dispose() {
+               if (!rootShell.isDisposed())
+                       rootShell.dispose();
+       }
+
+       protected boolean isFullscreen() {
+               return fullscreen;
+       }
+
+       protected boolean isStacking() {
+               return stacking;
+       }
+
+       protected Image getIconForExt(String ext) {
+               Program program = Program.findProgram(ext);
+               if (program == null)
+                       return display.getSystemImage(SWT.ICON_INFORMATION);
+
+               ImageData iconData = program.getImageData();
+               if (iconData == null) {
+                       return display.getSystemImage(SWT.ICON_INFORMATION);
+               } else {
+                       return new Image(display, iconData);
+               }
+
+       }
+
+       private static GridLayout noSpaceGridLayout(GridLayout layout) {
+               layout.horizontalSpacing = 0;
+               layout.verticalSpacing = 0;
+               layout.marginWidth = 0;
+               layout.marginHeight = 0;
+               return layout;
+       }
+
+       public static void main(String[] args) {
+               List<String> options = Arrays.asList(args);
+               if (options.contains("--help")) {
+                       System.out.println("Usage: java " + MiniDesktopManager.class.getName().replace('.', '/') + " [OPTION]");
+                       System.out.println("A minimalistic desktop manager based on Java and Eclipse SWT.");
+                       System.out.println("  --fullscreen : take control of the whole screen (default is to run in a window)");
+                       System.out.println("  --stacking   : open apps as tabs (default is to create new windows)");
+                       System.out.println("  --help       : print this help and exit");
+                       System.exit(1);
+               }
+               boolean fullscreen = options.contains("--fullscreen");
+               boolean stacking = options.contains("--stacking");
+
+               MiniDesktopManager desktopManager = new MiniDesktopManager(fullscreen, stacking);
+               desktopManager.init();
+               desktopManager.run();
+               desktopManager.dispose();
+               System.exit(0);
+       }
+
+       class AppContext {
+               private Shell shell;
+               private CTabItem tabItem;
+
+               public AppContext(Shell shell) {
+                       this.shell = shell;
+               }
+
+               public AppContext(CTabItem tabItem) {
+                       this.tabItem = tabItem;
+               }
+
+               Composite getAppParent() {
+                       if (shell != null)
+                               return shell;
+                       if (tabItem != null)
+                               return (Composite) tabItem.getControl();
+                       throw new IllegalStateException();
+               }
+       }
+}
index b88dbff31eafa3001debc13794d4825438efa0f6..6f6a782fbabc15290a44b0239acfa53c42bc2321 100644 (file)
@@ -24,20 +24,24 @@ import org.eclipse.swt.widgets.TableItem;
 import org.eclipse.swt.widgets.Text;
 
 public class MiniExplorer {
-       private Path url;
+       private Path path;
        private Text addressT;
        private Table browser;
 
        private boolean showHidden = false;
 
-       public MiniExplorer(Composite parent, int style) {
-               parent.setLayout(new GridLayout());
+       public MiniExplorer(Composite parent, String url) {
+               this(parent);
+               setUrl(url);
+       }
+
+       public MiniExplorer(Composite parent) {
+               parent.setLayout(noSpaceGridLayout(new GridLayout()));
 
                Composite toolBar = new Composite(parent, SWT.NONE);
                toolBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
                toolBar.setLayout(new FillLayout());
-               addressT = new Text(toolBar, SWT.SINGLE | SWT.BORDER);
-               // addressT.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+               addressT = new Text(toolBar, SWT.SINGLE);
                addressT.addSelectionListener(new SelectionAdapter() {
 
                        @Override
@@ -45,20 +49,25 @@ public class MiniExplorer {
                                setUrl(addressT.getText().trim());
                        }
                });
-               browser = createTable(parent, this.url);
+               browser = createTable(parent, this.path);
 
        }
 
-       public void setUrl(Path url) {
-               this.url = url;
+       public void setPath(Path url) {
+               this.path = url;
                if (addressT != null)
                        addressT.setText(url.toString());
                if (browser != null) {
                        Composite parent = browser.getParent();
                        browser.dispose();
-                       browser = createTable(parent, this.url);
+                       browser = createTable(parent, this.path);
                        parent.layout(true, true);
                }
+               pathChanged(url);
+       }
+
+       protected void pathChanged(Path path) {
+
        }
 
        protected Table createTable(Composite parent, Path path) {
@@ -72,7 +81,7 @@ public class MiniExplorer {
                                TableItem item = table.getItem(pt);
                                Path path = (Path) item.getData();
                                if (Files.isDirectory(path)) {
-                                       setUrl(path);
+                                       setPath(path);
                                } else {
                                        Program.launch(path.toString());
                                }
@@ -88,14 +97,14 @@ public class MiniExplorer {
 
                        try {
                                // directories
-                               DirectoryStream<Path> ds = Files.newDirectoryStream(url, p -> Files.isDirectory(p) && isShown(p));
+                               DirectoryStream<Path> ds = Files.newDirectoryStream(path, p -> Files.isDirectory(p) && isShown(p));
                                ds.forEach(p -> {
                                        TableItem ti = new TableItem(table, SWT.NONE);
                                        ti.setText(p.getFileName().toString() + "/");
                                        ti.setData(p);
                                });
                                // files
-                               ds = Files.newDirectoryStream(url, p -> !Files.isDirectory(p) && isShown(p));
+                               ds = Files.newDirectoryStream(path, p -> !Files.isDirectory(p) && isShown(p));
                                ds.forEach(p -> {
                                        TableItem ti = new TableItem(table, SWT.NONE);
                                        ti.setText(p.getFileName().toString());
@@ -120,16 +129,30 @@ public class MiniExplorer {
        }
 
        public void setUrl(String url) {
-               setUrl(Paths.get(url));
+               setPath(Paths.get(url));
+       }
+
+       private static GridLayout noSpaceGridLayout(GridLayout layout) {
+               layout.horizontalSpacing = 0;
+               layout.verticalSpacing = 0;
+               layout.marginWidth = 0;
+               layout.marginHeight = 0;
+               return layout;
        }
 
        public static void main(String[] args) {
                Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent();
                Shell shell = new Shell(display, SWT.SHELL_TRIM);
 
-               MiniExplorer miniBrowser = new MiniExplorer(shell, SWT.NONE);
                String url = args.length > 0 ? args[0] : System.getProperty("user.home");
-               miniBrowser.setUrl(url);
+               new MiniExplorer(shell, url) {
+
+                       @Override
+                       protected void pathChanged(Path path) {
+                               shell.setText(path.toString());
+                       }
+
+               };
 
                shell.open();
                shell.setSize(new Point(800, 480));
index cacf55aaa76e3186fd85b093827a4b463569d94e..0c43e3bf0df5e2b5b2e52641749396d5b369bb4d 100644 (file)
@@ -61,7 +61,12 @@ public class MiniTerminal implements KeyListener, PaintListener {
 
        private Thread readOut;
 
-       public MiniTerminal(Composite parent, int style) {
+       public MiniTerminal(Composite parent, String url) {
+               this(parent);
+               setPath(url);
+       }
+
+       public MiniTerminal(Composite parent) {
                charset = StandardCharsets.UTF_8;
 
                Display display = parent.getDisplay();
@@ -199,7 +204,7 @@ public class MiniTerminal implements KeyListener, PaintListener {
                        // exit
                        else if (args.get(0).equals("exit")) {
                                println("logout");
-                               area.getShell().dispose();
+                               exitCalled();
                                return;
                        }
 
@@ -210,7 +215,7 @@ public class MiniTerminal implements KeyListener, PaintListener {
                        process = pb.start();
 
                        stdIn = process.getOutputStream();
-                       readOut = new Thread("MinitTerminal read out") {
+                       readOut = new Thread("MiniTerminal read out") {
                                @Override
                                public void run() {
                                        running = true;
@@ -300,6 +305,10 @@ public class MiniTerminal implements KeyListener, PaintListener {
 //             area.setCaret(caret);
        }
 
+       protected void exitCalled() {
+
+       }
+
        public void setPath(String path) {
                this.currentDir = Paths.get(path);
        }
@@ -312,9 +321,15 @@ public class MiniTerminal implements KeyListener, PaintListener {
                Display display = Display.getCurrent() == null ? new Display() : Display.getCurrent();
                Shell shell = new Shell(display, SWT.SHELL_TRIM);
 
-               MiniTerminal miniBrowser = new MiniTerminal(shell, SWT.NONE);
                String url = args.length > 0 ? args[0] : System.getProperty("user.home");
-               miniBrowser.setPath(url);
+               new MiniTerminal(shell, url) {
+
+                       @Override
+                       protected void exitCalled() {
+                               shell.dispose();
+                               System.exit(0);
+                       }
+               };
 
                shell.open();
                shell.setSize(new Point(800, 480));