/*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2018 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
*******************************************************************************/
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;
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;
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;
* @see IPropertyPage
* @see PropertyPage
*/
-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$
+public class PropertyPageView extends PageBookView implements IContributedContentsView {
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;
/**
private IWorkbenchPart lastPart;
private ISelection lastSelection;
- private final Map<IWorkbenchPart, ISelection> lastSelections = new WeakHashMap<IWorkbenchPart, ISelection>();
+ private final Map<IWorkbenchPart, ISelection> lastSelections = new WeakHashMap<>();
private ResourceManager resourceManager;
private ImageDescriptor pinned;
/**
- * Set of workbench parts, which should not be used as a source for PropertySheet
+ * The workbench post-selection listener for this view that changes the
+ * input of the pagebook page for the part which changed its selection.
*/
- private Set<String> ignoredViews;
+ private ISelectionListener selectionListener = this::doSelectionChanged;
@Override
public void createPartControl(Composite parent) {
// 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().addSelectionListener(immediateSelectionListener);
- site.getPage().addPostSelectionListener(this);
+ site.getPage().addPostSelectionListener(selectionListener);
}
}
// Remove ourselves as a workbench selection listener.
if (!bootstrapOnly) {
- getSite().getPage().removePostSelectionListener(this);
- getSite().getPage().removeSelectionListener(immediateSelectionListener);
+ getSite().getPage().removePostSelectionListener(selectionListener);
}
if (resourceManager != null) {
page.createControl(book);
page.setMessage(Messages.PropertyPageView_noPropertiesAvailable);
return page;
- */
+ */
PropertyPage page = new PropertyPage(getSite());
initPage(page);
@Override
protected PageRec doCreatePage(IWorkbenchPart part) {
-
// NOTE: If the default page should be shown, this method must return null.
if (part == null)
return null;
return this == part || ignore;
}
- private Set<String> getIgnoredViews() {
- if (ignoredViews == null) {
- ignoredViews = new HashSet<String>();
- 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) {
- String partID = part.getSite().getId();
- //System.out.println("isImportant(" + partID + ")");
- return !isWorkbenchSelectionPinned() && !isPropertyView(part) && !isViewIgnored(partID);
+ //System.out.println("isImportant(" + part.getSite().getId() + ")");
+ return !isWorkbenchSelectionPinned() && !isPropertyView(part);
}
/**
// 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);
}
* <code>false</code> otherwise
*/
boolean doSelectionChanged(IWorkbenchPart part, ISelection sel) {
-
// we ignore our own selection or null selection
if (isPropertyView(part) || sel == null) {
return false;
lastPart.addPropertyListener(partPropertyListener);
}
- updatePartName(ppage, sel);
if (!sameSelection) {
+ updatePartName(ppage, sel);
ppage.selectionChanged(part, sel);
return true;
}
// 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(), new Runnable() {
- @Override
- public void run() {
- if (!getPageBook().isDisposed()) {
- if (getPartName().equals(parameter)) return;
- //System.out.println("doSetParameterName : " + parameter);
- doSetPartName(parameter);
- }
+ SWTUtils.asyncExec(getPageBook(), () -> {
+ if (!getPageBook().isDisposed()) {
+ if (getPartName().equals(parameter)) return;
+ //System.out.println("doSetParameterName : " + parameter);
+ doSetPartName(parameter);
}
});
};
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;
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;
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.
- *
- * <p>
- * 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;
/**
Tree tree;
@SuppressWarnings({ "rawtypes" })
- final HashMap<CacheKey<?>, NodeQueryProcessor> processors = new HashMap<CacheKey<?>, NodeQueryProcessor>();
+ final HashMap<CacheKey<?>, NodeQueryProcessor> processors = new HashMap<>();
@SuppressWarnings({ "rawtypes" })
- final HashMap<Object, PrimitiveQueryProcessor> primitiveProcessors = new HashMap<Object, PrimitiveQueryProcessor>();
+ final HashMap<Object, PrimitiveQueryProcessor> primitiveProcessors = new HashMap<>();
@SuppressWarnings({ "rawtypes" })
- final HashMap<Class, DataSource> dataSources = new HashMap<Class, DataSource>();
+ final HashMap<Class, DataSource> dataSources = new HashMap<>();
class GraphExplorerContext extends AbstractDisposable implements IGraphExplorerContext {
// This is for query debugging only.
* <code>null</code> there's nothing scheduled yet in which case
* scheduling can commence. Otherwise the update should be skipped.
*/
- AtomicReference<Runnable> currentQueryUpdater = new AtomicReference<Runnable>();
+ AtomicReference<Runnable> currentQueryUpdater = new AtomicReference<>();
/**
* Keeps track of nodes that have already been auto-expanded. After
* expanded state after that. This makes it possible for the user to
* close auto-expanded nodes.
*/
- Map<NodeContext, Boolean> autoExpanded = new WeakHashMap<NodeContext, Boolean>();
+ Map<NodeContext, Boolean> autoExpanded = new WeakHashMap<>();
@Override
GraphExplorerContext explorerContext = new GraphExplorerContext();
- HashSet<TreeItem> pendingItems = new HashSet<TreeItem>();
+ HashSet<TreeItem> pendingItems = new HashSet<>();
boolean updating = false;
boolean pendingRoot = false;
* Access this map only in the SWT thread to keep it thread-safe.
* </p>
*/
- BijectionMap<NodeContext, TreeItem> contextToItem = new BijectionMap<NodeContext, TreeItem>();
+ BijectionMap<NodeContext, TreeItem> contextToItem = new BijectionMap<>();
/**
* Columns of the UI viewer. Use {@link #setColumns(Column[])} to
* initialize.
*/
Column[] columns = new Column[0];
- Map<String, Integer> columnKeyToIndex = new HashMap<String, Integer>();
+ Map<String, Integer> columnKeyToIndex = new HashMap<>();
boolean refreshingColumnSizes = false;
boolean columnsAreVisible = true;
/** Set to true when the Tree widget is disposed. */
private boolean disposed = false;
- private final CopyOnWriteArrayList<FocusListener> focusListeners = new CopyOnWriteArrayList<FocusListener>();
- private final CopyOnWriteArrayList<MouseListener> mouseListeners = new CopyOnWriteArrayList<MouseListener>();
- private final CopyOnWriteArrayList<KeyListener> keyListeners = new CopyOnWriteArrayList<KeyListener>();
+ private final CopyOnWriteArrayList<FocusListener> focusListeners = new CopyOnWriteArrayList<>();
+ private final CopyOnWriteArrayList<MouseListener> mouseListeners = new CopyOnWriteArrayList<>();
+ private final CopyOnWriteArrayList<KeyListener> 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;
* item was a part of the current selection in which case the selection must
* be updated.
*/
- private final Map<TreeItem, NodeContext> selectedItems = new HashMap<TreeItem, NodeContext>();
+ private final Map<TreeItem, NodeContext> selectedItems = new HashMap<>();
/**
* TODO: specify what this is for
*/
- private final Set<NodeContext> selectionRefreshContexts = new HashSet<NodeContext>();
+ private final Set<NodeContext> selectionRefreshContexts = new HashSet<>();
/**
* If this field is non-null, it means that if {@link #setData(Event)}
*
* @see #setPendingImages(IProgressMonitor)
*/
- Map<TreeItem, ImageTask> imageTasks = new THashMap<TreeItem, ImageTask>();
+ Map<TreeItem, ImageTask> imageTasks = new THashMap<>();
/**
* A state flag indicating whether the vertical scroll bar was visible for
updateCounter = 0;
uiUpdateScheduler.schedule(this, 50, TimeUnit.MILLISECONDS);
} else {
- tree.getDisplay().asyncExec(new UpdateRunner(GraphExplorerImpl.this, GraphExplorerImpl.this.explorerContext));
+ tree.getDisplay().asyncExec(new UpdateRunner(GraphExplorerImpl.this));
}
}
* modified. These are used internally to prevent duplicate edits from being
* initiated which should always be a sensible thing to do.
*/
- private Set<NodeContext> currentlyModifiedNodes = new THashSet<NodeContext>();
+ private Set<NodeContext> currentlyModifiedNodes = new THashSet<>();
private final TreeEditor editor;
private Color invalidModificationColor = null;
// 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, 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;
- }
+ 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.MouseDown, mouseEditListener);
tree.addListener(SWT.DragDetect, mouseEditListener);
- tree.addListener(SWT.DragDetect, new Listener() {
- @Override
- public void handleEvent(Event event) {
- Point test = new Point(event.x, event.y);
- TreeItem item = tree.getItem(test);
- if(item != null) {
- for(int i=0;i<tree.getColumnCount();i++) {
- Rectangle rect = item.getBounds(i);
- if(rect.contains(test)) {
- tree.setData(KEY_DRAG_COLUMN, i);
- return;
- }
+ 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<tree.getColumnCount();i++) {
+ Rectangle rect = item.getBounds(i);
+ if(rect.contains(test)) {
+ tree.setData(KEY_DRAG_COLUMN, i);
+ return;
}
}
- tree.setData(KEY_DRAG_COLUMN, -1);
}
+ tree.setData(KEY_DRAG_COLUMN, -1);
});
- tree.addListener(SWT.MouseMove, new Listener() {
- @Override
- public void handleEvent(Event event) {
- Point test = new Point(event.x, event.y);
- TreeItem item = tree.getItem(test);
- if(item != null) {
- for(int i=0;i<tree.getColumnCount();i++) {
- Rectangle rect = item.getBounds(i);
- if(rect.contains(test)) {
- transientState.setActiveColumn(i);
- return;
- }
+ tree.addListener(SWT.MouseMove, event -> {
+ Point test = new Point(event.x, event.y);
+ TreeItem item = tree.getItem(test);
+ if(item != null) {
+ for(int i=0;i<tree.getColumnCount();i++) {
+ Rectangle rect = item.getBounds(i);
+ if(rect.contains(test)) {
+ transientState.setActiveColumn(i);
+ return;
}
}
- transientState.setActiveColumn(null);
}
+ transientState.setActiveColumn(null);
});
// Add focus/mouse/key listeners for supporting the respective
}
});
- // 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);
- }
- });
+ OpenStrategy os = new OpenStrategy(tree);
+ os.addPostSelectionListener(SelectionListener.widgetSelectedAdapter(e -> {
+ //System.out.println("OPENSTRATEGY: post selection changed: " + e);
+ resetSelection();
+ selectionProvider.firePostSelection(selectionProvider.getSelection());
+ }));
// This listener takes care of updating the set of currently selected
// TreeItem instances. This set is needed because we need to know in
});
}
- /**
- * 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;
-
- /**
- * <code>true</code> 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(" + postSelectionModCount + ")");
- //System.out.println(" provider selection: " + selectionProvider.getSelection());
- //System.out.println(" widget selection: " + selection);
-
+// System.out.println("resetSelection()");
+// 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.
// System.out.println("MODCOUNT: " + modCount + " vs. " + count);
if (modCount != count)
return;
- widgetSelectionChanged(true);
+ resetSelection();
}
});
}
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
*/
class UpdateRunner implements Runnable {
+ private static final Logger LOGGER = LoggerFactory.getLogger(UpdateRunner.class);
+
final GraphExplorerImpl ge;
- //final IGraphExplorerContext geContext;
- UpdateRunner(GraphExplorerImpl ge, IGraphExplorerContext geContext) {
+ UpdateRunner(GraphExplorerImpl ge) {
this.ge = ge;
- // this.geContext = geContext;
}
public void run() {
try {
doRun();
} catch (Throwable t) {
- t.printStackTrace();
+ LOGGER.error("", t);
}
-
}
public void doRun() {
/*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2018 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
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.
* </p>
*
* @author Toni Kalajainen
+ * @author Tuukka Lehtonen
*/
-public class BasePostSelectionProvider implements IPostSelectionProvider {
+public class BasePostSelectionProvider extends BaseSelectionProvider implements IPostSelectionProvider {
- 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;
- }
+ protected ListenerList<ISelectionChangedListener> postSelectionListeners = new ListenerList<>();
public void clearListeners() {
- selectionListeners.clear();
- postSelectionListeners.clear();
- }
-
- public void clearSelectionChangedListeners() {
- postSelectionListeners.clear();
+ super.clearListeners();
+ clearPostSelectionChangedListeners();
}
public void clearPostSelectionChangedListeners() {
postSelectionListeners.clear();
}
- public void removeSelectionChangedListener(ISelectionChangedListener listener) {
- selectionListeners.remove(listener);
- }
-
@Override
public void addPostSelectionChangedListener(ISelectionChangedListener listener) {
postSelectionListeners.add(listener);
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
}
}
- 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);
- }
-
}
/*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2018 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
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.
*/
public class BaseSelectionProvider implements ISelectionProvider {
- protected ListenerList selectionListeners = new ListenerList();
+ protected ListenerList<ISelectionChangedListener> selectionListeners = new ListenerList<>();
protected ISelection selection = StructuredSelection.EMPTY;
return selection;
}
+ public void clearListeners() {
+ clearSelectionChangedListeners();
+ }
+
+ public void clearSelectionChangedListeners() {
+ selectionListeners.clear();
+ }
+
public void removeSelectionChangedListener(ISelectionChangedListener listener) {
selectionListeners.remove(listener);
}
*
* @param selection the new selection
*/
- public void setAndFireNonEqualSelection(ISelection selection) {
+ public boolean setAndFireNonEqualSelection(ISelection selection) {
ISelection old = getSelection();
- if (selection == old)
- return;
+ if (ObjectUtils.objectEquals(old, selection))
+ return false;
this.selection = selection;
- if (selection != null && !selection.equals(old))
+ if (selection != null)
fireSelection(selection);
+ return true;
}
public boolean selectionEquals(ISelection s) {
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;
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) {
if (uiContext != null) {
control.setUiContexts(Collections.singleton(uiContext));
}
-
+
control.setStatePersistor(persistor);
-
+
control.finish();
setProperties();
-
+
control.setInputSource(PassThruInputSource.INSTANCE);
- 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;
-
- }
-
+ 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;
});
-
+
}
public void synchronizeColumnsVisible(Boolean columnsVisible) {
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();
+ }
+
}
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.simantics.utils.thread.swt;bundle-version="1.1.0",
+ org.slf4j.api
Export-Package: org.simantics.views.swt
Bundle-Activator: org.simantics.views.swt.Activator
Bundle-Vendor: Semantum Oy
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;
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;
import org.simantics.scenegraph.ontology.ScenegraphResources;
import org.simantics.scl.runtime.function.Function1;
import org.simantics.ui.workbench.IPropertyPage;
-import org.simantics.utils.ui.jface.ActiveSelectionProvider;
+import org.simantics.utils.ui.ErrorLogger;
+import org.simantics.utils.ui.jface.BasePostSelectionProvider;
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
*/
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;
protected ModelledSupport support;
- ActiveSelectionProvider selectionProvider = new ActiveSelectionProvider() {
+ private BasePostSelectionProvider selectionProvider = new BasePostSelectionProvider() {
@Override
public void setSelection(ISelection selection) {
- super.setSelection(selection);
+ super.setAndFireNonEqualSelection(selection);
+ super.firePostSelection(selection);
}
};
@Override
protected WidgetSupportImpl createSupport() {
-
try {
runtime = Simantics.getSession().sync(
new WriteResultRequest<Resource>(Simantics.getSession().getService(VirtualGraph.class)) {
return runtime;
}
});
- } catch (ServiceNotFoundException e) {
- Logger.defaultLogError(e);
- } catch (DatabaseException e) {
- Logger.defaultLogError(e);
+ } catch (ServiceNotFoundException | DatabaseException e) {
+ LOGGER.error("Failed to initialize modelled view database runtime support structures", e);
}
support = new ModelledSupport(this);
return support;
-
}
public void fireInput() {
}
if (load) {
-
try {
-
loader = new SWTViewLoaderProcess(this, getSite(), getClass().getSimpleName());
viewVariable = loader.getVariable(Simantics.getSession(), configurationURI(), runtime);
body.layout(true);
- getSite().setSelectionProvider(selectionProvider);
-
} catch (DatabaseException e) {
-
- e.printStackTrace();
- Logger.defaultLogError(e);
-
+ LOGGER.error("Failed to create modelled SWT view controls", e);
}
-
}
-
}
@Override
// 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) {
RemoverUtil.remove(graph, rt);
}
});
- } catch (ServiceNotFoundException e) {
- Logger.defaultLogError(e);
- } catch (DatabaseException e) {
- Logger.defaultLogError(e);
+ } catch (ServiceNotFoundException | DatabaseException e) {
+ LOGGER.error("Failed to dispose of modelled view database runtime support structures", e);
}
}
}
}
}
-
+
// Can be used to cancel already scheduled dispose
volatile boolean reallyClearExisting = false;
-
+
Runnable clearExisting = new Runnable() {
@Override
protected IPropertyPage getPropertyPage() {
return null;
}
-
+
}