]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.workbench/src/org/simantics/workbench/internal/contributions/GraphRequestStatusTrim.java
Index tokenized lowercase versions of name and types for UI searches
[simantics/platform.git] / bundles / org.simantics.workbench / src / org / simantics / workbench / internal / contributions / GraphRequestStatusTrim.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.workbench.internal.contributions;
13
14 import org.eclipse.jface.action.Action;
15 import org.eclipse.jface.action.IMenuListener;
16 import org.eclipse.jface.action.IMenuManager;
17 import org.eclipse.jface.action.MenuManager;
18 import org.eclipse.jface.preference.IPreferenceStore;
19 import org.eclipse.jface.util.IPropertyChangeListener;
20 import org.eclipse.jface.util.PropertyChangeEvent;
21 import org.eclipse.osgi.util.NLS;
22 import org.eclipse.swt.SWT;
23 import org.eclipse.swt.graphics.Color;
24 import org.eclipse.swt.graphics.GC;
25 import org.eclipse.swt.graphics.Point;
26 import org.eclipse.swt.graphics.Rectangle;
27 import org.eclipse.swt.widgets.Composite;
28 import org.eclipse.swt.widgets.Display;
29 import org.eclipse.swt.widgets.Event;
30 import org.eclipse.swt.widgets.Listener;
31 import org.eclipse.swt.widgets.Menu;
32 import org.eclipse.ui.internal.TrimUtil;
33 import org.eclipse.ui.internal.WorkbenchMessages;
34 import org.simantics.db.MonitorContext;
35 import org.simantics.db.MonitorHandler;
36 import org.simantics.db.Session;
37 import org.simantics.db.SessionReference;
38 import org.simantics.db.SessionVariables;
39 import org.simantics.db.service.LifecycleSupport;
40 import org.simantics.db.service.SessionMonitorSupport;
41
42 /**
43  * The graph request status control, which shows the current graph request state
44  * of a workbench window in the window trim.
45  * <p>
46  * Adapted from Eclipse's Heap Status control.
47  * </p>
48  */
49 public class GraphRequestStatusTrim extends Composite {
50
51     final String requestStatusMessage = "{0}R / {1}W";
52     final String requestToolTip = "Session: {0}\nPending: {1} read requests, {2} write requests";
53
54     private boolean armed;
55     //private final Image gcImage;
56     private final Color bgCol, lowMemCol, freeMemCol;
57     private Color topLeftCol;
58     private final Color bottomRightCol, sepCol, textCol;
59     //private Color armCol;
60     //private final Canvas button;
61     private final IPreferenceStore prefStore;
62     private final int updateInterval = 200;
63     private boolean hasChanged;
64     // start with 12x12
65     private Rectangle imgBounds = new Rectangle(0,0,12,12);
66
67     private SessionMonitorSupport session;
68     private MonitorContext monitorContext;
69     private long lastRedrawTime = 0;
70
71     class Status {
72         SessionReference sessionRef;
73         int reads;
74         int writes;
75
76         void clear() {
77             sessionRef = null;
78             reads = 0;
79             writes = 0;
80         }
81     }
82
83     private final Status status = new Status();
84
85     private final MonitorHandler monitorHandler = new MonitorHandler() {
86         @Override
87         public void valuesChanged(MonitorContext c) {
88             //updateStats();
89             long time = System.currentTimeMillis();
90             // Require that 100ms has passed before refreshing again.
91             if ((time - 100) > lastRedrawTime) {
92                 lastRedrawTime = time;
93                 if (!isDisposed()) {
94                     getDisplay().asyncExec(timer);
95                 }
96             }
97         }
98     };
99
100     private final Runnable timer = new Runnable() {
101         public void run() {
102             if (!isDisposed()) {
103                 updateStats();
104                 if (hasChanged) {
105                     updateToolTip();
106                     redraw();
107                     hasChanged = false;
108                 }
109                 getDisplay().timerExec(updateInterval, this);
110             }
111         }
112     };
113
114     private final IPropertyChangeListener prefListener = new IPropertyChangeListener() {
115         public void propertyChange(PropertyChangeEvent event) {
116 //          if (IHeapStatusConstants.PREF_UPDATE_INTERVAL.equals(event.getProperty())) {
117 //          setUpdateIntervalInMS(prefStore.getInt(IHeapStatusConstants.PREF_UPDATE_INTERVAL));
118 //          }
119 //          else if (IHeapStatusConstants.PREF_SHOW_MAX.equals(event.getProperty())) {
120 //          showMax = prefStore.getBoolean(IHeapStatusConstants.PREF_SHOW_MAX);
121 //          }
122         }
123     };
124
125     public void attachToSession(Session session) {
126         if (session != this.session) {
127             if (monitorContext != null) {
128                 this.session.unregisterMonitor(monitorContext);
129                 monitorContext = null;
130                 this.session = null;
131                 status.clear();
132             }
133
134             SessionMonitorSupport support = null;
135             if (session != null)
136                 support = session.peekService(SessionMonitorSupport.class);
137             if (support == null) {
138                 hasChanged = true;
139                 return;
140             }
141
142             this.session = support;
143             monitorContext = this.session.registerMonitor(monitorHandler);
144             LifecycleSupport lifecycleSupport = session.getService(LifecycleSupport.class);
145             status.sessionRef = lifecycleSupport.getSessionReference();
146             getDisplay().asyncExec(timer);
147         }
148     }
149
150     /**
151      * Creates a new heap status control with the given parent, and using
152      * the given preference store to obtain settings such as the refresh
153      * interval.
154      * 
155      * @param parent the parent composite
156      * @param prefStore the preference store
157      */
158     public GraphRequestStatusTrim(Composite parent, IPreferenceStore prefStore) {
159         super(parent, SWT.NONE);
160
161         this.prefStore = prefStore;
162         prefStore.addPropertyChangeListener(prefListener);
163
164 //        setUpdateIntervalInMS(prefStore.getInt(IHeapStatusConstants.PREF_UPDATE_INTERVAL));
165 //        showMax = prefStore.getBoolean(IHeapStatusConstants.PREF_SHOW_MAX);
166
167         //button = new Canvas(this, SWT.NONE);
168
169 //        ImageDescriptor imageDesc = SimanticsUI.getImageDescriptor("icons/etool16/wrench.png"); //$NON-NLS-1$
170 //        gcImage = imageDesc.createImage();
171 //        if (gcImage != null) {
172 //            imgBounds = gcImage.getBounds();
173 //        }
174         Display display = getDisplay();
175 //        usedMemCol = display.getSystemColor(SWT.COLOR_INFO_BACKGROUND);
176         lowMemCol = new Color(display, 255, 70, 70);  // medium red
177         freeMemCol = new Color(display, 255, 190, 125);  // light orange
178         bgCol = display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
179         sepCol = topLeftCol = /*armCol =*/ display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
180         bottomRightCol = display.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
181         textCol = display.getSystemColor(SWT.COLOR_INFO_FOREGROUND);
182 //        markCol = textCol;
183
184         createContextMenu();
185
186         Listener listener = new Listener() {
187
188             public void handleEvent(Event event) {
189                 switch (event.type) {
190                     case SWT.Dispose:
191                         doDispose();
192                         break;
193 //                    case SWT.Resize:
194 //                        Rectangle rect = getClientArea();
195 //                        button.setBounds(rect.width - imgBounds.width - 1, 1, imgBounds.width, rect.height - 2);
196 //                        break;
197                     case SWT.Paint:
198                         if (event.widget == GraphRequestStatusTrim.this) {
199                             paintComposite(event.gc);
200                         }
201 //                        else if (event.widget == button) {
202 //                            paintButton(event.gc);
203 //                        }
204                         break;
205                     case SWT.MouseUp:
206                         if (event.button == 1) {
207                             // TODO: if the DB is locked, somehow release it ?
208                             arm(false);
209                         }
210                         break;
211                     case SWT.MouseDown:
212                         if (event.button == 1) {
213                             if (event.widget == GraphRequestStatusTrim.this) {
214 //                          setMark();
215 //                            } else if (event.widget == button) {
216 //                                arm(true);
217                             }
218                         }
219                         break;
220                     case SWT.MouseExit:
221                         arm(false);
222                         break;
223                 }
224             }
225
226         };
227         addListener(SWT.Dispose, listener);
228         addListener(SWT.MouseDown, listener);
229         addListener(SWT.Paint, listener);
230         addListener(SWT.Resize, listener);
231 //        button.addListener(SWT.MouseDown, listener);
232 //        button.addListener(SWT.MouseExit, listener);
233 //        button.addListener(SWT.MouseUp, listener);
234 //        button.addListener(SWT.Paint, listener);
235
236         // make sure stats are updated before first paint
237         //updateStats();
238
239         getDisplay().asyncExec(new Runnable() {
240             public void run() {
241                 if (!isDisposed()) {
242                     getDisplay().timerExec(updateInterval, timer);
243                 }
244             }
245         });
246     }
247
248 //    private void setUpdateIntervalInMS(int interval) {
249 //        updateInterval = Math.max(100, interval);
250 //    }
251
252     private void doDispose() {
253         prefStore.removePropertyChangeListener(prefListener);
254 //        if (gcImage != null) {
255 //            gcImage.dispose();
256 //        }
257
258         if (lowMemCol != null) {
259             lowMemCol.dispose();
260         }
261         if (freeMemCol != null) {
262             freeMemCol.dispose();
263         }
264     }
265
266     /* (non-Javadoc)
267      * @see org.eclipse.swt.widgets.Composite#computeSize(int, int, boolean)
268      */
269     @Override
270     public Point computeSize(int wHint, int hHint, boolean changed) {
271         GC gc = new GC(this);
272         Point p = gc.textExtent("MMMMMMM");
273         int height = imgBounds.height;
274         // choose the largest of
275         //      - Text height + margins
276         //      - Image height + margins
277         //      - Default Trim heightin
278         height = Math.max(height, p.y) + 4;
279         height = Math.max(TrimUtil.TRIM_DEFAULT_HEIGHT, height);
280         gc.dispose();
281         return new Point(p.x + 2, height);
282     }
283
284     private void arm(boolean armed) {
285         if (this.armed == armed) {
286             return;
287         }
288         this.armed = armed;
289 //        button.redraw();
290 //        button.update();
291     }
292
293     /**
294      * Creates the context menu
295      */
296     private void createContextMenu() {
297         MenuManager menuMgr = new MenuManager();
298         menuMgr.setRemoveAllWhenShown(true);
299         menuMgr.addMenuListener(new IMenuListener() {
300             public void menuAboutToShow(IMenuManager menuMgr) {
301                 fillMenu(menuMgr);
302             }
303         });
304         Menu menu = menuMgr.createContextMenu(this);
305         setMenu(menu);
306     }
307
308     private void fillMenu(IMenuManager menuMgr) {
309         //menuMgr.add(new ShowSessionsAction());
310         menuMgr.add(new CloseAction());
311     }
312
313 //    private void paintButton(GC gc) {
314 //        Rectangle rect = button.getClientArea();
315 //
316 //        if (armed) {
317 //            gc.setBackground(armCol);
318 //            gc.fillRectangle(rect.x, rect.y, rect.width, rect.height);
319 //        }
320 ////        if (gcImage != null) {
321 ////            int by = (rect.height - imgBounds.height) / 2 + rect.y; // button y
322 ////            gc.drawImage(gcImage, rect.x, by);
323 ////        }
324 //    }
325
326
327     private void paintComposite(GC gc) {
328         Rectangle rect = getClientArea();
329         int x = rect.x;
330         int y = rect.y;
331         int w = rect.width;
332         int h = rect.height;
333 //        int bw = imgBounds.width; // button width
334         int bw = 0;
335         int dx = x + w - bw - 2; // divider x
336 //        int sw = w - bw - 3; // status width
337 //        int uw = (int) (sw * usedMem / totalMem); // used mem width
338 //        int ux = x + 1 + uw; // used mem right edge
339
340         gc.setBackground(bgCol);
341         gc.fillRectangle(rect);
342         gc.setForeground(sepCol);
343         gc.drawLine(dx, y, dx, y + h);
344 //        gc.drawLine(ux, y, ux, y + h);
345         gc.setForeground(topLeftCol);
346         gc.drawLine(x, y, x+w, y);
347         gc.drawLine(x, y, x, y+h);
348         gc.setForeground(bottomRightCol);
349         gc.drawLine(x+w-1, y, x+w-1, y+h);
350         gc.drawLine(x, y+h-1, x+w, y+h-1);
351
352 //        gc.setBackground(usedMemCol);
353 //        gc.fillRectangle(x + 1, y + 1, uw, h - 2);
354
355         String reads = String.valueOf(status.reads);
356         String writes = String.valueOf(status.writes);
357         String s = NLS.bind(requestStatusMessage, new String[] { reads, writes });
358
359         Point p = gc.textExtent(s);
360         //int sx = (rect.width - 15 - p.x) / 2 + rect.x + 1;
361         int sx = (rect.width - 2 - p.x) / 2 + rect.x + 1;
362         int sy = (rect.height - 2 - p.y) / 2 + rect.y + 1;
363         gc.setForeground(textCol);
364         gc.setAlpha(192);
365         gc.drawString(s, sx, sy, true);
366
367         // draw an I-shaped bar in the foreground colour for the mark (if present)
368 //        if (mark != -1) {
369 //            int ssx = (int) (sw * mark / totalMem) + x + 1;
370 //            paintMark(gc, ssx, y, h);
371 //        }
372     }
373
374 //      private void paintMark(GC gc, int x, int y, int h) {
375 //        gc.setForeground(markCol);
376 //        gc.drawLine(x, y+1, x, y+h-2);
377 //        gc.drawLine(x-1, y+1, x+1, y+1);
378 //        gc.drawLine(x-1, y+h-2, x+1, y+h-2);
379 //      }
380
381     private void updateStats() {
382         if (monitorContext == null)
383             return;
384
385         int reads = monitorContext.getInteger(SessionVariables.QUEUED_READS);
386         int writes = monitorContext.getInteger(SessionVariables.QUEUED_WRITES);
387         if (reads != status.reads) {
388             status.reads = reads;
389             this.hasChanged = true;
390         }
391         if (writes != status.writes) {
392             status.writes = writes;
393             this.hasChanged = true;
394         }
395     }
396
397     private void updateToolTip() {
398         String server = "";
399         if (status.sessionRef != null)
400             server = status.sessionRef.getServerReference().toString();
401         String reads = String.valueOf(status.reads);
402         String writes = String.valueOf(status.writes);
403         String toolTip = NLS.bind(requestToolTip, new String[] { server, reads, writes });
404         if (!toolTip.equals(getToolTipText())) {
405             setToolTipText(toolTip);
406         }
407     }
408
409
410     class ShowSessionsAction extends Action{
411         ShowSessionsAction(){
412             super("Show Local Sessions");
413         }
414
415         /* (non-Javadoc)
416          * @see org.eclipse.jface.action.IAction#run()
417          */
418         @Override
419         public void run(){
420         }
421     }
422
423     class CloseAction extends Action{
424         CloseAction(){
425             super(WorkbenchMessages.WorkbenchWindow_close);
426         }
427
428         /* (non-Javadoc)
429          * @see org.eclipse.jface.action.IAction#run()
430          */
431         @Override
432         public void run(){
433             dispose();
434         }
435     }
436
437 }
438