--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<classpath>\r
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>\r
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>\r
+ <classpathentry kind="src" path="src"/>\r
+ <classpathentry kind="output" path="bin"/>\r
+</classpath>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>\r
+<projectDescription>\r
+ <name>org.simantics.ui.workspace.tracker</name>\r
+ <comment></comment>\r
+ <projects>\r
+ </projects>\r
+ <buildSpec>\r
+ <buildCommand>\r
+ <name>org.eclipse.jdt.core.javabuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.ManifestBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ <buildCommand>\r
+ <name>org.eclipse.pde.SchemaBuilder</name>\r
+ <arguments>\r
+ </arguments>\r
+ </buildCommand>\r
+ </buildSpec>\r
+ <natures>\r
+ <nature>org.eclipse.pde.PluginNature</nature>\r
+ <nature>org.eclipse.jdt.core.javanature</nature>\r
+ </natures>\r
+</projectDescription>\r
--- /dev/null
+eclipse.preferences.version=1\r
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled\r
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8\r
+org.eclipse.jdt.core.compiler.compliance=1.8\r
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error\r
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error\r
+org.eclipse.jdt.core.compiler.source=1.8\r
--- /dev/null
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Workspace Size Monitoring
+Bundle-SymbolicName: org.simantics.ui.workspace.tracker;singleton:=true
+Bundle-Version: 1.0.0.qualifier
+Bundle-Activator: org.simantics.ui.workspace.tracker.internal.Activator
+Bundle-Vendor: Semantum Oy
+Require-Bundle: javax.inject,
+ org.eclipse.osgi,
+ org.eclipse.jface,
+ org.eclipse.e4.ui.services,
+ org.eclipse.e4.core.di.annotations,
+ org.eclipse.core.runtime,
+ org.eclipse.e4.core.di,
+ org.simantics.filesystem.services,
+ org.slf4j.api,
+ org.eclipse.e4.ui.model.workbench,
+ org.eclipse.ui.workbench,
+ org.eclipse.ui,
+ org.eclipse.e4.core.contexts
+Bundle-RequiredExecutionEnvironment: JavaSE-1.8
+Import-Package: javax.annotation;version="1.2.0",
+ javax.inject;version="1.0.0",
+ org.eclipse.e4.ui.workbench.modeling
+Bundle-ActivationPolicy: lazy
--- /dev/null
+source.. = src/
+output.. = bin/
+bin.includes = plugin.xml,\
+ META-INF/,\
+ .,\
+ fragment.e4xmi
--- /dev/null
+<?xml version="1.0" encoding="ASCII"?>\r
+<fragment:ModelFragments xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:fragment="http://www.eclipse.org/ui/2010/UIModel/fragment" xmlns:menu="http://www.eclipse.org/ui/2010/UIModel/application/ui/menu" xmi:id="_BxaXACerEeWxCPrV0pAZQQ">\r
+ <fragments xsi:type="fragment:StringModelFragment" xmi:id="_wcLoQMX-Eea_bKDmo1phvA" featurename="trimContributions" parentElementId="xpath:/">\r
+ <elements xsi:type="menu:TrimContribution" xmi:id="_z1UuUMX-Eea_bKDmo1phvA" elementId="org.simantics.ui.workspace.tracker.trimcontribution.0" parentId="org.eclipse.ui.trim.status" positionInParent="after=additions">\r
+ <children xsi:type="menu:ToolControl" xmi:id="_Ch72IMfsEeeUz6Cs9kKeKg" elementId="org.simantics.ui.workspace.tracker.toolcontrol.0" contributionURI="bundleclass://org.simantics.ui.workspace.tracker/org.simantics.ui.workspace.tracker.internal.contributions.WorkspaceSizeTrackerContribution"/>\r
+ </elements>\r
+ </fragments>\r
+</fragment:ModelFragments>\r
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.4"?>
+<plugin>
+
+ <extension
+ id="org.simantics.ui.workspace.tracker.fragment"
+ point="org.eclipse.e4.workbench.model">
+ <fragment
+ apply="initial"
+ uri="fragment.e4xmi">
+ </fragment>
+ </extension>
+ <extension
+ point="org.eclipse.ui.preferencePages">
+ <page
+ category="org.eclipse.ui.preferencePages.Workspace"
+ class="org.simantics.ui.workspace.tracker.internal.preferences.WorkspaceSizeTrackingPreferencePage"
+ id="org.simantics.ui.workspace.tracker.preferencePage"
+ name="Size Tracking">
+ </page>
+ </extension>
+ <extension
+ point="org.eclipse.core.runtime.preferences">
+ <initializer
+ class="org.simantics.ui.workspace.tracker.internal.preferences.WorkspaceSizeTrackingPreferenceInitializer">
+ </initializer>
+ </extension>
+
+</plugin>
--- /dev/null
+package org.simantics.ui.workspace.tracker.internal;
+
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.ui.preferences.ScopedPreferenceStore;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.util.tracker.ServiceTracker;
+import org.simantics.filesystem.services.sizetracker.DirectorySizeService;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.31.0
+ */
+public class Activator implements BundleActivator {
+
+ private static Activator instance;
+ private static BundleContext context;
+ private ServiceTracker<DirectorySizeService, DirectorySizeService> tracker;
+ private IPreferenceStore preferenceStore;
+
+ static BundleContext getContext() {
+ return context;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext bundleContext) throws Exception {
+ Activator.instance = this;
+ Activator.context = bundleContext;
+ tracker = new ServiceTracker<>(bundleContext, DirectorySizeService.class, null);
+ tracker.open();
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.osgi.framework.BundleActivator#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext bundleContext) throws Exception {
+ tracker.close();
+ Activator.context = null;
+ Activator.instance = null;
+ }
+
+ /**
+ * @return <code>null</code> if service is no longer available
+ */
+ public DirectorySizeService getDirectorySizeService() {
+ return tracker.getService();
+ }
+
+ public BundleContext getBundleContext() {
+ return context;
+ }
+
+ public IPreferenceStore getPreferenceStore() {
+ if (preferenceStore == null) {
+ preferenceStore = new ScopedPreferenceStore(InstanceScope.INSTANCE, context.getBundle().getSymbolicName());
+ }
+ return preferenceStore;
+ }
+
+ public static Activator getDefault() {
+ return instance;
+ }
+
+}
--- /dev/null
+package org.simantics.ui.workspace.tracker.internal.contributions;
+
+/**
+ * Preference constants for the heap status.
+ *
+ * @author Tuukka Lehtonen
+ * @since 1.31.0
+ */
+public interface IWorkspaceSizeTrackerConstants {
+
+ String P_NODE = "org.simantics.ui.workspace.tracker";
+
+ /**
+ * Boolean preference key for whether or not to show the status bar workspace
+ * size monitor trim.
+ */
+ String PREF_SHOW_MONITOR = "WorkspaceSizeTracker.showMonitor"; //$NON-NLS-1$
+
+ /**
+ * Preference key for the update interval (value in milliseconds).
+ */
+ String PREF_UPDATE_INTERVAL = "WorkspaceSizeTracker.updateInterval"; //$NON-NLS-1$
+
+ /**
+ * Boolean preference key for whether to highlight to the user when low on disk space.
+ */
+ String PREF_HIGHLIGHT_LOW_SPACE = "WorkspaceSizeTracker.highlightLowSpace"; //$NON-NLS-1$
+
+ /**
+ * Preference key for the low space threshold (value in megabytes).
+ */
+ String PREF_LOW_SPACE_THRESHOLD = "WorkspaceSizeTracker.lowSpaceThreshold"; //$NON-NLS-1$
+
+}
--- /dev/null
+package org.simantics.ui.workspace.tracker.internal.contributions;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.31.0
+ */
+public class Messages extends NLS {
+
+ private static final String BUNDLE_NAME = "org.simantics.ui.workspace.tracker.internal.contributions.messages";//$NON-NLS-1$
+
+ //==============================================================
+ // Workspace size trim
+
+ public static String WorkspaceSizeTrackerTrim_close;
+ public static String WorkspaceSizeTrackerTrim_status;
+ public static String WorkspaceSizeTrackerTrim_widthStr;
+ public static String WorkspaceSizeTrackerTrim_memoryToolTip;
+ public static String WorkspaceSizeTrackerTrim_meg;
+ public static String WorkspaceSizeTrackerTrim_gig;
+ public static String WorkspaceSizeTrackerTrim_noMark;
+
+ public static String SetMarkAction_text;
+ public static String ClearMarkAction_text;
+ public static String ShowMaxAction_text;
+
+ static {
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+}
\ No newline at end of file
--- /dev/null
+package org.simantics.ui.workspace.tracker.internal.contributions;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.e4.core.contexts.IEclipseContext;
+import org.eclipse.e4.ui.model.application.MApplication;
+import org.eclipse.e4.ui.model.application.ui.MUIElement;
+import org.eclipse.e4.ui.model.application.ui.menu.MToolControl;
+import org.eclipse.e4.ui.workbench.modeling.EModelService;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.ui.PlatformUI;
+import org.simantics.filesystem.services.sizetracker.DirectorySizeService;
+import org.simantics.filesystem.services.sizetracker.SizeTracker;
+import org.simantics.ui.workspace.tracker.internal.Activator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.31.0
+ */
+public class WorkspaceSizeTrackerContribution {
+
+ private Logger logger = LoggerFactory.getLogger(WorkspaceSizeTrackerContribution.class);
+
+ private SizeTracker workspaceSizeTracker;
+
+ @PostConstruct
+ void createControls(Composite parent, MToolControl toolControl) {
+ String trackSize = System.getProperty("org.simantics.filesystem.services.sizeTracker", null);
+ if (trackSize != null && trackSize.equalsIgnoreCase("false"))
+ return;
+ Path ws = getWorkspacePath();
+ if (ws != null && !Files.isDirectory(ws))
+ return;
+ DirectorySizeService dss = Activator.getDefault().getDirectorySizeService();
+ if (dss == null)
+ return;
+
+ try {
+ workspaceSizeTracker = dss.track(ws);
+ new WorkspaceSizeTrackerTrim(parent, toolControl, workspaceSizeTracker, Activator.getDefault().getPreferenceStore());
+ } catch (IOException e) {
+ logger.error("Failed to start workspace size tracking for {}", ws, e);
+ }
+ }
+
+ @PreDestroy
+ void dispose() {
+ try (SizeTracker t = workspaceSizeTracker) {
+ } catch (IOException e) {
+ logger.error("Failed to shutdown workspace size tracking for {}", workspaceSizeTracker, e);
+ } finally {
+ workspaceSizeTracker = null;
+ }
+ }
+
+ private static Path getWorkspacePath() {
+ IPath ip = Platform.getLocation();
+ return ip != null ? ip.toFile().toPath() : null;
+ }
+
+ public static void showTracker(boolean show) {
+ IEclipseContext context = PlatformUI.getWorkbench().getService(IEclipseContext.class);
+ if (context == null)
+ return;
+
+ EModelService modelService = context.get(EModelService.class);
+ MApplication app = context.get(MApplication.class);
+ if (modelService == null || app == null)
+ return;
+
+ MUIElement element = modelService.find("org.simantics.ui.workspace.tracker.toolcontrol.0", app);
+ if (element != null && element.isToBeRendered() != show) {
+ element.setToBeRendered(show);
+ Object widget = element.getWidget();
+ if (widget instanceof Control) {
+ ((Control) widget).getShell().layout(null, SWT.ALL | SWT.CHANGED | SWT.DEFER);
+ }
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+/*******************************************************************************
+ * Copyright (c) 2017 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:
+ * Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.ui.workspace.tracker.internal.contributions;
+
+import java.io.IOException;
+import java.nio.file.FileStore;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.eclipse.e4.ui.model.application.ui.menu.MToolControl;
+import org.eclipse.jface.action.Action;
+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.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.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.Shell;
+import org.simantics.filesystem.services.sizetracker.SizeTracker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The Heap Status control, which shows the heap usage statistics in the window trim.
+ *
+ * @since 3.1
+ */
+public class WorkspaceSizeTrackerTrim extends Composite {
+
+ private Logger logger = LoggerFactory.getLogger(WorkspaceSizeTrackerTrim.class);
+
+ private MToolControl toolControl;
+ private SizeTracker sizeTracker;
+ private IPreferenceStore prefStore;
+
+ private Color bgCol, usedSpaceCol, lowSpaceCol, topLeftCol, bottomRightCol, sepCol, textCol;
+ @SuppressWarnings("unused")
+ private Color markCol;
+
+ private int updateInterval;
+
+ private String storeName;
+ private long totalSpace;
+ private long availableSpace;
+ private long usedSpace;
+ private long prevTotalSpace = -1L;
+ private long prevAvailableSpace = -1L;
+ private long prevUsedSpace = -1L;
+
+ private boolean hasChanged;
+ private long mark = -1;
+
+ /**
+ * How many MB of free disk space means we are low on disk space?
+ */
+ private long lowSpaceThreshold = 500;
+ private boolean highlightLowSpace = true;
+
+ private boolean updateTooltip = false;
+
+ private final Runnable timer = new Runnable() {
+ @Override
+ public void run() {
+ if (!isDisposed()) {
+ safeUpdateStats();
+ if (hasChanged) {
+ if (updateTooltip) {
+ updateToolTip();
+ }
+ redraw();
+ hasChanged = false;
+ }
+ getDisplay().timerExec(updateInterval, this);
+ }
+ }
+ };
+
+ private final IPropertyChangeListener prefListener = event -> {
+ if (IWorkspaceSizeTrackerConstants.PREF_UPDATE_INTERVAL.equals(event.getProperty())) {
+ setUpdateIntervalInMS(prefStore.getInt(IWorkspaceSizeTrackerConstants.PREF_UPDATE_INTERVAL));
+ } else if (IWorkspaceSizeTrackerConstants.PREF_HIGHLIGHT_LOW_SPACE.equals(event.getProperty())) {
+ highlightLowSpace = prefStore.getBoolean(IWorkspaceSizeTrackerConstants.PREF_HIGHLIGHT_LOW_SPACE);
+ hasChanged = true;
+ } else if (IWorkspaceSizeTrackerConstants.PREF_LOW_SPACE_THRESHOLD.equals(event.getProperty())) {
+ lowSpaceThreshold = prefStore.getLong(IWorkspaceSizeTrackerConstants.PREF_LOW_SPACE_THRESHOLD);
+ hasChanged = true;
+ } else if (IWorkspaceSizeTrackerConstants.PREF_SHOW_MONITOR.equals(event.getProperty())) {
+ boolean show = prefStore.getBoolean(IWorkspaceSizeTrackerConstants.PREF_SHOW_MONITOR);
+ if (!show)
+ showTracker(false);
+ }
+ };
+
+ /**
+ * 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 toolControl
+ *
+ * @param parent the parent composite
+ * @param sizeTracker the workspace sizeTracker service
+ * @param prefStore the preference store
+ */
+ public WorkspaceSizeTrackerTrim(Composite parent, MToolControl toolControl, SizeTracker sizeTracker, IPreferenceStore prefStore) {
+ super(parent, SWT.NONE);
+ this.toolControl = toolControl;
+ this.sizeTracker = sizeTracker;
+
+ this.prefStore = prefStore;
+ prefStore.addPropertyChangeListener(prefListener);
+
+ setUpdateIntervalInMS(prefStore.getInt(IWorkspaceSizeTrackerConstants.PREF_UPDATE_INTERVAL));
+
+ Display display = getDisplay();
+ usedSpaceCol = display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
+ lowSpaceCol = new Color(display, 255, 70, 70); // medium red
+ bgCol = display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND);
+ sepCol = topLeftCol = display.getSystemColor(SWT.COLOR_WIDGET_NORMAL_SHADOW);
+ bottomRightCol = display.getSystemColor(SWT.COLOR_WIDGET_HIGHLIGHT_SHADOW);
+ markCol = textCol = display.getSystemColor(SWT.COLOR_WIDGET_FOREGROUND);
+
+ createContextMenu();
+
+ Listener listener = event -> {
+ switch (event.type) {
+ case SWT.Dispose:
+ doDispose();
+ break;
+ case SWT.Paint:
+ if (event.widget == WorkspaceSizeTrackerTrim.this) {
+ paintComposite(event.gc);
+ }
+ break;
+ case SWT.MouseDown:
+ if (event.button == 1) {
+ if (event.widget == WorkspaceSizeTrackerTrim.this) {
+ setMark();
+ }
+ }
+ break;
+ case SWT.MouseEnter:
+ WorkspaceSizeTrackerTrim.this.updateTooltip = true;
+ updateToolTip();
+ break;
+ case SWT.MouseExit:
+ if (event.widget == WorkspaceSizeTrackerTrim.this) {
+ WorkspaceSizeTrackerTrim.this.updateTooltip = false;
+ }
+ break;
+ }
+ };
+ addListener(SWT.Dispose, listener);
+ addListener(SWT.MouseDown, listener);
+ addListener(SWT.Paint, listener);
+ addListener(SWT.MouseEnter, listener);
+ addListener(SWT.MouseExit, listener);
+
+ // make sure stats are updated before first paint
+ safeUpdateStats();
+
+ getDisplay().asyncExec(() -> {
+ if (!isDisposed()) {
+ getDisplay().timerExec(updateInterval, timer);
+ }
+ });
+ }
+
+ @Override
+ public void setBackground(Color color) {
+ bgCol = color;
+ }
+
+ @Override
+ public void setForeground(Color color) {
+ if (color == null) {
+ markCol = textCol = getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND);
+ } else {
+ markCol = textCol = color;
+ }
+ }
+
+ @Override
+ public Color getForeground() {
+ if (usedSpaceCol != null) {
+ return usedSpaceCol;
+ }
+ return getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND);
+ }
+
+ private void setUpdateIntervalInMS(int interval) {
+ updateInterval = Math.max(100, interval);
+ }
+
+ private void doDispose() {
+ prefStore.removePropertyChangeListener(prefListener);
+ if (lowSpaceCol != null) {
+ lowSpaceCol.dispose();
+ }
+ }
+
+ @Override
+ public Point computeSize(int wHint, int hHint, boolean changed) {
+ GC gc = new GC(this);
+ Point p = gc.textExtent(Messages.WorkspaceSizeTrackerTrim_widthStr);
+ int height = p.y + 4;
+ gc.dispose();
+ return new Point(p.x, height);
+ }
+
+ /**
+ * Creates the context menu
+ */
+ private void createContextMenu() {
+ MenuManager menuMgr = new MenuManager();
+ menuMgr.setRemoveAllWhenShown(true);
+ menuMgr.addMenuListener(menuMgr1 -> fillMenu(menuMgr1));
+ Menu menu = menuMgr.createContextMenu(this);
+ setMenu(menu);
+ }
+
+ private void fillMenu(IMenuManager menuMgr) {
+ menuMgr.add(new SetMarkAction());
+ menuMgr.add(new ClearMarkAction());
+ menuMgr.add(new CloseSizeTrackerTrimAction());
+ }
+
+ /**
+ * Sets the mark to the current usedMem level.
+ */
+ private void setMark() {
+ safeUpdateStats(); // get up-to-date stats before taking the mark
+ mark = usedSpace;
+ hasChanged = true;
+ redraw();
+ }
+
+ /**
+ * Clears the mark.
+ */
+ private void clearMark() {
+ mark = -1;
+ hasChanged = true;
+ redraw();
+ }
+
+ private void paintComposite(GC gc) {
+ paintCompositeMaxUnknown(gc);
+ }
+
+ private void paintCompositeMaxUnknown(GC gc) {
+ Rectangle rect = getClientArea();
+ int x = rect.x;
+ int y = rect.y;
+ int w = rect.width;
+ int h = rect.height;
+ int sw = w - 1; // status width
+ long storeUsedSpace = totalSpace - availableSpace;
+ int uw = (int) (sw * storeUsedSpace / totalSpace); // used space width
+ int ux = x + 1 + uw; // used space right edge
+ if (bgCol != null) {
+ gc.setBackground(bgCol);
+ }
+ gc.fillRectangle(rect);
+
+ boolean lowOnSpace = false;
+ if (highlightLowSpace) {
+ lowOnSpace = (1024L*1024L*lowSpaceThreshold) >= availableSpace;
+ }
+
+ gc.setForeground(sepCol);
+ 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(lowOnSpace ? lowSpaceCol : usedSpaceCol);
+ gc.fillRectangle(x + 1, y + 1, uw, h - 2);
+
+ String s = NLS.bind(Messages.WorkspaceSizeTrackerTrim_status, convertToSizeString(usedSpace), convertToSizeString(availableSpace));
+ Point p = gc.textExtent(s);
+ int sx = (rect.width - 15 - p.x) / 2 + rect.x + 1;
+ int sy = (rect.height - 2 - p.y) / 2 + rect.y + 1;
+ gc.setForeground(textCol);
+ gc.drawString(s, sx, sy, true);
+ }
+
+ private void safeUpdateStats() {
+ try {
+ updateStats();
+ } catch (IOException e) {
+ logger.error("Failed to update workspace size statistics.", e);
+ }
+ }
+
+ private void updateStats() throws IOException {
+ Path path = sizeTracker.path();
+ FileStore store = Files.getFileStore(path);
+
+ storeName = store.toString();
+ totalSpace = store.getTotalSpace();
+ availableSpace = store.getUsableSpace();
+ usedSpace = sizeTracker.size();
+
+ if (convertToMeg(prevTotalSpace) != convertToMeg(totalSpace)) {
+ prevTotalSpace = totalSpace;
+ this.hasChanged = true;
+ }
+ if (prevAvailableSpace != availableSpace) {
+ prevAvailableSpace = availableSpace;
+ this.hasChanged = true;
+ }
+ if (convertToMeg(prevUsedSpace) != convertToMeg(usedSpace)) {
+ prevUsedSpace = usedSpace;
+ this.hasChanged = true;
+ }
+ }
+
+ private void updateToolTip() {
+ String usedStr = convertToSizeString(usedSpace);
+ String availableStr = convertToSizeString(availableSpace);
+ String totalStr = convertToSizeString(totalSpace);
+ String markStr = mark == -1 ? Messages.WorkspaceSizeTrackerTrim_noMark : convertToSizeString(mark);
+ String toolTip = NLS.bind(Messages.WorkspaceSizeTrackerTrim_memoryToolTip, new Object[] { usedStr, storeName, availableStr, totalStr, markStr });
+ if (!toolTip.equals(getToolTipText())) {
+ setToolTipText(toolTip);
+ }
+ }
+
+ /**
+ * Converts the given number of bytes to a printable number of megabytes (rounded up).
+ */
+ private String convertToSizeString(long numBytes) {
+ long megs = convertToMeg(numBytes);
+ if (megs > 10000) {
+ double megsd = (double) megs;
+ long gigs = (long) Math.floor(megsd / 1024.0);
+ long decimals = (long) (megsd - gigs*1024);
+ decimals = (decimals + 5) / 10;
+ return NLS.bind(Messages.WorkspaceSizeTrackerTrim_gig, new Long(gigs), new Long(decimals));
+ } else {
+ return NLS.bind(Messages.WorkspaceSizeTrackerTrim_meg, new Long(megs));
+ }
+ }
+
+ /**
+ * Converts the given number of bytes to the corresponding number of megabytes (rounded up).
+ */
+ private long convertToMeg(long numBytes) {
+ return (numBytes + (512 * 1024)) / (1024 * 1024);
+ }
+
+ class SetMarkAction extends Action {
+ SetMarkAction() {
+ super(Messages.SetMarkAction_text);
+ }
+
+ @Override
+ public void run() {
+ setMark();
+ }
+ }
+
+ class ClearMarkAction extends Action {
+ ClearMarkAction() {
+ super(Messages.ClearMarkAction_text);
+ }
+
+ @Override
+ public void run() {
+ clearMark();
+ }
+ }
+
+ class CloseSizeTrackerTrimAction extends Action{
+ CloseSizeTrackerTrimAction(){
+ super(Messages.WorkspaceSizeTrackerTrim_close);
+ }
+
+ @Override
+ public void run(){
+ showTracker(false);
+ }
+ }
+
+ private void showTracker(boolean show) {
+ if (toolControl.isToBeRendered() != show) {
+ Object widget = toolControl.getWidget();
+ Shell shell = widget instanceof Control ? ((Control) widget).getShell() : null;
+ toolControl.setToBeRendered(show);
+ if (shell != null)
+ shell.layout(null, SWT.ALL | SWT.CHANGED | SWT.DEFER);
+ prefStore.setValue(IWorkspaceSizeTrackerConstants.PREF_SHOW_MONITOR, show);
+ }
+ }
+
+}
\ No newline at end of file
--- /dev/null
+###############################################################################\r
+# Copyright (c) 2017 Association for Decentralized Information Management in\r
+# 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
+# Semantum Oy - initial API and implementation\r
+###############################################################################\r
+\r
+# package: org.simantics.ui.workspace.tracker.internal.contributions\r
+\r
+#==============================================================\r
+# Workspace Size Tracker\r
+\r
+WorkspaceSizeTrackerTrim_close=&Close\r
+WorkspaceSizeTrackerTrim_status={0} / {1}\r
+WorkspaceSizeTrackerTrim_widthStr=MMMMMMMMMMMM\r
+WorkspaceSizeTrackerTrim_memoryToolTip=Workspace size: {0} {1} free/total space: {2}/{3} mark: {4}\r
+WorkspaceSizeTrackerTrim_meg={0}M\r
+WorkspaceSizeTrackerTrim_gig={0}.{1}G\r
+WorkspaceSizeTrackerTrim_noMark=<none>\r
+\r
+SetMarkAction_text=&Set Mark\r
+ClearMarkAction_text=&Clear Mark\r
+ShowMaxAction_text=Show &Max Size\r
--- /dev/null
+package org.simantics.ui.workspace.tracker.internal.preferences;
+
+import org.eclipse.osgi.util.NLS;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public class Messages extends NLS {
+
+ private static final String BUNDLE_NAME = "org.simantics.ui.workspace.tracker.internal.preferences.messages";//$NON-NLS-1$
+
+ public static String WorkspaceSizeTrackingPreferencePage_Workspace_Size_Tracking_Settings;
+ public static String WorkspaceSizeTrackingPreferencePage_Show_Monitor;
+ public static String WorkspaceSizeTrackingPreferencePage_Update_Interval;
+ public static String WorkspaceSizeTrackingPreferencePage_Highlight_Low_Space;
+ public static String WorkspaceSizeTrackingPreferencePage_Low_Space_Threshold;
+
+ static {
+ // load message values from bundle file
+ NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+ }
+
+}
--- /dev/null
+package org.simantics.ui.workspace.tracker.internal.preferences;
+
+import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer;
+import org.eclipse.core.runtime.preferences.DefaultScope;
+import org.eclipse.core.runtime.preferences.IScopeContext;
+import org.osgi.service.prefs.Preferences;
+import org.simantics.ui.workspace.tracker.internal.contributions.IWorkspaceSizeTrackerConstants;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.31.0
+ */
+public class WorkspaceSizeTrackingPreferenceInitializer extends AbstractPreferenceInitializer {
+
+ public WorkspaceSizeTrackingPreferenceInitializer() {
+ }
+
+ @Override
+ public void initializeDefaultPreferences() {
+ IScopeContext context = DefaultScope.INSTANCE;
+ Preferences node = context.getNode(IWorkspaceSizeTrackerConstants.P_NODE);
+ node.putBoolean(IWorkspaceSizeTrackerConstants.PREF_SHOW_MONITOR, true);
+ node.putInt(IWorkspaceSizeTrackerConstants.PREF_UPDATE_INTERVAL, 1000);
+ node.putBoolean(IWorkspaceSizeTrackerConstants.PREF_HIGHLIGHT_LOW_SPACE, true);
+ node.putLong(IWorkspaceSizeTrackerConstants.PREF_LOW_SPACE_THRESHOLD, 500);
+ }
+
+}
--- /dev/null
+package org.simantics.ui.workspace.tracker.internal.preferences;
+
+import org.eclipse.jface.preference.BooleanFieldEditor;
+import org.eclipse.jface.preference.FieldEditorPreferencePage;
+import org.eclipse.jface.preference.IntegerFieldEditor;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.simantics.ui.workspace.tracker.internal.Activator;
+import org.simantics.ui.workspace.tracker.internal.contributions.IWorkspaceSizeTrackerConstants;
+import org.simantics.ui.workspace.tracker.internal.contributions.WorkspaceSizeTrackerContribution;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.31.0
+ */
+public class WorkspaceSizeTrackingPreferencePage extends FieldEditorPreferencePage implements IWorkbenchPreferencePage {
+
+ private BooleanFieldEditor fShowSizeMonitor;
+ private IntegerFieldEditor fUpdateInterval;
+ private BooleanFieldEditor fHighlightLowSpace;
+ private IntegerFieldEditor fLowSpaceThreshold;
+
+ /**
+ * Create the console page.
+ */
+ public WorkspaceSizeTrackingPreferencePage() {
+ super(GRID);
+ setDescription(Messages.WorkspaceSizeTrackingPreferencePage_Workspace_Size_Tracking_Settings);
+ setPreferenceStore(Activator.getDefault().getPreferenceStore());
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.preference.PreferencePage#createControl(Composite)
+ */
+ @Override
+ public void createControl(Composite parent) {
+ super.createControl(parent);
+ }
+
+ /**
+ * Create all field editors for this page
+ */
+ @Override
+ public void createFieldEditors() {
+ fShowSizeMonitor = new BooleanFieldEditor(IWorkspaceSizeTrackerConstants.PREF_SHOW_MONITOR, Messages.WorkspaceSizeTrackingPreferencePage_Show_Monitor, SWT.NONE, getFieldEditorParent());
+ addField(fShowSizeMonitor);
+ fUpdateInterval = new IntegerFieldEditor(IWorkspaceSizeTrackerConstants.PREF_UPDATE_INTERVAL, Messages.WorkspaceSizeTrackingPreferencePage_Update_Interval, getFieldEditorParent());
+ fUpdateInterval.setValidRange(100, 10000);
+ addField(fUpdateInterval);
+ fHighlightLowSpace = new BooleanFieldEditor(IWorkspaceSizeTrackerConstants.PREF_HIGHLIGHT_LOW_SPACE, Messages.WorkspaceSizeTrackingPreferencePage_Highlight_Low_Space, SWT.NONE, getFieldEditorParent());
+ addField(fHighlightLowSpace);
+ fLowSpaceThreshold = new IntegerFieldEditor(IWorkspaceSizeTrackerConstants.PREF_LOW_SPACE_THRESHOLD, Messages.WorkspaceSizeTrackingPreferencePage_Low_Space_Threshold, getFieldEditorParent());
+ fLowSpaceThreshold.setValidRange(100, 500000);
+ addField(fLowSpaceThreshold);
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.ui.IWorkbenchPreferencePage#init(org.eclipse.ui.IWorkbench)
+ */
+ @Override
+ public void init(IWorkbench workbench) {
+ }
+
+ /* (non-Javadoc)
+ * @see org.eclipse.jface.preference.FieldEditorPreferencePage#performOk()
+ */
+ @Override
+ public boolean performOk() {
+ boolean show = fShowSizeMonitor.getBooleanValue();
+ WorkspaceSizeTrackerContribution.showTracker(show);
+ return super.performOk();
+ }
+
+}
--- /dev/null
+WorkspaceSizeTrackingPreferencePage_Workspace_Size_Tracking_Settings=Workspace Size Tracking Settings\r
+WorkspaceSizeTrackingPreferencePage_Show_Monitor=Sho&w workspace size monitor in status bar\r
+WorkspaceSizeTrackingPreferencePage_Update_Interval=Monitor &update interval (ms)\r
+WorkspaceSizeTrackingPreferencePage_Highlight_Low_Space=Highlight low disk space\r
+WorkspaceSizeTrackingPreferencePage_Low_Space_Threshold=Low disk space threshold (MB)\r
<module>org.simantics.threadlog</module>
<module>org.simantics.trend</module>
<module>org.simantics.ui</module>
+ <module>org.simantics.ui.workspace.tracker</module>
<module>org.simantics.user.ontology</module>
<module>org.simantics.utils</module>
<module>org.simantics.utils.datastructures</module>
version="0.0.0"
unpack="false"/>
+ <plugin
+ id="org.simantics.ui.workspace.tracker"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
<plugin
id="org.simantics.backup.ontology"
download-size="0"