X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.workbench%2Fsrc%2Forg%2Fsimantics%2Fworkbench%2Finternal%2Fcontributions%2FGraphRequestStatusTrim.java;fp=bundles%2Forg.simantics.workbench%2Fsrc%2Forg%2Fsimantics%2Fworkbench%2Finternal%2Fcontributions%2FGraphRequestStatusTrim.java;h=5531c32ae607121aa52c18ab7363066461e9db55;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git 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 index 000000000..5531c32ae --- /dev/null +++ b/bundles/org.simantics.workbench/src/org/simantics/workbench/internal/contributions/GraphRequestStatusTrim.java @@ -0,0 +1,438 @@ +/******************************************************************************* + * Copyright (c) 2007, 2010 Association for Decentralized Information Management + * in Industry THTH ry. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * VTT Technical Research Centre of Finland - initial API and implementation + *******************************************************************************/ +package org.simantics.workbench.internal.contributions; + +import org.eclipse.jface.action.Action; +import org.eclipse.jface.action.IMenuListener; +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.MenuManager; +import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; +import org.eclipse.osgi.util.NLS; +import org.eclipse.swt.SWT; +import org.eclipse.swt.graphics.Color; +import org.eclipse.swt.graphics.GC; +import org.eclipse.swt.graphics.Point; +import org.eclipse.swt.graphics.Rectangle; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Event; +import org.eclipse.swt.widgets.Listener; +import org.eclipse.swt.widgets.Menu; +import org.eclipse.ui.internal.TrimUtil; +import org.eclipse.ui.internal.WorkbenchMessages; +import org.simantics.db.MonitorContext; +import org.simantics.db.MonitorHandler; +import org.simantics.db.Session; +import org.simantics.db.SessionReference; +import org.simantics.db.SessionVariables; +import org.simantics.db.service.LifecycleSupport; +import org.simantics.db.service.SessionMonitorSupport; + +/** + * The graph request status control, which shows the current graph request state + * of a workbench window in the window trim. + *

+ * Adapted from Eclipse's Heap Status control. + *

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