]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.workbench/src/org/simantics/workbench/internal/contributions/GraphRequestStatusTrim.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.workbench / src / org / simantics / workbench / internal / contributions / GraphRequestStatusTrim.java
diff --git a/bundles/org.simantics.workbench/src/org/simantics/workbench/internal/contributions/GraphRequestStatusTrim.java b/bundles/org.simantics.workbench/src/org/simantics/workbench/internal/contributions/GraphRequestStatusTrim.java
new file mode 100644 (file)
index 0000000..5531c32
--- /dev/null
@@ -0,0 +1,438 @@
+/*******************************************************************************\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
+package org.simantics.workbench.internal.contributions;\r
+\r
+import org.eclipse.jface.action.Action;\r
+import org.eclipse.jface.action.IMenuListener;\r
+import org.eclipse.jface.action.IMenuManager;\r
+import org.eclipse.jface.action.MenuManager;\r
+import org.eclipse.jface.preference.IPreferenceStore;\r
+import org.eclipse.jface.util.IPropertyChangeListener;\r
+import org.eclipse.jface.util.PropertyChangeEvent;\r
+import org.eclipse.osgi.util.NLS;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.graphics.Color;\r
+import org.eclipse.swt.graphics.GC;\r
+import org.eclipse.swt.graphics.Point;\r
+import org.eclipse.swt.graphics.Rectangle;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.swt.widgets.Event;\r
+import org.eclipse.swt.widgets.Listener;\r
+import org.eclipse.swt.widgets.Menu;\r
+import org.eclipse.ui.internal.TrimUtil;\r
+import org.eclipse.ui.internal.WorkbenchMessages;\r
+import org.simantics.db.MonitorContext;\r
+import org.simantics.db.MonitorHandler;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.SessionReference;\r
+import org.simantics.db.SessionVariables;\r
+import org.simantics.db.service.LifecycleSupport;\r
+import org.simantics.db.service.SessionMonitorSupport;\r
+\r
+/**\r
+ * The graph request status control, which shows the current graph request state\r
+ * of a workbench window in the window trim.\r
+ * <p>\r
+ * Adapted from Eclipse's Heap Status control.\r
+ * </p>\r
+ */\r
+public class GraphRequestStatusTrim extends Composite {\r
+\r
+    final String requestStatusMessage = "{0}R / {1}W";\r
+    final String requestToolTip = "Session: {0}\nPending: {1} read requests, {2} write requests";\r
+\r
+    private boolean armed;\r
+    //private final Image gcImage;\r
+    private final Color bgCol, lowMemCol, freeMemCol;\r
+    private Color topLeftCol;\r
+    private final Color bottomRightCol, sepCol, textCol;\r
+    //private Color armCol;\r
+    //private final Canvas button;\r
+    private final IPreferenceStore prefStore;\r
+    private final int updateInterval = 200;\r
+    private boolean hasChanged;\r
+    // start with 12x12\r
+    private Rectangle imgBounds = new Rectangle(0,0,12,12);\r
+\r
+    private SessionMonitorSupport session;\r
+    private MonitorContext monitorContext;\r
+    private long lastRedrawTime = 0;\r
+\r
+    class Status {\r
+        SessionReference sessionRef;\r
+        int reads;\r
+        int writes;\r
+\r
+        void clear() {\r
+            sessionRef = null;\r
+            reads = 0;\r
+            writes = 0;\r
+        }\r
+    }\r
+\r
+    private final Status status = new Status();\r
+\r
+    private final MonitorHandler monitorHandler = new MonitorHandler() {\r
+        @Override\r
+        public void valuesChanged(MonitorContext c) {\r
+            //updateStats();\r
+            long time = System.currentTimeMillis();\r
+            // Require that 100ms has passed before refreshing again.\r
+            if ((time - 100) > lastRedrawTime) {\r
+                lastRedrawTime = time;\r
+                if (!isDisposed()) {\r
+                    getDisplay().asyncExec(timer);\r
+                }\r
+            }\r
+        }\r
+    };\r
+\r
+    private final Runnable timer = new Runnable() {\r
+        public void run() {\r
+            if (!isDisposed()) {\r
+                updateStats();\r
+                if (hasChanged) {\r
+                    updateToolTip();\r
+                    redraw();\r
+                    hasChanged = false;\r
+                }\r
+                getDisplay().timerExec(updateInterval, this);\r
+            }\r
+        }\r
+    };\r
+\r
+    private final IPropertyChangeListener prefListener = new IPropertyChangeListener() {\r
+        public void propertyChange(PropertyChangeEvent event) {\r
+//          if (IHeapStatusConstants.PREF_UPDATE_INTERVAL.equals(event.getProperty())) {\r
+//          setUpdateIntervalInMS(prefStore.getInt(IHeapStatusConstants.PREF_UPDATE_INTERVAL));\r
+//          }\r
+//          else if (IHeapStatusConstants.PREF_SHOW_MAX.equals(event.getProperty())) {\r
+//          showMax = prefStore.getBoolean(IHeapStatusConstants.PREF_SHOW_MAX);\r
+//          }\r
+        }\r
+    };\r
+\r
+    public void attachToSession(Session session) {\r
+        if (session != this.session) {\r
+            if (monitorContext != null) {\r
+                this.session.unregisterMonitor(monitorContext);\r
+                monitorContext = null;\r
+                this.session = null;\r
+                status.clear();\r
+            }\r
+\r
+            SessionMonitorSupport support = null;\r
+            if (session != null)\r
+                support = session.peekService(SessionMonitorSupport.class);\r
+            if (support == null) {\r
+                hasChanged = true;\r
+                return;\r
+            }\r
+\r
+            this.session = support;\r
+            monitorContext = this.session.registerMonitor(monitorHandler);\r
+            LifecycleSupport lifecycleSupport = session.getService(LifecycleSupport.class);\r
+            status.sessionRef = lifecycleSupport.getSessionReference();\r
+            getDisplay().asyncExec(timer);\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Creates a new heap status control with the given parent, and using\r
+     * the given preference store to obtain settings such as the refresh\r
+     * interval.\r
+     * \r
+     * @param parent the parent composite\r
+     * @param prefStore the preference store\r
+     */\r
+    public GraphRequestStatusTrim(Composite parent, IPreferenceStore prefStore) {\r
+        super(parent, SWT.NONE);\r
+\r
+        this.prefStore = prefStore;\r
+        prefStore.addPropertyChangeListener(prefListener);\r
+\r
+//        setUpdateIntervalInMS(prefStore.getInt(IHeapStatusConstants.PREF_UPDATE_INTERVAL));\r
+//        showMax = prefStore.getBoolean(IHeapStatusConstants.PREF_SHOW_MAX);\r
+\r
+        //button = new Canvas(this, SWT.NONE);\r
+\r
+//        ImageDescriptor imageDesc = SimanticsUI.getImageDescriptor("icons/etool16/wrench.png"); //$NON-NLS-1$\r
+//        gcImage = imageDesc.createImage();\r
+//        if (gcImage != null) {\r
+//            imgBounds = gcImage.getBounds();\r
+//        }\r
+        Display display = getDisplay();\r
+//        usedMemCol = display.getSystemColor(SWT.COLOR_INFO_BACKGROUND);\r
+        lowMemCol = new Color(display, 255, 70, 70);  // medium red\r
+        freeMemCol = new Color(display, 255, 190, 125);  // light orange\r
+        bgCol = display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);\r
+        sepCol = topLeftCol = /*armCol =*/ display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);\r
+        bottomRightCol = display.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);\r
+        textCol = display.getSystemColor(SWT.COLOR_INFO_FOREGROUND);\r
+//        markCol = textCol;\r
+\r
+        createContextMenu();\r
+\r
+        Listener listener = new Listener() {\r
+\r
+            public void handleEvent(Event event) {\r
+                switch (event.type) {\r
+                    case SWT.Dispose:\r
+                        doDispose();\r
+                        break;\r
+//                    case SWT.Resize:\r
+//                        Rectangle rect = getClientArea();\r
+//                        button.setBounds(rect.width - imgBounds.width - 1, 1, imgBounds.width, rect.height - 2);\r
+//                        break;\r
+                    case SWT.Paint:\r
+                        if (event.widget == GraphRequestStatusTrim.this) {\r
+                            paintComposite(event.gc);\r
+                        }\r
+//                        else if (event.widget == button) {\r
+//                            paintButton(event.gc);\r
+//                        }\r
+                        break;\r
+                    case SWT.MouseUp:\r
+                        if (event.button == 1) {\r
+                            // TODO: if the DB is locked, somehow release it ?\r
+                            arm(false);\r
+                        }\r
+                        break;\r
+                    case SWT.MouseDown:\r
+                        if (event.button == 1) {\r
+                            if (event.widget == GraphRequestStatusTrim.this) {\r
+//                          setMark();\r
+//                            } else if (event.widget == button) {\r
+//                                arm(true);\r
+                            }\r
+                        }\r
+                        break;\r
+                    case SWT.MouseExit:\r
+                        arm(false);\r
+                        break;\r
+                }\r
+            }\r
+\r
+        };\r
+        addListener(SWT.Dispose, listener);\r
+        addListener(SWT.MouseDown, listener);\r
+        addListener(SWT.Paint, listener);\r
+        addListener(SWT.Resize, listener);\r
+//        button.addListener(SWT.MouseDown, listener);\r
+//        button.addListener(SWT.MouseExit, listener);\r
+//        button.addListener(SWT.MouseUp, listener);\r
+//        button.addListener(SWT.Paint, listener);\r
+\r
+        // make sure stats are updated before first paint\r
+        //updateStats();\r
+\r
+        getDisplay().asyncExec(new Runnable() {\r
+            public void run() {\r
+                if (!isDisposed()) {\r
+                    getDisplay().timerExec(updateInterval, timer);\r
+                }\r
+            }\r
+        });\r
+    }\r
+\r
+//    private void setUpdateIntervalInMS(int interval) {\r
+//        updateInterval = Math.max(100, interval);\r
+//    }\r
+\r
+    private void doDispose() {\r
+        prefStore.removePropertyChangeListener(prefListener);\r
+//        if (gcImage != null) {\r
+//            gcImage.dispose();\r
+//        }\r
+\r
+        if (lowMemCol != null) {\r
+            lowMemCol.dispose();\r
+        }\r
+        if (freeMemCol != null) {\r
+            freeMemCol.dispose();\r
+        }\r
+    }\r
+\r
+    /* (non-Javadoc)\r
+     * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)\r
+     */\r
+    @Override\r
+    public Point computeSize(int wHint, int hHint, boolean changed) {\r
+        GC gc = new GC(this);\r
+        Point p = gc.textExtent("MMMMMMM");\r
+        int height = imgBounds.height;\r
+        // choose the largest of\r
+        //     - Text height + margins\r
+        //     - Image height + margins\r
+        //     - Default Trim heightin\r
+        height = Math.max(height, p.y) + 4;\r
+        height = Math.max(TrimUtil.TRIM_DEFAULT_HEIGHT, height);\r
+        gc.dispose();\r
+        return new Point(p.x + 2, height);\r
+    }\r
+\r
+    private void arm(boolean armed) {\r
+        if (this.armed == armed) {\r
+            return;\r
+        }\r
+        this.armed = armed;\r
+//        button.redraw();\r
+//        button.update();\r
+    }\r
+\r
+    /**\r
+     * Creates the context menu\r
+     */\r
+    private void createContextMenu() {\r
+        MenuManager menuMgr = new MenuManager();\r
+        menuMgr.setRemoveAllWhenShown(true);\r
+        menuMgr.addMenuListener(new IMenuListener() {\r
+            public void menuAboutToShow(IMenuManager menuMgr) {\r
+                fillMenu(menuMgr);\r
+            }\r
+        });\r
+        Menu menu = menuMgr.createContextMenu(this);\r
+        setMenu(menu);\r
+    }\r
+\r
+    private void fillMenu(IMenuManager menuMgr) {\r
+        //menuMgr.add(new ShowSessionsAction());\r
+        menuMgr.add(new CloseAction());\r
+    }\r
+\r
+//    private void paintButton(GC gc) {\r
+//        Rectangle rect = button.getClientArea();\r
+//\r
+//        if (armed) {\r
+//            gc.setBackground(armCol);\r
+//            gc.fillRectangle(rect.x, rect.y, rect.width, rect.height);\r
+//        }\r
+////        if (gcImage != null) {\r
+////            int by = (rect.height - imgBounds.height) / 2 + rect.y; // button y\r
+////            gc.drawImage(gcImage, rect.x, by);\r
+////        }\r
+//    }\r
+\r
+\r
+    private void paintComposite(GC gc) {\r
+        Rectangle rect = getClientArea();\r
+        int x = rect.x;\r
+        int y = rect.y;\r
+        int w = rect.width;\r
+        int h = rect.height;\r
+//        int bw = imgBounds.width; // button width\r
+        int bw = 0;\r
+        int dx = x + w - bw - 2; // divider x\r
+//        int sw = w - bw - 3; // status width\r
+//        int uw = (int) (sw * usedMem / totalMem); // used mem width\r
+//        int ux = x + 1 + uw; // used mem right edge\r
+\r
+        gc.setBackground(bgCol);\r
+        gc.fillRectangle(rect);\r
+        gc.setForeground(sepCol);\r
+        gc.drawLine(dx, y, dx, y + h);\r
+//        gc.drawLine(ux, y, ux, y + h);\r
+        gc.setForeground(topLeftCol);\r
+        gc.drawLine(x, y, x+w, y);\r
+        gc.drawLine(x, y, x, y+h);\r
+        gc.setForeground(bottomRightCol);\r
+        gc.drawLine(x+w-1, y, x+w-1, y+h);\r
+        gc.drawLine(x, y+h-1, x+w, y+h-1);\r
+\r
+//        gc.setBackground(usedMemCol);\r
+//        gc.fillRectangle(x + 1, y + 1, uw, h - 2);\r
+\r
+        String reads = String.valueOf(status.reads);\r
+        String writes = String.valueOf(status.writes);\r
+        String s = NLS.bind(requestStatusMessage, new String[] { reads, writes });\r
+\r
+        Point p = gc.textExtent(s);\r
+        //int sx = (rect.width - 15 - p.x) / 2 + rect.x + 1;\r
+        int sx = (rect.width - 2 - p.x) / 2 + rect.x + 1;\r
+        int sy = (rect.height - 2 - p.y) / 2 + rect.y + 1;\r
+        gc.setForeground(textCol);\r
+        gc.setAlpha(192);\r
+        gc.drawString(s, sx, sy, true);\r
+\r
+        // draw an I-shaped bar in the foreground colour for the mark (if present)\r
+//        if (mark != -1) {\r
+//            int ssx = (int) (sw * mark / totalMem) + x + 1;\r
+//            paintMark(gc, ssx, y, h);\r
+//        }\r
+    }\r
+\r
+//     private void paintMark(GC gc, int x, int y, int h) {\r
+//        gc.setForeground(markCol);\r
+//        gc.drawLine(x, y+1, x, y+h-2);\r
+//        gc.drawLine(x-1, y+1, x+1, y+1);\r
+//        gc.drawLine(x-1, y+h-2, x+1, y+h-2);\r
+//     }\r
+\r
+    private void updateStats() {\r
+        if (monitorContext == null)\r
+            return;\r
+\r
+        int reads = monitorContext.getInteger(SessionVariables.QUEUED_READS);\r
+        int writes = monitorContext.getInteger(SessionVariables.QUEUED_WRITES);\r
+        if (reads != status.reads) {\r
+            status.reads = reads;\r
+            this.hasChanged = true;\r
+        }\r
+        if (writes != status.writes) {\r
+            status.writes = writes;\r
+            this.hasChanged = true;\r
+        }\r
+    }\r
+\r
+    private void updateToolTip() {\r
+        String server = "";\r
+        if (status.sessionRef != null)\r
+            server = status.sessionRef.getServerReference().toString();\r
+        String reads = String.valueOf(status.reads);\r
+        String writes = String.valueOf(status.writes);\r
+        String toolTip = NLS.bind(requestToolTip, new String[] { server, reads, writes });\r
+        if (!toolTip.equals(getToolTipText())) {\r
+            setToolTipText(toolTip);\r
+        }\r
+    }\r
+\r
+\r
+    class ShowSessionsAction extends Action{\r
+        ShowSessionsAction(){\r
+            super("Show Local Sessions");\r
+        }\r
+\r
+        /* (non-Javadoc)\r
+         * @see org.eclipse.jface.action.IAction#run()\r
+         */\r
+        @Override\r
+        public void run(){\r
+        }\r
+    }\r
+\r
+    class CloseAction extends Action{\r
+        CloseAction(){\r
+            super(WorkbenchMessages.WorkbenchWindow_close);\r
+        }\r
+\r
+        /* (non-Javadoc)\r
+         * @see org.eclipse.jface.action.IAction#run()\r
+         */\r
+        @Override\r
+        public void run(){\r
+            dispose();\r
+        }\r
+    }\r
+\r
+}\r
+\r