From b7250834202635a09dd18e25370ed9b4c32b1380 Mon Sep 17 00:00:00 2001
From: Tuukka Lehtonen
Date: Thu, 13 Dec 2018 13:43:37 +0200
Subject: [PATCH] Revert "Usability fixes for GraphExplorerImpl -related WB
selection propagation"
This reverts commit 270834ce3962a4bca3945d06e642a99d21688c16.
---
.../ui/platform/PropertyPageView.java | 115 +++++++--
.../browsing/ui/swt/GraphExplorerImpl.java | 241 +++++++++++++-----
.../browsing/ui/swt/UpdateRunner.java | 12 +-
.../ui/jface/BasePostSelectionProvider.java | 95 ++++++-
.../utils/ui/jface/BaseSelectionProvider.java | 22 +-
.../views/swt/client/impl/SWTExplorer.java | 114 ++++++---
.../META-INF/MANIFEST.MF | 3 +-
.../org/simantics/views/swt/ModelledView.java | 47 ++--
8 files changed, 486 insertions(+), 163 deletions(-)
diff --git a/bundles/org.simantics.browsing.ui.platform/src/org/simantics/browsing/ui/platform/PropertyPageView.java b/bundles/org.simantics.browsing.ui.platform/src/org/simantics/browsing/ui/platform/PropertyPageView.java
index 05109c813..0d4fc055b 100644
--- a/bundles/org.simantics.browsing.ui.platform/src/org/simantics/browsing/ui/platform/PropertyPageView.java
+++ b/bundles/org.simantics.browsing.ui.platform/src/org/simantics/browsing/ui/platform/PropertyPageView.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2018 Association for Decentralized Information Management
+ * 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
@@ -11,10 +11,17 @@
*******************************************************************************/
package org.simantics.browsing.ui.platform;
+import java.util.HashSet;
import java.util.Map;
+import java.util.Set;
import java.util.WeakHashMap;
import java.util.function.Consumer;
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IExtension;
+import org.eclipse.core.runtime.IExtensionPoint;
+import org.eclipse.core.runtime.IExtensionRegistry;
+import org.eclipse.core.runtime.RegistryFactory;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
@@ -31,6 +38,7 @@ import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPart3;
import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.part.IContributedContentsView;
import org.eclipse.ui.part.IPage;
@@ -41,6 +49,8 @@ import org.simantics.db.management.ISessionContextProvider;
import org.simantics.selectionview.PropertyPage;
import org.simantics.ui.workbench.IPropertyPage;
import org.simantics.ui.workbench.ResourceInput;
+import org.simantics.utils.threads.SWTThread;
+import org.simantics.utils.threads.Throttler;
import org.simantics.utils.ui.BundleUtils;
import org.simantics.utils.ui.SWTUtils;
@@ -81,12 +91,19 @@ import org.simantics.utils.ui.SWTUtils;
* @see IPropertyPage
* @see PropertyPage
*/
-public class PropertyPageView extends PageBookView implements IContributedContentsView {
+public class PropertyPageView extends PageBookView implements ISelectionListener, IContributedContentsView {
+
+ /**
+ * Extension point used to modify behavior of the view
+ */
+ private static final String EXT_POINT = "org.eclipse.ui.propertiesView"; //$NON-NLS-1$
private static final String PROPERTY_VIEW_CONTEXT = "org.simantics.modeling.ui.properties";
private static final String PROP_PINNED = "pinned";
+ protected static final long SELECTION_CHANGE_THRESHOLD = 500;
+
private ISessionContextProvider contextProvider;
/**
@@ -107,7 +124,7 @@ public class PropertyPageView extends PageBookView implements IContributedConten
private IWorkbenchPart lastPart;
private ISelection lastSelection;
- private final Map lastSelections = new WeakHashMap<>();
+ private final Map lastSelections = new WeakHashMap();
private ResourceManager resourceManager;
@@ -115,10 +132,9 @@ public class PropertyPageView extends PageBookView implements IContributedConten
private ImageDescriptor pinned;
/**
- * The workbench post-selection listener for this view that changes the
- * input of the pagebook page for the part which changed its selection.
+ * Set of workbench parts, which should not be used as a source for PropertySheet
*/
- private ISelectionListener selectionListener = this::doSelectionChanged;
+ private Set ignoredViews;
@Override
public void createPartControl(Composite parent) {
@@ -195,12 +211,13 @@ public class PropertyPageView extends PageBookView implements IContributedConten
// This prevents the Properties view from providing a selection to other
// workbench parts, thus making them lose their selections which is not
// desirable.
- site.setSelectionProvider(null);
+// site.setSelectionProvider(null);
contextProvider = Simantics.getSessionContextProvider();
if (!bootstrapOnly) {
- site.getPage().addPostSelectionListener(selectionListener);
+ site.getPage().addSelectionListener(immediateSelectionListener);
+ site.getPage().addPostSelectionListener(this);
}
}
@@ -229,7 +246,8 @@ public class PropertyPageView extends PageBookView implements IContributedConten
// Remove ourselves as a workbench selection listener.
if (!bootstrapOnly) {
- getSite().getPage().removePostSelectionListener(selectionListener);
+ getSite().getPage().removePostSelectionListener(this);
+ getSite().getPage().removeSelectionListener(immediateSelectionListener);
}
if (resourceManager != null) {
@@ -246,7 +264,7 @@ public class PropertyPageView extends PageBookView implements IContributedConten
page.createControl(book);
page.setMessage(Messages.PropertyPageView_noPropertiesAvailable);
return page;
- */
+ */
PropertyPage page = new PropertyPage(getSite());
initPage(page);
@@ -258,6 +276,7 @@ public class PropertyPageView extends PageBookView implements IContributedConten
@Override
protected PageRec doCreatePage(IWorkbenchPart part) {
+
// NOTE: If the default page should be shown, this method must return null.
if (part == null)
return null;
@@ -315,10 +334,37 @@ public class PropertyPageView extends PageBookView implements IContributedConten
return this == part || ignore;
}
+ private Set getIgnoredViews() {
+ if (ignoredViews == null) {
+ ignoredViews = new HashSet();
+ IExtensionRegistry registry = RegistryFactory.getRegistry();
+ IExtensionPoint ep = registry.getExtensionPoint(EXT_POINT);
+ if (ep != null) {
+ IExtension[] extensions = ep.getExtensions();
+ for (int i = 0; i < extensions.length; i++) {
+ IConfigurationElement[] elements = extensions[i].getConfigurationElements();
+ for (int j = 0; j < elements.length; j++) {
+ if ("excludeSources".equalsIgnoreCase(elements[j].getName())) { //$NON-NLS-1$
+ String id = elements[j].getAttribute("id"); //$NON-NLS-1$
+ if (id != null)
+ ignoredViews.add(id);
+ }
+ }
+ }
+ }
+ }
+ return ignoredViews;
+ }
+
+ private boolean isViewIgnored(String partID) {
+ return getIgnoredViews().contains(partID);
+ }
+
@Override
protected boolean isImportant(IWorkbenchPart part) {
- //System.out.println("isImportant(" + part.getSite().getId() + ")");
- return !isWorkbenchSelectionPinned() && !isPropertyView(part);
+ String partID = part.getSite().getId();
+ //System.out.println("isImportant(" + partID + ")");
+ return !isWorkbenchSelectionPinned() && !isPropertyView(part) && !isViewIgnored(partID);
}
/**
@@ -371,10 +417,39 @@ public class PropertyPageView extends PageBookView implements IContributedConten
// super.partHidden(part);
}
+ ISelectionListener immediateSelectionListener = new ISelectionListener() {
+
+ private Throttler throttler = new Throttler(SWTThread.getThreadAccess(PlatformUI.getWorkbench().getDisplay()), 500, 3);
+
+ @Override
+ public void selectionChanged(final IWorkbenchPart part, final ISelection selection) {
+
+ // Do not process selections from self
+ if(PropertyPageView.this == part) return;
+
+ throttler.schedule(new Runnable() {
+
+ @Override
+ public void run() {
+ PropertyPageView.this.doSelectionChanged(part, selection);
+ }
+
+ });
+
+ }
+ };
+
public ISelection getLastSelection() {
return lastSelection;
}
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.ui.ISelectionListener#selectionChanged(org.eclipse.ui.IWorkbenchPart,
+ * org.eclipse.jface.viewers.ISelection)
+ */
+ @Override
public void selectionChanged(IWorkbenchPart part, ISelection sel) {
doSelectionChanged(part, sel);
}
@@ -386,6 +461,7 @@ public class PropertyPageView extends PageBookView implements IContributedConten
* false otherwise
*/
boolean doSelectionChanged(IWorkbenchPart part, ISelection sel) {
+
// we ignore our own selection or null selection
if (isPropertyView(part) || sel == null) {
return false;
@@ -423,8 +499,8 @@ public class PropertyPageView extends PageBookView implements IContributedConten
lastPart.addPropertyListener(partPropertyListener);
}
+ updatePartName(ppage, sel);
if (!sameSelection) {
- updatePartName(ppage, sel);
ppage.selectionChanged(part, sel);
return true;
}
@@ -440,11 +516,14 @@ public class PropertyPageView extends PageBookView implements IContributedConten
// This check is not safe - there might be a burst of changes incoming
//if (getPartName().equals(parameter)) return;
//System.out.println("partNameUpdateCallback : " + parameter);
- SWTUtils.asyncExec(getPageBook(), () -> {
- if (!getPageBook().isDisposed()) {
- if (getPartName().equals(parameter)) return;
- //System.out.println("doSetParameterName : " + parameter);
- doSetPartName(parameter);
+ SWTUtils.asyncExec(getPageBook(), new Runnable() {
+ @Override
+ public void run() {
+ if (!getPageBook().isDisposed()) {
+ if (getPartName().equals(parameter)) return;
+ //System.out.println("doSetParameterName : " + parameter);
+ doSetPartName(parameter);
+ }
}
});
};
diff --git a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl.java b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl.java
index 0168ad864..df736c1e6 100644
--- a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl.java
+++ b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/GraphExplorerImpl.java
@@ -50,7 +50,6 @@ import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.resource.LocalResourceManager;
import org.eclipse.jface.resource.ResourceManager;
-import org.eclipse.jface.util.OpenStrategy;
import org.eclipse.jface.viewers.IPostSelectionProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
@@ -69,6 +68,7 @@ import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
@@ -289,6 +289,24 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
public static final int DEFAULT_MAX_CHILDREN = 1000;
+ private static final long POST_SELECTION_DELAY = 300;
+
+ /**
+ * The time in milliseconds that must elapse between consecutive
+ * {@link Tree} {@link SelectionListener#widgetSelected(SelectionEvent)}
+ * invocations in order for this class to construct a new selection.
+ *
+ *
+ * This is done because selection construction can be very expensive as the
+ * selected set grows larger when the user is pressing shift+arrow keys.
+ * GraphExplorerImpl will naturally listen to all changes in the tree
+ * selection, but as an optimization will not construct new
+ * StructuredSelection instances for every selection change event. A new
+ * selection will be constructed and set only if the selection hasn't
+ * changed for the amount of milliseconds specified by this constant.
+ */
+ private static final long SELECTION_CHANGE_QUIET_TIME = 150;
+
private final IThreadWorkQueue thread;
/**
@@ -310,11 +328,11 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
Tree tree;
@SuppressWarnings({ "rawtypes" })
- final HashMap, NodeQueryProcessor> processors = new HashMap<>();
+ final HashMap, NodeQueryProcessor> processors = new HashMap, NodeQueryProcessor>();
@SuppressWarnings({ "rawtypes" })
- final HashMap
*/
- BijectionMap contextToItem = new BijectionMap<>();
+ BijectionMap contextToItem = new BijectionMap();
/**
* Columns of the UI viewer. Use {@link #setColumns(Column[])} to
* initialize.
*/
Column[] columns = new Column[0];
- Map columnKeyToIndex = new HashMap<>();
+ Map columnKeyToIndex = new HashMap();
boolean refreshingColumnSizes = false;
boolean columnsAreVisible = true;
@@ -519,12 +537,12 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
/** Set to true when the Tree widget is disposed. */
private boolean disposed = false;
- private final CopyOnWriteArrayList focusListeners = new CopyOnWriteArrayList<>();
- private final CopyOnWriteArrayList mouseListeners = new CopyOnWriteArrayList<>();
- private final CopyOnWriteArrayList keyListeners = new CopyOnWriteArrayList<>();
+ private final CopyOnWriteArrayList focusListeners = new CopyOnWriteArrayList();
+ private final CopyOnWriteArrayList mouseListeners = new CopyOnWriteArrayList();
+ private final CopyOnWriteArrayList keyListeners = new CopyOnWriteArrayList();
/** Selection provider */
- private GraphExplorerPostSelectionProvider postSelectionProvider = new GraphExplorerPostSelectionProvider(this);
+ private GraphExplorerPostSelectionProvider postSelectionProvider = new GraphExplorerPostSelectionProvider(this);
protected BasePostSelectionProvider selectionProvider = new BasePostSelectionProvider();
protected SelectionDataResolver selectionDataResolver;
protected SelectionFilter selectionFilter;
@@ -552,12 +570,12 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
* item was a part of the current selection in which case the selection must
* be updated.
*/
- private final Map selectedItems = new HashMap<>();
+ private final Map selectedItems = new HashMap();
/**
* TODO: specify what this is for
*/
- private final Set selectionRefreshContexts = new HashSet<>();
+ private final Set selectionRefreshContexts = new HashSet();
/**
* If this field is non-null, it means that if {@link #setData(Event)}
@@ -631,7 +649,7 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
*
* @see #setPendingImages(IProgressMonitor)
*/
- Map imageTasks = new THashMap<>();
+ Map imageTasks = new THashMap();
/**
* A state flag indicating whether the vertical scroll bar was visible for
@@ -695,7 +713,7 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
updateCounter = 0;
uiUpdateScheduler.schedule(this, 50, TimeUnit.MILLISECONDS);
} else {
- tree.getDisplay().asyncExec(new UpdateRunner(GraphExplorerImpl.this));
+ tree.getDisplay().asyncExec(new UpdateRunner(GraphExplorerImpl.this, GraphExplorerImpl.this.explorerContext));
}
}
@@ -770,7 +788,7 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
* modified. These are used internally to prevent duplicate edits from being
* initiated which should always be a sensible thing to do.
*/
- private Set currentlyModifiedNodes = new THashSet<>();
+ private Set currentlyModifiedNodes = new THashSet();
private final TreeEditor editor;
private Color invalidModificationColor = null;
@@ -1363,14 +1381,17 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
// Keep track of the previous single selection to help
// decide whether to start editing a tree node on mouse
// downs or not.
- tree.addListener(SWT.Selection, event -> {
- TreeItem[] selection = tree.getSelection();
- if (selection.length == 1) {
- //for (TreeItem item : selection)
- // System.out.println("selection: " + item);
- previousSingleSelection = selection[0];
- } else {
- previousSingleSelection = null;
+ tree.addListener(SWT.Selection, new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ TreeItem[] selection = tree.getSelection();
+ if (selection.length == 1) {
+ //for (TreeItem item : selection)
+ // System.out.println("selection: " + item);
+ previousSingleSelection = selection[0];
+ } else {
+ previousSingleSelection = null;
+ }
}
});
@@ -1472,33 +1493,39 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
};
tree.addListener(SWT.MouseDown, mouseEditListener);
tree.addListener(SWT.DragDetect, mouseEditListener);
- tree.addListener(SWT.DragDetect, event -> {
- Point test = new Point(event.x, event.y);
- TreeItem item = tree.getItem(test);
- if(item != null) {
- for(int i=0;i {
- Point test = new Point(event.x, event.y);
- TreeItem item = tree.getItem(test);
- if(item != null) {
- for(int i=0;i {
- //System.out.println("OPENSTRATEGY: post selection changed: " + e);
- resetSelection();
- selectionProvider.firePostSelection(selectionProvider.getSelection());
- }));
+ // Add a tree selection listener for keeping the selection of
+ // GraphExplorer's ISelectionProvider up-to-date.
+ tree.addSelectionListener(new SelectionListener() {
+ @Override
+ public void widgetDefaultSelected(SelectionEvent e) {
+ widgetSelected(e);
+ }
+ @Override
+ public void widgetSelected(SelectionEvent e) {
+ widgetSelectionChanged(false);
+ }
+ });
// This listener takes care of updating the set of currently selected
// TreeItem instances. This set is needed because we need to know in
@@ -1578,14 +1611,108 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
});
}
+ /**
+ * Mod count for delaying post selection changed events.
+ */
+ int postSelectionModCount = 0;
+
+ /**
+ * Last tree selection modification time for implementing a quiet
+ * time for selection changes.
+ */
+ long lastSelectionModTime = System.currentTimeMillis() - 10000;
+
+ /**
+ * Current target time for the selection to be set. Calculated
+ * according to the set quiet time and last selection modification
+ * time.
+ */
+ long selectionSetTargetTime = 0;
+
+ /**
+ * true if delayed selection runnable is current scheduled or
+ * running.
+ */
+ boolean delayedSelectionScheduled = false;
+
+ Runnable SELECTION_DELAY = new Runnable() {
+ @Override
+ public void run() {
+ if (tree.isDisposed())
+ return;
+ long now = System.currentTimeMillis();
+ long waitTimeLeft = selectionSetTargetTime - now;
+ if (waitTimeLeft > 0) {
+ // Not enough quiet time, reschedule.
+ delayedSelectionScheduled = true;
+ tree.getDisplay().timerExec((int) waitTimeLeft, this);
+ } else {
+ // Time to perform selection, stop rescheduling.
+ delayedSelectionScheduled = false;
+ resetSelection();
+ }
+ }
+ };
+
+ private void widgetSelectionChanged(boolean forceSelectionChange) {
+ long modTime = System.currentTimeMillis();
+ long delta = modTime - lastSelectionModTime;
+ lastSelectionModTime = modTime;
+ if (!forceSelectionChange && delta < SELECTION_CHANGE_QUIET_TIME) {
+ long msToWait = SELECTION_CHANGE_QUIET_TIME - delta;
+ selectionSetTargetTime = modTime + msToWait;
+ if (!delayedSelectionScheduled) {
+ delayedSelectionScheduled = true;
+ tree.getDisplay().timerExec((int) msToWait, SELECTION_DELAY);
+ }
+ // Make sure that post selection change events do not fire.
+ ++postSelectionModCount;
+ return;
+ }
+
+ // Immediate selection reconstruction.
+ resetSelection();
+ }
+
private void resetSelection() {
final ISelection selection = getWidgetSelection();
-// System.out.println("resetSelection()");
-// System.out.println(" provider selection: " + selectionProvider.getSelection());
-// System.out.println(" widget selection: " + selection);
+
+ //System.out.println("resetSelection(" + postSelectionModCount + ")");
+ //System.out.println(" provider selection: " + selectionProvider.getSelection());
+ //System.out.println(" widget selection: " + selection);
+
selectionProvider.setAndFireNonEqualSelection(selection);
- }
+ // Implement deferred firing of post selection events
+ final int count = ++postSelectionModCount;
+ //System.out.println("[" + System.currentTimeMillis() + "] scheduling postSelectionChanged " + count + ": " + selection);
+ ThreadUtils.getNonBlockingWorkExecutor().schedule(new Runnable() {
+ @Override
+ public void run() {
+ int newCount = postSelectionModCount;
+ // Don't publish selection yet, there's another change incoming.
+ //System.out.println("[" + System.currentTimeMillis() + "] checking post selection publish: " + count + " vs. " + newCount + ": " + selection);
+ if (newCount != count)
+ return;
+ //System.out.println("[" + System.currentTimeMillis() + "] " + count + " count equals, firing post selection listeners: " + selection);
+
+ if (tree.isDisposed())
+ return;
+
+ //System.out.println("scheduling fire post selection changed: " + selection);
+ tree.getDisplay().asyncExec(new Runnable() {
+ @Override
+ public void run() {
+ if (tree.isDisposed() || selectionProvider == null)
+ return;
+ //System.out.println("firing post selection changed: " + selection);
+ selectionProvider.firePostSelection(selection);
+ }
+ });
+ }
+ }, POST_SELECTION_DELAY, TimeUnit.MILLISECONDS);
+ }
+
protected void setDefaultProcessors() {
// Add a simple IMAGER query processor that always returns null.
// With this processor no images will ever be shown.
@@ -2300,7 +2427,7 @@ class GraphExplorerImpl extends GraphExplorerImplBase implements Listener, Graph
// System.out.println("MODCOUNT: " + modCount + " vs. " + count);
if (modCount != count)
return;
- resetSelection();
+ widgetSelectionChanged(true);
}
});
}
diff --git a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/UpdateRunner.java b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/UpdateRunner.java
index 80ef2bf39..72c17ed74 100644
--- a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/UpdateRunner.java
+++ b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/UpdateRunner.java
@@ -21,9 +21,8 @@ import org.simantics.browsing.ui.CheckedState;
import org.simantics.browsing.ui.NodeContext;
import org.simantics.browsing.ui.NodeQueryManager;
import org.simantics.browsing.ui.common.internal.GENodeQueryManager;
+import org.simantics.browsing.ui.common.internal.IGraphExplorerContext;
import org.simantics.browsing.ui.content.PrunedChildrenResult;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* This class is responsible for updating the {@link TreeItem}s contained by the
@@ -37,20 +36,21 @@ import org.slf4j.LoggerFactory;
*/
class UpdateRunner implements Runnable {
- private static final Logger LOGGER = LoggerFactory.getLogger(UpdateRunner.class);
-
final GraphExplorerImpl ge;
+ //final IGraphExplorerContext geContext;
- UpdateRunner(GraphExplorerImpl ge) {
+ UpdateRunner(GraphExplorerImpl ge, IGraphExplorerContext geContext) {
this.ge = ge;
+ // this.geContext = geContext;
}
public void run() {
try {
doRun();
} catch (Throwable t) {
- LOGGER.error("", t);
+ t.printStackTrace();
}
+
}
public void doRun() {
diff --git a/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/jface/BasePostSelectionProvider.java b/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/jface/BasePostSelectionProvider.java
index b06143bf6..c5ca0e754 100644
--- a/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/jface/BasePostSelectionProvider.java
+++ b/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/jface/BasePostSelectionProvider.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2018 Association for Decentralized Information Management
+ * 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
@@ -21,6 +21,8 @@ import org.eclipse.jface.viewers.IPostSelectionProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.simantics.utils.ObjectUtils;
/**
* BaseSelectionProvider is a base implementation ISelectionProvider -interface.
@@ -34,21 +36,40 @@ import org.eclipse.jface.viewers.SelectionChangedEvent;
*
*
* @author Toni Kalajainen
- * @author Tuukka Lehtonen
*/
-public class BasePostSelectionProvider extends BaseSelectionProvider implements IPostSelectionProvider {
+public class BasePostSelectionProvider implements IPostSelectionProvider {
- protected ListenerList postSelectionListeners = new ListenerList<>();
+ protected ListenerList selectionListeners = new ListenerList();
+
+ protected ListenerList postSelectionListeners = new ListenerList();
+
+ protected ISelection selection = StructuredSelection.EMPTY;
+
+ public void addSelectionChangedListener(ISelectionChangedListener listener) {
+ selectionListeners.add(listener);
+ }
+
+ public ISelection getSelection() {
+ return selection;
+ }
public void clearListeners() {
- super.clearListeners();
- clearPostSelectionChangedListeners();
+ selectionListeners.clear();
+ postSelectionListeners.clear();
+ }
+
+ public void clearSelectionChangedListeners() {
+ postSelectionListeners.clear();
}
public void clearPostSelectionChangedListeners() {
postSelectionListeners.clear();
}
+ public void removeSelectionChangedListener(ISelectionChangedListener listener) {
+ selectionListeners.remove(listener);
+ }
+
@Override
public void addPostSelectionChangedListener(ISelectionChangedListener listener) {
postSelectionListeners.add(listener);
@@ -59,10 +80,30 @@ public class BasePostSelectionProvider extends BaseSelectionProvider implements
postSelectionListeners.remove(listener);
}
+ public void setSelection(ISelection selection) {
+ setSelectionWithoutFiring(selection);
+ }
+
+ protected Object[] getListeners() {
+ return selectionListeners.getListeners();
+ }
+
protected Object[] getPostListeners() {
return postSelectionListeners.getListeners();
}
+ /**
+ * Notify other UIs that selection has changed
+ * @param selection new selection
+ */
+ public void fireSelection(ISelection selection) {
+ if (selection == null)
+ return;
+ SelectionChangedEvent e = new SelectionChangedEvent(this, selection);
+ for (Object l : getListeners())
+ ((ISelectionChangedListener) l).selectionChanged(e);
+ }
+
/**
* Notify other UIs that selection has changed
* @param selection new selection
@@ -82,4 +123,46 @@ public class BasePostSelectionProvider extends BaseSelectionProvider implements
}
}
+ public void setSelectionWithoutFiring(ISelection selection) {
+ this.selection = selection;
+ }
+
+
+ /**
+ * Sets a new selection and always fires a SelectionChangedEvent about it.
+ *
+ * @param selection the new selection
+ */
+ public void setAndFireSelection(ISelection selection) {
+ setSelection(selection);
+ fireSelection(selection);
+ }
+
+ /**
+ * Sets the new selection for this provider and fires all selection change
+ * listeners if the specified selection differs from the current selection.
+ * If the selection is either the same object or considered equal to the
+ * current selection, the listeners are not fired.
+ *
+ * @param selection the new selection
+ */
+ public void setAndFireNonEqualSelection(ISelection selection) {
+ ISelection old = getSelection();
+ if (ObjectUtils.objectEquals(old, selection))
+ return;
+
+ this.selection = selection;
+ if (selection != null && !selection.equals(old))
+ fireSelection(selection);
+ }
+
+ public boolean selectionEquals(ISelection s) {
+ if (s == selection)
+ return true;
+ if (s == null)
+ // Old selection had to be non-null
+ return true;
+ return s.equals(selection);
+ }
+
}
diff --git a/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/jface/BaseSelectionProvider.java b/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/jface/BaseSelectionProvider.java
index 55ec0241b..b2e6d9215 100644
--- a/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/jface/BaseSelectionProvider.java
+++ b/bundles/org.simantics.utils.ui/src/org/simantics/utils/ui/jface/BaseSelectionProvider.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2007, 2018 Association for Decentralized Information Management
+ * 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
@@ -20,7 +20,6 @@ import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
-import org.simantics.utils.ObjectUtils;
/**
* BaseSelectionProvider is a base implementation ISelectionProvider -interface.
@@ -40,7 +39,7 @@ import org.simantics.utils.ObjectUtils;
*/
public class BaseSelectionProvider implements ISelectionProvider {
- protected ListenerList selectionListeners = new ListenerList<>();
+ protected ListenerList selectionListeners = new ListenerList();
protected ISelection selection = StructuredSelection.EMPTY;
@@ -60,14 +59,6 @@ public class BaseSelectionProvider implements ISelectionProvider {
return selection;
}
- public void clearListeners() {
- clearSelectionChangedListeners();
- }
-
- public void clearSelectionChangedListeners() {
- selectionListeners.clear();
- }
-
public void removeSelectionChangedListener(ISelectionChangedListener listener) {
selectionListeners.remove(listener);
}
@@ -115,15 +106,14 @@ public class BaseSelectionProvider implements ISelectionProvider {
*
* @param selection the new selection
*/
- public boolean setAndFireNonEqualSelection(ISelection selection) {
+ public void setAndFireNonEqualSelection(ISelection selection) {
ISelection old = getSelection();
- if (ObjectUtils.objectEquals(old, selection))
- return false;
+ if (selection == old)
+ return;
this.selection = selection;
- if (selection != null)
+ if (selection != null && !selection.equals(old))
fireSelection(selection);
- return true;
}
public boolean selectionEquals(ISelection s) {
diff --git a/bundles/org.simantics.views.swt.client/src/org/simantics/views/swt/client/impl/SWTExplorer.java b/bundles/org.simantics.views.swt.client/src/org/simantics/views/swt/client/impl/SWTExplorer.java
index e196e6732..1666413e9 100644
--- a/bundles/org.simantics.views.swt.client/src/org/simantics/views/swt/client/impl/SWTExplorer.java
+++ b/bundles/org.simantics.views.swt.client/src/org/simantics/views/swt/client/impl/SWTExplorer.java
@@ -10,8 +10,11 @@ import org.eclipse.jface.viewers.IPostSelectionProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
import org.eclipse.ui.IWorkbenchSite;
import org.simantics.browsing.ui.Column;
import org.simantics.browsing.ui.StatePersistor;
@@ -42,19 +45,9 @@ public class SWTExplorer extends SingleSWTViewNode {
public Boolean useNodeBrowseContexts;
public Boolean useNodeActionContexts;
public StatePersistor persistor;
-
+
public ISelection lastSelection;
-
- private ISelectionChangedListener internalToExternalSelectionPropagator = event -> {
- IWorkbenchSite site = getSite();
- if (site != null) {
- ISelectionProvider sp = site.getSelectionProvider();
- if (sp != null) {
- sp.setSelection(event.getSelection());
- }
- }
- };
-
+
@Override
public void createControls(Composite parent) {
@@ -77,30 +70,80 @@ public class SWTExplorer extends SingleSWTViewNode {
if (uiContext != null) {
control.setUiContexts(Collections.singleton(uiContext));
}
-
+
control.setStatePersistor(persistor);
-
+
control.finish();
setProperties();
-
+
control.setInputSource(PassThruInputSource.INSTANCE);
- ISelectionProvider isp = (ISelectionProvider)control.getExplorer().getAdapter(ISelectionProvider.class);
- if (isp instanceof IPostSelectionProvider) {
- ((IPostSelectionProvider) isp).addPostSelectionChangedListener(internalToExternalSelectionPropagator);
- } else {
- isp.addSelectionChangedListener(internalToExternalSelectionPropagator);
- }
-
- control.addListenerToControl(SWT.Selection, event -> {
- if(selectionListener != null)
- selectionListener.apply(event);
- ISelection selection = (ISelection)control.getExplorer().getWidgetSelection();
- propertyCallback.apply("selection", selection);
- lastSelection = selection;
+ ISelectionProvider sp = (ISelectionProvider)control.getExplorer().getAdapter(ISelectionProvider.class);
+ sp.addSelectionChangedListener(new ISelectionChangedListener() {
+
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+ if (site != null) {
+ ISelectionProvider sp = site.getSelectionProvider();
+ if (sp != null) {
+ sp.setSelection(event.getSelection());
+ }
+ }
+ }
+
});
-
+
+ IPostSelectionProvider psp = (IPostSelectionProvider)control.getExplorer().getAdapter(IPostSelectionProvider.class);
+ psp.addPostSelectionChangedListener(new ISelectionChangedListener() {
+
+ @Override
+ public void selectionChanged(SelectionChangedEvent event) {
+
+// ISelection selection = (ISelection)control.getExplorer().getWidgetSelection();
+ if (site != null) {
+ ISelectionProvider sp = site.getSelectionProvider();
+ if (sp != null) {
+ sp.setSelection(event.getSelection());
+ }
+ }
+
+ }
+
+ });
+
+ control.addListenerToControl(SWT.Selection, new Listener() {
+
+ @Override
+ public void handleEvent(Event event) {
+
+ if(selectionListener != null)
+ selectionListener.apply(event);
+
+ ISelection selection = (ISelection)control.getExplorer().getWidgetSelection();
+ // [Tuukka@2012-04-08] Disabled this because it was causing
+ // horrible selection feedback effects in the Model Browser
+ // view that is using it. It causes the browser to react to
+ // external selections which were initially published as its own
+ // with a delay.
+ //System.out.println("selection: " + selection);
+// if(publishSelection != null && publishSelection) {
+// if (site != null) {
+// ISelectionProvider sp = site.getSelectionProvider();
+// if (sp != null) {
+// sp.setSelection(selection);
+// }
+// }
+// }
+
+ propertyCallback.apply("selection", selection);
+
+ lastSelection = selection;
+
+ }
+
+ });
+
}
public void synchronizeColumnsVisible(Boolean columnsVisible) {
@@ -148,16 +191,5 @@ public class SWTExplorer extends SingleSWTViewNode {
final public void synchronizeLayout(LayoutBean layout) {
}
-
- @Override
- public void dispose() {
- ISelectionProvider isp = (ISelectionProvider)control.getExplorer().getAdapter(ISelectionProvider.class);
- if (isp instanceof IPostSelectionProvider) {
- ((IPostSelectionProvider) isp).removePostSelectionChangedListener(internalToExternalSelectionPropagator);
- } else {
- isp.removeSelectionChangedListener(internalToExternalSelectionPropagator);
- }
- super.dispose();
- }
-
+
}
diff --git a/bundles/org.simantics.views.swt/META-INF/MANIFEST.MF b/bundles/org.simantics.views.swt/META-INF/MANIFEST.MF
index cd17a1872..18048f38c 100644
--- a/bundles/org.simantics.views.swt/META-INF/MANIFEST.MF
+++ b/bundles/org.simantics.views.swt/META-INF/MANIFEST.MF
@@ -16,8 +16,7 @@ Require-Bundle: org.simantics.browsing.ui.swt;bundle-version="1.1.0";visibility:
org.simantics.project;bundle-version="1.0.1",
org.simantics.scenegraph.loader;bundle-version="1.0.0";visibility:=reexport,
org.simantics.scenegraph.ontology;bundle-version="1.0.0",
- org.simantics.utils.thread.swt;bundle-version="1.1.0",
- org.slf4j.api
+ org.simantics.utils.thread.swt;bundle-version="1.1.0"
Export-Package: org.simantics.views.swt
Bundle-Activator: org.simantics.views.swt.Activator
Bundle-Vendor: Semantum Oy
diff --git a/bundles/org.simantics.views.swt/src/org/simantics/views/swt/ModelledView.java b/bundles/org.simantics.views.swt/src/org/simantics/views/swt/ModelledView.java
index 92396f421..f50954857 100644
--- a/bundles/org.simantics.views.swt/src/org/simantics/views/swt/ModelledView.java
+++ b/bundles/org.simantics.views.swt/src/org/simantics/views/swt/ModelledView.java
@@ -27,6 +27,7 @@ import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchSite;
import org.simantics.Simantics;
+import org.simantics.browsing.ui.common.ErrorLogger;
import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;
import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupportImpl;
import org.simantics.db.ReadGraph;
@@ -35,6 +36,7 @@ import org.simantics.db.VirtualGraph;
import org.simantics.db.WriteGraph;
import org.simantics.db.common.request.WriteRequest;
import org.simantics.db.common.request.WriteResultRequest;
+import org.simantics.db.common.utils.Logger;
import org.simantics.db.exception.DatabaseException;
import org.simantics.db.exception.ServiceNotFoundException;
import org.simantics.db.layer0.util.RemoverUtil;
@@ -45,11 +47,8 @@ import org.simantics.layer0.Layer0;
import org.simantics.scenegraph.ontology.ScenegraphResources;
import org.simantics.scl.runtime.function.Function1;
import org.simantics.ui.workbench.IPropertyPage;
-import org.simantics.utils.ui.ErrorLogger;
-import org.simantics.utils.ui.jface.BasePostSelectionProvider;
+import org.simantics.utils.ui.jface.ActiveSelectionProvider;
import org.simantics.views.swt.client.base.SWTRoot;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
/**
* To use this class, first model your view contents in .pgraph files according
@@ -68,8 +67,6 @@ import org.slf4j.LoggerFactory;
*/
public class ModelledView extends SimanticsView implements IPartListener2 {
- private static final Logger LOGGER = LoggerFactory.getLogger(ModelledView.class);
-
public static final int TIME_BEFORE_DISPOSE_WHEN_HIDDEN = 30000; // ms
private static final boolean DEBUG = false;
@@ -91,11 +88,10 @@ public class ModelledView extends SimanticsView implements IPartListener2 {
protected ModelledSupport support;
- private BasePostSelectionProvider selectionProvider = new BasePostSelectionProvider() {
+ ActiveSelectionProvider selectionProvider = new ActiveSelectionProvider() {
@Override
public void setSelection(ISelection selection) {
- super.setAndFireNonEqualSelection(selection);
- super.firePostSelection(selection);
+ super.setSelection(selection);
}
};
@@ -105,6 +101,7 @@ public class ModelledView extends SimanticsView implements IPartListener2 {
@Override
protected WidgetSupportImpl createSupport() {
+
try {
runtime = Simantics.getSession().sync(
new WriteResultRequest(Simantics.getSession().getService(VirtualGraph.class)) {
@@ -117,13 +114,16 @@ public class ModelledView extends SimanticsView implements IPartListener2 {
return runtime;
}
});
- } catch (ServiceNotFoundException | DatabaseException e) {
- LOGGER.error("Failed to initialize modelled view database runtime support structures", e);
+ } catch (ServiceNotFoundException e) {
+ Logger.defaultLogError(e);
+ } catch (DatabaseException e) {
+ Logger.defaultLogError(e);
}
support = new ModelledSupport(this);
return support;
+
}
public void fireInput() {
@@ -166,7 +166,9 @@ public class ModelledView extends SimanticsView implements IPartListener2 {
}
if (load) {
+
try {
+
loader = new SWTViewLoaderProcess(this, getSite(), getClass().getSimpleName());
viewVariable = loader.getVariable(Simantics.getSession(), configurationURI(), runtime);
@@ -198,10 +200,17 @@ public class ModelledView extends SimanticsView implements IPartListener2 {
body.layout(true);
+ getSite().setSelectionProvider(selectionProvider);
+
} catch (DatabaseException e) {
- LOGGER.error("Failed to create modelled SWT view controls", e);
+
+ e.printStackTrace();
+ Logger.defaultLogError(e);
+
}
+
}
+
}
@Override
@@ -211,12 +220,14 @@ public class ModelledView extends SimanticsView implements IPartListener2 {
// Only create controls if the part is TRULY visible.
// Fast view parts seem to cause calls to createPartControl even
// when the part is hidden in reality
+ boolean visible = site.getPage().isPartVisible(this);
if (DEBUG)
System.out.println(this + ": createControls( visible=" + site.getPage().isPartVisible(this) + " )");
doCreateControls(true);
getSite().setSelectionProvider(selectionProvider);
getSite().getPage().addPartListener(this);
+
}
protected void inputChanged(IWorkbenchPart provider, Object input) {
@@ -280,8 +291,10 @@ public class ModelledView extends SimanticsView implements IPartListener2 {
RemoverUtil.remove(graph, rt);
}
});
- } catch (ServiceNotFoundException | DatabaseException e) {
- LOGGER.error("Failed to dispose of modelled view database runtime support structures", e);
+ } catch (ServiceNotFoundException e) {
+ Logger.defaultLogError(e);
+ } catch (DatabaseException e) {
+ Logger.defaultLogError(e);
}
}
@@ -381,10 +394,10 @@ public class ModelledView extends SimanticsView implements IPartListener2 {
}
}
}
-
+
// Can be used to cancel already scheduled dispose
volatile boolean reallyClearExisting = false;
-
+
Runnable clearExisting = new Runnable() {
@Override
@@ -432,5 +445,5 @@ public class ModelledView extends SimanticsView implements IPartListener2 {
protected IPropertyPage getPropertyPage() {
return null;
}
-
+
}
--
2.47.1