]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.workbench/src/org/simantics/workbench/splashHandlers/InteractiveSplashHandler.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.workbench / src / org / simantics / workbench / splashHandlers / InteractiveSplashHandler.java
diff --git a/bundles/org.simantics.workbench/src/org/simantics/workbench/splashHandlers/InteractiveSplashHandler.java b/bundles/org.simantics.workbench/src/org/simantics/workbench/splashHandlers/InteractiveSplashHandler.java
new file mode 100644 (file)
index 0000000..09b2a6f
--- /dev/null
@@ -0,0 +1,598 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 Association for Decentralized Information Management\r
+ * in Industry THTH ry.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+\r
+package org.simantics.workbench.splashHandlers;\r
+\r
+import java.util.Timer;\r
+import java.util.TimerTask;\r
+\r
+import org.eclipse.jface.dialogs.MessageDialog;\r
+import org.eclipse.jface.resource.ImageDescriptor;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.events.SelectionAdapter;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.graphics.GC;\r
+import org.eclipse.swt.graphics.Image;\r
+import org.eclipse.swt.graphics.ImageData;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.graphics.Rectangle;\r
+import org.eclipse.swt.graphics.Region;\r
+import org.eclipse.swt.layout.FillLayout;\r
+import org.eclipse.swt.layout.GridData;\r
+import org.eclipse.swt.layout.GridLayout;\r
+import org.eclipse.swt.widgets.Button;\r
+import org.eclipse.swt.widgets.Canvas;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Event;\r
+import org.eclipse.swt.widgets.Label;\r
+import org.eclipse.swt.widgets.Listener;\r
+import org.eclipse.swt.widgets.Shell;\r
+import org.eclipse.swt.widgets.Text;\r
+import org.eclipse.ui.splash.AbstractSplashHandler;\r
+import org.simantics.workbench.internal.Activator;\r
+\r
+\r
+/**\r
+ * @since 3.3\r
+ */\r
+@SuppressWarnings("unused")\r
+public class InteractiveSplashHandler extends AbstractSplashHandler {\r
+\r
+    private static final String SPLASH_IMAGE              = "simantics.png";\r
+\r
+    private final static int    FADE_TIME_MS              = 250;\r
+\r
+    private final static int    F_LABEL_HORIZONTAL_INDENT = 10;\r
+\r
+    private final static int    F_BUTTON_WIDTH_HINT       = 80;\r
+\r
+    private final static int    F_TEXT_WIDTH_HINT         = 175;\r
+\r
+    private final static int    F_COLUMN_COUNT            = 3;\r
+\r
+    private Composite           fCompositeLogin;\r
+\r
+    private Text                fTextUsername;\r
+\r
+    private Text                fTextPassword;\r
+\r
+    private Button              fButtonOK;\r
+\r
+    private Button              fButtonCancel;\r
+\r
+    private boolean             fAuthenticated;\r
+\r
+    private Image               splashImage;\r
+\r
+    private Image               currentBackground;\r
+\r
+    private long                fadeStartTime             = 0;\r
+\r
+    private boolean             fadeComplete              = false;\r
+\r
+    private Timer               watchdogTimer             = new Timer("splash-watchdog");\r
+\r
+    enum State {\r
+        INIT,\r
+        OK,\r
+        DIRTY,\r
+        UPDATED,\r
+        ;\r
+        State ok() {\r
+//            System.out.println(this + " -> " + OK);\r
+            return OK;\r
+        }\r
+        State dirty() {\r
+//            System.out.println(this + " -> " + DIRTY);\r
+            return DIRTY;\r
+        }\r
+        State updated() {\r
+//            if (this != DIRTY) {\r
+//                System.err.println("ERROR: transition from " + this + " to " + DIRTY);\r
+//            }\r
+//            System.out.println(this + " -> " + UPDATED);\r
+            return UPDATED;\r
+        }\r
+    }\r
+\r
+    private State state = State.INIT;\r
+\r
+    /**\r
+     * \r
+     */\r
+    public InteractiveSplashHandler() {\r
+        fCompositeLogin = null;\r
+        fTextUsername = null;\r
+        fTextPassword = null;\r
+        fButtonOK = null;\r
+        fButtonCancel = null;\r
+        fAuthenticated = false;\r
+    }\r
+\r
+    /**\r
+     * Takes a screenshot of the desktop and blends the splash screen PNG image\r
+     * on top of it. The blended result is then set as currentBackground.\r
+     * \r
+     * @param splash\r
+     */\r
+    private void updateBackground1(Shell splash) {\r
+//        System.out.println("Screenshotting");\r
+        Point size = splash.getSize();\r
+        Point pt = splash.getLocation();\r
+        //System.out.println("location: " + pt + ", size: " + size);\r
+\r
+        splash.setRegion(new Region());\r
+\r
+        // Get screenshot into backgroundImage\r
+        Rectangle clientArea = splash.getDisplay().getClientArea();\r
+        //System.out.println("client area: " + clientArea);\r
+        final Image backgroundImage = new Image(splash.getDisplay(), clientArea.width, clientArea.height);\r
+        GC gc = new GC(splash.getDisplay());\r
+        gc.copyArea(backgroundImage, 0, 0);\r
+        gc.dispose();\r
+\r
+        // Combine the splash screen with the background\r
+        final Image newSplashBackground = new Image(splash.getDisplay(), size.x, size.y);\r
+        GC gc2 = new GC(newSplashBackground);\r
+        gc2.drawImage(backgroundImage, pt.x, pt.y, size.x, size.y, 0, 0, size.x, size.y);\r
+        gc2.drawImage(splashImage, 0, 0);\r
+        gc2.dispose();\r
+\r
+        // Screenshot no longer needed\r
+        backgroundImage.dispose();\r
+\r
+        Region r = new Region();\r
+        Rectangle r2 = splashImage.getBounds();\r
+        r.add(r2);\r
+        splash.setRegion(r);\r
+\r
+        // Switch shell background image, dispose the old one.\r
+        Image old = splash.getBackgroundImage();\r
+        splash.setBackgroundImage(newSplashBackground);\r
+        currentBackground = newSplashBackground;\r
+        if (old != null)\r
+            old.dispose();\r
+    }\r
+\r
+    /**\r
+     * Takes a screenshot of the desktop and uses that as the background of the\r
+     * splash as currentBackground.\r
+     * \r
+     * @param splash\r
+     */\r
+    private void updateBackground2(Shell splash) {\r
+        //System.out.println("Screenshotting");\r
+        Point size = splash.getSize();\r
+        Point pt = splash.getLocation();\r
+        //System.out.println("location: " + pt + ", size: " + size);\r
+\r
+        splash.setRegion(new Region());\r
+\r
+        // Get screenshot into backgroundImage\r
+        Rectangle clientArea = splash.getDisplay().getClientArea();\r
+        //System.out.println("client area: " + clientArea);\r
+        final Image backgroundImage = new Image(splash.getDisplay(), clientArea.width, clientArea.height);\r
+        GC gc = new GC(splash.getDisplay());\r
+        gc.copyArea(backgroundImage, 0, 0);\r
+        gc.dispose();\r
+\r
+        // Combine the splash screen with the background\r
+        final Image newSplashBackground = new Image(splash.getDisplay(), size.x, size.y);\r
+        GC gc2 = new GC(newSplashBackground);\r
+        gc2.drawImage(backgroundImage, pt.x, pt.y, size.x, size.y, 0, 0, size.x, size.y);\r
+        gc2.dispose();\r
+\r
+        // Screenshot no longer needed\r
+        backgroundImage.dispose();\r
+\r
+        Region r = new Region();\r
+        Rectangle r2 = newSplashBackground.getBounds();\r
+        r.add(r2);\r
+        splash.setRegion(r);\r
+\r
+        // Switch shell background image, dispose the old one.\r
+        Image old = splash.getBackgroundImage();\r
+        splash.setBackgroundImage(newSplashBackground);\r
+        currentBackground = newSplashBackground;\r
+        if (old != null)\r
+            old.dispose();\r
+    }\r
+\r
+    private void initializeBackground(Shell splash) {\r
+        Point size = splash.getSize();\r
+        Point pt = splash.getLocation();\r
+        //System.out.println("location: " + pt + ", size: " + size);\r
+\r
+        // Combine the splash screen with the background\r
+        Image newSplashBackground = new Image(splash.getDisplay(), size.x, size.y);\r
+        ImageData imgData = newSplashBackground.getImageData();\r
+        imgData.alpha = 0;\r
+\r
+        Region r = new Region();\r
+        Rectangle r2 = splashImage.getBounds();\r
+        Rectangle r3 = new Rectangle(r2.x, r2.y, r2.width, r2.height);\r
+        r.add(r3);\r
+        splash.setRegion(r);\r
+\r
+        // Switch shell background image, dispose the old one.\r
+        splash.setBackgroundImage(newSplashBackground);\r
+        currentBackground = newSplashBackground;\r
+    }\r
+\r
+    @Override\r
+    public void dispose() {\r
+        super.dispose();\r
+\r
+        // Destroy images\r
+        if (splashImage != null)\r
+            splashImage.dispose();\r
+        if (currentBackground != null)\r
+            currentBackground.dispose();\r
+    }\r
+\r
+    /*\r
+     * (non-Javadoc)\r
+     * \r
+     * @see org.eclipse.ui.splash.AbstractSplashHandler#init(org.eclipse.swt.widgets.Shell)\r
+     */\r
+    public void init(final Shell splash) {\r
+\r
+        super.init(splash);\r
+\r
+        ImageDescriptor splashDesc = Activator.getImageDescriptor(SPLASH_IMAGE);\r
+        if (splashDesc == null) {\r
+            // If splash-image is not available, do nothing.\r
+            return;\r
+        }\r
+        splashImage  = splashDesc.createImage();\r
+//        System.out.println("logo bounds: " + i.getBounds());\r
+\r
+        splash.setSize(splashImage.getBounds().width, splashImage.getBounds().height);\r
+//        splash.setRegion(new Region());\r
+\r
+        Point pt = splash.getLocation();\r
+        pt.x -= splashImage.getBounds().width/2;\r
+        pt.y -= splashImage.getBounds().height/2;\r
+        splash.setLocation(pt);\r
+\r
+//        updateSplashImage(splash);\r
+        updateBackground2(splash);\r
+        //initializeSplash(splash);\r
+        state = state.ok();\r
+\r
+//      Configure the shell layout\r
+        configureUISplash();\r
+//      Create UI\r
+        createUI();\r
+//      Create UI listeners\r
+        createUIListeners();\r
+//      Force the splash screen to layout\r
+        splash.layout(true);\r
+//      Keep the splash screen visible and prevent the RCP application from \r
+//      loading until the close button is clicked.\r
+        doEventLoop();\r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void doEventLoop() {\r
+        final Shell splash = getSplash();\r
+//        while (fAuthenticated == false) {\r
+        \r
+        // Make sure that the splash doesn't block program startup when it is\r
+        // hidden.\r
+        watchdogTimer.schedule(new TimerTask() {\r
+            @Override\r
+            public void run() {\r
+                // Terminate the timer and complete the fade.\r
+//                System.out.println("watchdog");\r
+                watchdogTimer.cancel();\r
+                fadeComplete = true;\r
+            }\r
+        }, FADE_TIME_MS + 50);\r
+\r
+        while (!fadeComplete) {\r
+            if (splash.getDisplay().readAndDispatch() == false) {\r
+                // Cannot use Display.sleep because it may not wake up until the\r
+                // window receives events which will not happen if the window is\r
+                // not visible.\r
+//                splash.getDisplay().sleep();\r
+                try {\r
+                    Thread.sleep(5);\r
+                } catch (InterruptedException e) {\r
+                    e.printStackTrace();\r
+                }\r
+            }\r
+        }\r
+        splash.redraw();\r
+        while (splash.getDisplay().readAndDispatch());\r
+\r
+//        System.out.println("ENDING EVENT LOOP");\r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void createUIListeners() {\r
+        // Update the translucency\r
+        /*\r
+        for (int in : new int[] { SWT.Activate, SWT.Deactivate, SWT.Show, SWT.Hide, SWT.Iconify, SWT.Deiconify }) {\r
+            getSplash().addListener(in, new Listener() {\r
+                @Override\r
+                public void handleEvent(Event event) {\r
+                    int type = event.type;\r
+//                    System.out.println("[" + state + "][" + event.time + "] event: " + type);\r
+//                    System.out.flush();\r
+                    \r
+//                    switch (state) {\r
+//                        case OK:\r
+//                            if (type == SWT.Deactivate) {\r
+//                                state = state.dirty();\r
+//                            }\r
+//                            break;\r
+//                            \r
+//                        case DIRTY:\r
+//                            if (type == SWT.Activate) {\r
+//                                state = state.updated();\r
+//                                updateSplashImage(getSplash());\r
+//                            }\r
+//                            break;\r
+//                        case UPDATED:\r
+//                            if (type == SWT.Activate) {\r
+//                                state = state.ok();\r
+//                            }\r
+//                            break;\r
+//                        default:\r
+//                    }\r
+                }\r
+            });\r
+        }\r
+        */\r
+\r
+        fCompositeLogin.addListener(SWT.Paint, new Listener() {\r
+            @Override\r
+            public void handleEvent(Event event) {\r
+                // Time elapsed in milliseconds from the beginning of the fade.\r
+                float timeElapsed = 0;\r
+                if (fadeStartTime == 0) {\r
+                    fadeStartTime = System.currentTimeMillis();\r
+                } else {\r
+                    timeElapsed = (System.currentTimeMillis() - fadeStartTime);\r
+                }\r
+                int fade = Math.min(255, (int) Math.round(255f * timeElapsed / (float) FADE_TIME_MS));\r
+                if (fade >= 255) {\r
+                    fadeComplete = true;\r
+                }\r
+                \r
+                GC gc = event.gc;\r
+                gc.drawImage(currentBackground, 0, 0);\r
+                gc.setAlpha(fade);\r
+                gc.drawImage(splashImage, 0, 0);\r
+                \r
+                if (!fadeComplete) {\r
+                    getSplash().getDisplay().timerExec(25, new Runnable() {\r
+                        @Override\r
+                        public void run() {\r
+                            Shell s = getSplash();\r
+                            if (s != null && !s.isDisposed()) {\r
+                                Point size = s.getSize();\r
+                                s.redraw(0,0, size.x, size.y, true);\r
+                            }\r
+                        }\r
+                    });\r
+                }\r
+            }\r
+        });\r
+\r
+        // Create the OK button listeners\r
+//        createUIListenersButtonOK();\r
+        // Create the cancel button listeners\r
+//        createUIListenersButtonCancel();\r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void createUIListenersButtonCancel() {\r
+        fButtonCancel.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                handleButtonCancelWidgetSelected();\r
+            }\r
+        });\r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void handleButtonCancelWidgetSelected() {\r
+        // Abort the loading of the RCP application\r
+        getSplash().getDisplay().close();\r
+        System.exit(0);\r
+    }\r
+\r
+    /**\r
+     * configureUISplash\r
+     */\r
+    private void createUIListenersButtonOK() {\r
+        fButtonOK.addSelectionListener(new SelectionAdapter() {\r
+            public void widgetSelected(SelectionEvent e) {\r
+                handleButtonOKWidgetSelected();\r
+            }\r
+        });\r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void handleButtonOKWidgetSelected() {\r
+        String username = fTextUsername.getText();\r
+        String password = fTextPassword.getText();\r
+        // Aunthentication is successful if a user provides any username and\r
+        // any password\r
+        if ((username.length() > 0) &&\r
+                (password.length() > 0)) {\r
+            fAuthenticated = true;\r
+        } else {\r
+            MessageDialog.openError(\r
+                    getSplash(),\r
+                    "Authentication Failed",  //NON-NLS-1\r
+            "A username and password must be specified to login.");  //NON-NLS-1\r
+        }\r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void createUI() {\r
+        // Create the login panel\r
+        createUICompositeLogin();\r
+        // Create the blank spanner\r
+        //createUICompositeBlank();\r
+        // Create the user name label\r
+        //createUILabelUserName();\r
+        // Create the user name text widget\r
+        //createUITextUserName();\r
+        // Create the password label\r
+        //createUILabelPassword();\r
+        // Create the password text widget\r
+        //createUITextPassword();\r
+        // Create the blank label\r
+        //createUILabelBlank();\r
+        // Create the OK button\r
+        //createUIButtonOK();\r
+        // Create the cancel button\r
+        //createUIButtonCancel();\r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void createUIButtonCancel() {\r
+        // Create the button\r
+        fButtonCancel = new Button(fCompositeLogin, SWT.PUSH);\r
+        fButtonCancel.setText("Cancel"); //NON-NLS-1\r
+        // Configure layout data\r
+        GridData data = new GridData(SWT.NONE, SWT.NONE, false, false);\r
+        data.widthHint = F_BUTTON_WIDTH_HINT;  \r
+        data.verticalIndent = 10;\r
+        fButtonCancel.setLayoutData(data);\r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void createUIButtonOK() {\r
+        // Create the button\r
+        fButtonOK = new Button(fCompositeLogin, SWT.PUSH);\r
+        fButtonOK.setText("OK"); //NON-NLS-1\r
+        // Configure layout data\r
+        GridData data = new GridData(SWT.NONE, SWT.NONE, false, false);\r
+        data.widthHint = F_BUTTON_WIDTH_HINT;\r
+        data.verticalIndent = 10;\r
+        fButtonOK.setLayoutData(data);\r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void createUILabelBlank() {\r
+        Label label = new Label(fCompositeLogin, SWT.NONE);\r
+        label.setVisible(false);\r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void createUITextPassword() {\r
+        // Create the text widget\r
+        int style = SWT.PASSWORD | SWT.BORDER;\r
+        fTextPassword = new Text(fCompositeLogin, style);\r
+        // Configure layout data\r
+        GridData data = new GridData(SWT.NONE, SWT.NONE, false, false);\r
+        data.widthHint = F_TEXT_WIDTH_HINT;\r
+        data.horizontalSpan = 2;\r
+        fTextPassword.setLayoutData(data);\r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void createUILabelPassword() {\r
+        // Create the label\r
+        Label label = new Label(fCompositeLogin, SWT.NONE);\r
+        label.setText("&Password:"); //NON-NLS-1\r
+        // Configure layout data\r
+        GridData data = new GridData();\r
+        data.horizontalIndent = F_LABEL_HORIZONTAL_INDENT;\r
+        label.setLayoutData(data);\r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void createUITextUserName() {\r
+        // Create the text widget\r
+        fTextUsername = new Text(fCompositeLogin, SWT.BORDER);\r
+        // Configure layout data\r
+        GridData data = new GridData(SWT.NONE, SWT.NONE, false, false);\r
+        data.widthHint = F_TEXT_WIDTH_HINT;\r
+        data.horizontalSpan = 2;\r
+        fTextUsername.setLayoutData(data);\r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void createUILabelUserName() {\r
+        // Create the label\r
+        Label label = new Label(fCompositeLogin, SWT.NONE);\r
+        label.setText("&User Name:"); //NON-NLS-1\r
+        // Configure layout data\r
+        GridData data = new GridData();\r
+        data.horizontalIndent = F_LABEL_HORIZONTAL_INDENT;\r
+        label.setLayoutData(data);             \r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void createUICompositeBlank() {\r
+        Composite spanner = new Composite(fCompositeLogin, SWT.NONE);\r
+        GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);\r
+        data.horizontalSpan = F_COLUMN_COUNT;\r
+        spanner.setLayoutData(data);\r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void createUICompositeLogin() {\r
+        // Create the composite\r
+//        fCompositeLogin = new Composite(getSplash(), SWT.NONE);\r
+        fCompositeLogin = new Canvas(getSplash(), SWT.DOUBLE_BUFFERED);\r
+        GridLayout layout = new GridLayout(F_COLUMN_COUNT, false);\r
+        fCompositeLogin.setLayout(layout);\r
+    }\r
+\r
+    /**\r
+     * \r
+     */\r
+    private void configureUISplash() {\r
+        // Configure layout\r
+        FillLayout layout = new FillLayout(); \r
+        getSplash().setLayout(layout);\r
+        // Force shell to inherit the splash background\r
+        getSplash().setBackgroundMode(SWT.INHERIT_DEFAULT);\r
+    }\r
+\r
+}\r