-/*******************************************************************************\r
- * Copyright (c) 2007, 2012 Association for Decentralized Information Management\r
- * in 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
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.browsing.ui.swt.widgets;\r
-\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.HashSet;\r
-import java.util.Map;\r
-import java.util.Set;\r
-import java.util.function.Consumer;\r
-\r
-import org.eclipse.core.runtime.IAdaptable;\r
-import org.eclipse.core.runtime.Platform;\r
-import org.eclipse.jface.action.IMenuManager;\r
-import org.eclipse.jface.layout.GridDataFactory;\r
-import org.eclipse.jface.layout.GridLayoutFactory;\r
-import org.eclipse.jface.layout.TreeColumnLayout;\r
-import org.eclipse.jface.resource.JFaceResources;\r
-import org.eclipse.jface.resource.LocalResourceManager;\r
-import org.eclipse.jface.viewers.ColumnWeightData;\r
-import org.eclipse.jface.viewers.ISelectionProvider;\r
-import org.eclipse.swt.SWT;\r
-import org.eclipse.swt.dnd.DND;\r
-import org.eclipse.swt.dnd.DragSource;\r
-import org.eclipse.swt.dnd.DragSourceEvent;\r
-import org.eclipse.swt.dnd.DragSourceListener;\r
-import org.eclipse.swt.dnd.DropTarget;\r
-import org.eclipse.swt.dnd.DropTargetEvent;\r
-import org.eclipse.swt.dnd.DropTargetListener;\r
-import org.eclipse.swt.dnd.FileTransfer;\r
-import org.eclipse.swt.dnd.TextTransfer;\r
-import org.eclipse.swt.dnd.Transfer;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Control;\r
-import org.eclipse.swt.widgets.Event;\r
-import org.eclipse.swt.widgets.Listener;\r
-import org.eclipse.swt.widgets.Tree;\r
-import org.eclipse.swt.widgets.TreeColumn;\r
-import org.eclipse.swt.widgets.TreeItem;\r
-import org.eclipse.ui.ISelectionListener;\r
-import org.eclipse.ui.IWorkbenchSite;\r
-import org.eclipse.ui.contexts.IContextService;\r
-import org.simantics.browsing.ui.BuiltinKeys;\r
-import org.simantics.browsing.ui.Column;\r
-import org.simantics.browsing.ui.ExplorerState;\r
-import org.simantics.browsing.ui.GraphExplorer;\r
-import org.simantics.browsing.ui.GraphExplorer.TransientExplorerState;\r
-import org.simantics.browsing.ui.NodeContext;\r
-import org.simantics.browsing.ui.StatePersistor;\r
-import org.simantics.browsing.ui.common.ColumnKeys;\r
-import org.simantics.browsing.ui.common.EvaluatorData;\r
-import org.simantics.browsing.ui.common.EvaluatorDataImpl;\r
-import org.simantics.browsing.ui.common.processors.ComparableFactoryResolver;\r
-import org.simantics.browsing.ui.common.processors.ComparableSelectorQueryProcessor;\r
-import org.simantics.browsing.ui.common.processors.FilterSelectionRequestQueryProcessor;\r
-import org.simantics.browsing.ui.common.processors.ImageDecoratorFactoryResolver;\r
-import org.simantics.browsing.ui.common.processors.ImagerFactoryResolver;\r
-import org.simantics.browsing.ui.common.processors.LabelDecoratorFactoryResolver;\r
-import org.simantics.browsing.ui.common.processors.LabelerFactoryResolver;\r
-import org.simantics.browsing.ui.common.processors.UserSelectedComparableFactoryQueryProcessor;\r
-import org.simantics.browsing.ui.common.processors.UserSelectedViewpointFactoryQueryProcessor;\r
-import org.simantics.browsing.ui.common.processors.ViewpointFactoryResolver;\r
-import org.simantics.browsing.ui.common.views.FilterAreaSource;\r
-import org.simantics.browsing.ui.common.views.IFilterArea;\r
-import org.simantics.browsing.ui.common.views.IFilterAreaProvider;\r
-import org.simantics.browsing.ui.graph.impl.AsyncReadGraphDataSource;\r
-import org.simantics.browsing.ui.graph.impl.Evaluators;\r
-import org.simantics.browsing.ui.graph.impl.InheritsQueryProcessor;\r
-import org.simantics.browsing.ui.graph.impl.ReadGraphDataSource;\r
-import org.simantics.browsing.ui.graph.impl.RelatedObjectsQueryProcessor;\r
-import org.simantics.browsing.ui.graph.impl.SessionContextInputSource;\r
-import org.simantics.browsing.ui.model.browsecontexts.BrowseContext;\r
-import org.simantics.browsing.ui.model.nodetypes.NodeType;\r
-import org.simantics.browsing.ui.swt.Activator;\r
-import org.simantics.browsing.ui.swt.AdaptableHintContext;\r
-import org.simantics.browsing.ui.swt.ComparatorSelector;\r
-import org.simantics.browsing.ui.swt.ContextMenuInitializer;\r
-import org.simantics.browsing.ui.swt.DefaultExplorerSelectionListener;\r
-import org.simantics.browsing.ui.swt.DefaultIsCheckedProcessor2;\r
-import org.simantics.browsing.ui.swt.DefaultKeyListener;\r
-import org.simantics.browsing.ui.swt.DefaultMouseListener;\r
-import org.simantics.browsing.ui.swt.DefaultSelectionDataResolver;\r
-import org.simantics.browsing.ui.swt.FilterArea;\r
-import org.simantics.browsing.ui.swt.GraphExplorerFactory;\r
-import org.simantics.browsing.ui.swt.IContextMenuInitializer;\r
-import org.simantics.browsing.ui.swt.RootFilterArea;\r
-import org.simantics.browsing.ui.swt.StandardContextTypesQueryProcessor;\r
-import org.simantics.browsing.ui.swt.TypesQueryProcessor;\r
-import org.simantics.browsing.ui.swt.ViewpointSelector;\r
-import org.simantics.browsing.ui.swt.widgets.impl.Widget;\r
-import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;\r
-import org.simantics.db.AsyncReadGraph;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.common.request.ResourceRead;\r
-import org.simantics.db.common.utils.Logger;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.layer0.SelectionHints;\r
-import org.simantics.db.layer0.variable.Variable;\r
-import org.simantics.db.layer0.variable.Variables;\r
-import org.simantics.db.management.ISessionContext;\r
-import org.simantics.db.management.ISessionContextChangedListener;\r
-import org.simantics.db.management.ISessionContextProvider;\r
-import org.simantics.db.management.SessionContextChangedEvent;\r
-import org.simantics.project.ProjectKeys;\r
-import org.simantics.ui.SimanticsUI;\r
-import org.simantics.ui.dnd.LocalObjectTransfer;\r
-import org.simantics.ui.dnd.LocalSelectionDragSourceListener;\r
-import org.simantics.ui.dnd.NoImageDragSourceEffect;\r
-import org.simantics.ui.dnd.SessionContainer;\r
-import org.simantics.ui.selection.AnyResource;\r
-import org.simantics.ui.selection.AnyVariable;\r
-import org.simantics.ui.selection.ExplorerColumnContentType;\r
-import org.simantics.ui.selection.ExplorerInputContentType;\r
-import org.simantics.ui.selection.WorkbenchSelectionContentType;\r
-import org.simantics.ui.selection.WorkbenchSelectionElement;\r
-import org.simantics.ui.selection.WorkbenchSelectionUtils;\r
-import org.simantics.utils.ObjectUtils;\r
-import org.simantics.utils.datastructures.BinaryFunction;\r
-import org.simantics.utils.datastructures.Function;\r
-import org.simantics.utils.datastructures.disposable.DisposeState;\r
-import org.simantics.utils.datastructures.hints.HintListenerAdapter;\r
-import org.simantics.utils.datastructures.hints.HintTracker;\r
-import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
-import org.simantics.utils.datastructures.hints.IHintListener;\r
-import org.simantics.utils.datastructures.hints.IHintObservable;\r
-import org.simantics.utils.datastructures.hints.IHintTracker;\r
-\r
-\r
-public class GraphExplorerComposite extends Composite implements Widget, IAdaptable {\r
-\r
- protected UserSelectedComparableFactoryQueryProcessor userSelectedComparableFactoryQueryProcessor;\r
- protected UserSelectedViewpointFactoryQueryProcessor userSelectedViewpointFactoryQueryProcessor;\r
- protected FilterSelectionRequestQueryProcessor filterSelectionRequestQueryProcessor;\r
- protected IFilterArea filterArea;\r
- protected EvaluatorData evaluatorData;\r
-\r
- protected LocalResourceManager resourceManager;\r
-\r
- protected ISelectionListener workbenchSelectionListener;\r
-\r
- private final int style;\r
-\r
- final private IWorkbenchSite site;\r
-\r
- protected GraphExplorer explorer;\r
-\r
- protected IMenuManager menuManager;\r
-\r
- private final Map<String, Object> args;\r
-\r
- protected ISessionContextProvider contextProvider;\r
-\r
- private ISessionContext sessionContext;\r
-\r
- private Object dragSource;\r
-\r
- private IHintTracker sessionContextTracker = new SessionContextProjectTracker();\r
-\r
- private InputSource inputSource = new DirectInputSource();\r
- private FilterAreaSource filterAreaSource = new SelectionFilterAreaSource();\r
-\r
- private final TreeColumnLayout ad;\r
- private String[] editingColumn = ColumnKeys.KEYS_SINGLE;\r
- \r
- private StatePersistor persistor = null;\r
-\r
- private final Composite toolComposite;\r
- private final Composite toolComposite2;\r
- private final Composite explorerComposite;\r
- final private WidgetSupport support;\r
- private final boolean useNodeBrowseContexts;\r
- private final boolean useNodeActionContexts;\r
-\r
- static class SelectionElement extends AdaptableHintContext {\r
-\r
- final public WorkbenchSelectionElement wse;\r
- final public Object content;\r
- final public Resource resource;\r
- final public Variable variable;\r
- final public Object input;\r
- final public TransientExplorerState explorerState;\r
- \r
- private WorkbenchSelectionElement extractWse(Object content) {\r
- if(content instanceof NodeContext) {\r
- NodeContext context = (NodeContext)content;\r
- Object input = context.getConstant(NodeType.TYPE);\r
- if(input instanceof NodeType) \r
- return ((NodeType)input).getWorkbenchSelectionElement(context);\r
- }\r
- return null;\r
- }\r
- \r
- private Resource extractResource(Object content) {\r
- if(content instanceof NodeContext) {\r
- NodeContext context = (NodeContext)content;\r
- Object input = context.getConstant(BuiltinKeys.INPUT);\r
- if(input instanceof Resource) return (Resource)input;\r
- if(input instanceof IAdaptable) {\r
- Resource var = (Resource)((IAdaptable)input).getAdapter(Resource.class);\r
- if(var != null) return var;\r
- }\r
- }\r
- return null;\r
- }\r
- \r
- private Variable extractVariable(Object content) {\r
- if(content instanceof NodeContext) {\r
- NodeContext context = (NodeContext)content;\r
- Object input = context.getConstant(BuiltinKeys.INPUT);\r
- if(input instanceof Variable) return (Variable)input;\r
- if(input instanceof IAdaptable) {\r
- Variable var = (Variable)((IAdaptable)input).getAdapter(Variable.class);\r
- if(var != null) return var;\r
- }\r
- }\r
- return null;\r
- }\r
-\r
- private Object extractInput(Object content) {\r
- if(content instanceof NodeContext) {\r
- NodeContext context = (NodeContext)content;\r
- return context.getConstant(BuiltinKeys.INPUT);\r
- }\r
- return null;\r
- }\r
-\r
- public SelectionElement(GraphExplorer explorer, Key[] keys, Object content) {\r
- super(keys);\r
- this.content = content;\r
- this.wse = extractWse(content);\r
- this.resource = extractResource(content);\r
- this.variable = extractVariable(content);\r
- this.input = extractInput(content);\r
- this.explorerState = explorer.getTransientState();\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- @Override\r
- public <T> T getContent(WorkbenchSelectionContentType<T> contentType) {\r
-\r
- if(wse != null) {\r
- T result = wse.getContent(contentType);\r
- if(result != null) return result;\r
- }\r
- \r
- if(contentType instanceof AnyResource) return (T)resource;\r
- else if(contentType instanceof AnyVariable) {\r
- AnyVariable type = (AnyVariable)contentType;\r
- try {\r
- \r
- if(variable != null) return (T)variable;\r
- \r
- if(resource == null) return null;\r
- \r
- return (T) type.processor.sync(new ResourceRead<Variable>(resource) {\r
- @Override\r
- public Variable perform(ReadGraph graph) throws DatabaseException {\r
- return Variables.getPossibleVariable(graph, resource);\r
- }\r
- \r
- });\r
- } catch (DatabaseException e) {\r
- Logger.defaultLogError(e);\r
- }\r
- } else if (contentType instanceof ExplorerInputContentType) {\r
- return (T)input;\r
- } else if (contentType instanceof ExplorerColumnContentType) {\r
- return (T)explorerState.getActiveColumn();\r
- }\r
- return null;\r
- }\r
- \r
- @SuppressWarnings("rawtypes")\r
- @Override\r
- public Object getAdapter(Class adapter) {\r
- if(WorkbenchSelectionElement.class == adapter) {\r
- return wse;\r
- }\r
- if(NodeContext.class == adapter) {\r
- if(content instanceof NodeContext)\r
- return (NodeContext)content;\r
- else\r
- return null;\r
- }\r
- return super.getAdapter(adapter);\r
- }\r
-\r
- }\r
- private BinaryFunction<Object[], GraphExplorer, Object[]> selectionTransformation = new BinaryFunction<Object[], GraphExplorer, Object[]>() {\r
-\r
- private Key[] KEYS = new Key[] { SelectionHints.KEY_MAIN };\r
- \r
- @Override\r
- public Object[] call(GraphExplorer explorer, Object[] objects) {\r
- Object[] result = new Object[objects.length];\r
- for (int i = 0; i < objects.length; i++) {\r
- SelectionElement context = new SelectionElement(explorer, KEYS, objects[i]);\r
- context.setHint(SelectionHints.KEY_MAIN, objects[i]);\r
- result[i] = context;\r
- }\r
- return result;\r
- }\r
-\r
- };\r
-\r
- private Set<String> browseContexts = null;\r
-\r
- private DisposeState disposeState = DisposeState.Alive;\r
-\r
- private boolean created = false;\r
-\r
- protected String contextMenuId = null;\r
-\r
- protected Set<String> uiContext = null;\r
-\r
- protected ISessionContextChangedListener contextChangeListener = new ISessionContextChangedListener() {\r
- @Override\r
- public void sessionContextChanged(SessionContextChangedEvent event) {\r
- sessionContext = event.getNewValue();\r
- sessionContextTracker.track(sessionContext);\r
- }\r
- };\r
-\r
- public GraphExplorerComposite(Map<String, Object> args, IWorkbenchSite site, Composite parent, WidgetSupport support, int style) {\r
-\r
- super(parent, SWT.NONE);\r
-\r
- if (args == null)\r
- args = Collections.emptyMap();\r
-\r
- this.args = args;\r
- this.site = site;\r
- this.style = style;\r
- this.resourceManager = new LocalResourceManager(JFaceResources.getResources(parent.getDisplay()), this);\r
-\r
- contextProvider = getSessionContextProvider(site);\r
-\r
- Integer maxChildren = (Integer)args.get("maxChildren");\r
-\r
- GridLayoutFactory.fillDefaults().equalWidth(false).numColumns(1).margins(0,0).spacing(0,0).applyTo(this);\r
-\r
- toolComposite = new Composite(this, SWT.NONE);\r
-// toolComposite.setBackground(toolComposite.getDisplay().getSystemColor(SWT.COLOR_DARK_YELLOW));\r
-// GridDataFactory.fillDefaults().grab(true, false).minSize(1, 1).applyTo(toolComposite);\r
- GridDataFactory.fillDefaults().grab(true, false).applyTo(toolComposite);\r
- GridLayoutFactory.fillDefaults().applyTo(toolComposite);\r
-\r
- ad = new TreeColumnLayout();\r
- explorerComposite = new Composite(this, SWT.NONE);\r
- explorerComposite.setLayout(ad);\r
- GridDataFactory.fillDefaults().grab(true, true).minSize(1, 50).applyTo(explorerComposite);\r
-\r
- if (args.containsKey("treeView") && Boolean.TRUE.equals(args.get("treeView"))) {\r
- explorer = createExplorerControl2(explorerComposite, maxChildren);\r
- } else if (args.containsKey("natTable") && Boolean.TRUE.equals(args.get("natTable"))) {\r
- explorer = createExplorerControl3(explorerComposite, maxChildren);\r
- } else {\r
- explorer = createExplorerControl(explorerComposite, maxChildren);\r
- }\r
- \r
- if (args.containsKey("useNodeBrowseContexts") && Boolean.TRUE.equals(args.get("useNodeBrowseContexts"))) {\r
- useNodeBrowseContexts = true;\r
- } else {\r
- useNodeBrowseContexts = false;\r
- }\r
- \r
- if (args.containsKey("useNodeActionContexts") && Boolean.TRUE.equals(args.get("useNodeActionContexts"))) {\r
- useNodeActionContexts = true;\r
- } else {\r
- useNodeActionContexts = false;\r
- }\r
- \r
- toolComposite2 = new Composite(this, SWT.NONE);\r
-// toolComposite2.setBackground(toolComposite2.getDisplay().getSystemColor(SWT.COLOR_DARK_YELLOW));\r
-// GridDataFactory.fillDefaults().grab(true, false).minSize(1, 1).applyTo(toolComposite);\r
- GridDataFactory.fillDefaults().grab(true, false).applyTo(toolComposite2);\r
- GridLayoutFactory.fillDefaults().applyTo(toolComposite2);\r
-\r
- this.support = support;\r
-\r
- if (support != null)\r
- support.register(this);\r
-\r
- }\r
-\r
- public GraphExplorerComposite(Map<String, Object> args, IWorkbenchSite site, Composite parent, int style) {\r
-\r
- this(args, site, parent, null, style);\r
-\r
- }\r
-\r
- public ISessionContextProvider getSessionContextProvider(IWorkbenchSite site) {\r
- if(site != null)\r
- return SimanticsUI.getSessionContextProvider(site.getWorkbenchWindow());\r
- else\r
- return SimanticsUI.getSessionContextProvider();\r
- }\r
-\r
- public GraphExplorer getExplorer() {\r
- return explorer;\r
- }\r
-\r
- public Composite getExplorerComposite() {\r
- return explorerComposite;\r
- }\r
-\r
- public <T> T getExplorerControl() {\r
- return explorer.getControl();\r
- }\r
-\r
- public void addListenerToControl(int eventType, Listener listener) {\r
- ((Control)explorer.getControl()).addListener(eventType, listener);\r
- }\r
-\r
- public void finish() {\r
- created = true;\r
- createControls(site);\r
- attachToSession();\r
- }\r
-\r
- IWorkbenchSite getSite() {\r
- return site;\r
- }\r
-\r
- protected void activateUiContexts() {\r
- Collection<String> contexts = getUiContexts();\r
- if (contexts == null || contexts.isEmpty())\r
- return;\r
- IWorkbenchSite site = getSite();\r
- if (site != null) {\r
- IContextService cs = (IContextService) getSite().getService(IContextService.class);\r
- for (String context : contexts)\r
- cs.activateContext(context);\r
- }\r
- }\r
-\r
- protected void createControls(IWorkbenchSite site) {\r
-\r
- // Initialize explorer control.\r
-// GridDataFactory.fillDefaults().grab(true, true).applyTo(explorer.getControl());\r
-\r
- Control control = explorer.getControl();\r
-\r
- // Initialize context menu if an initializer is provided.\r
- IContextMenuInitializer cmi = getContextMenuInitializer();\r
- if (cmi != null) {\r
- ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class);\r
- menuManager = cmi.createContextMenu(control, selectionProvider, site);\r
- }\r
-\r
- // Initialize UI contexts\r
- activateUiContexts();\r
-\r
- // Initialize DND.\r
- dragSource = setupDND(explorer);\r
-\r
- // Listeners are only added once per listener, not every time the\r
- // session context changes.\r
- addListeners(explorer, menuManager);\r
-\r
- userSelectedComparableFactoryQueryProcessor = new UserSelectedComparableFactoryQueryProcessor();\r
- userSelectedViewpointFactoryQueryProcessor = new UserSelectedViewpointFactoryQueryProcessor();\r
- filterSelectionRequestQueryProcessor = new FilterSelectionRequestQueryProcessor();\r
- \r
- explorer.setPrimitiveProcessor(filterSelectionRequestQueryProcessor);\r
-\r
- boolean hasExtraControls = false;\r
- boolean hasExtraControls2 = false;\r
-\r
- Boolean displaySelectors = (Boolean)args.get("displaySelectors");\r
- if(displaySelectors == null || displaySelectors == true) {\r
-\r
- @SuppressWarnings("unused")\r
- ComparatorSelector comparatorSelector = new ComparatorSelector(explorer, userSelectedComparableFactoryQueryProcessor, toolComposite, SWT.READ_ONLY);\r
-// comparatorSelector.moveAbove(control);\r
-\r
- @SuppressWarnings("unused")\r
- ViewpointSelector viewpointSelector = new ViewpointSelector(explorer, userSelectedViewpointFactoryQueryProcessor, toolComposite, SWT.READ_ONLY);\r
-// viewpointSelector.moveAbove(control);\r
-\r
- hasExtraControls = true;\r
-\r
- }\r
-\r
- Boolean displayFilter = (Boolean)args.get("displayFilter");\r
- if(displayFilter == null || displayFilter == true) {\r
-\r
- \r
- filterArea = filterAreaSource.getFilterArea(toolComposite, explorer);\r
-// filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, toolComposite, SWT.READ_ONLY);\r
- //filterArea.moveAbove(control);\r
-\r
- hasExtraControls = true;\r
-\r
- }\r
-\r
- Boolean displayFilter2 = (Boolean)args.get("displayFilter2");\r
- if(displayFilter2 != null && displayFilter2 == true) {\r
-\r
- filterArea = filterAreaSource.getFilterArea(toolComposite2, explorer);\r
-// filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, toolComposite2, SWT.READ_ONLY);\r
-// //filterArea.moveAbove(control);\r
-\r
- hasExtraControls2 = true;\r
-\r
- }\r
-\r
-// filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, this, SWT.READ_ONLY);\r
-// filterArea.moveAbove(control);\r
-\r
- if(!hasExtraControls)\r
- GridDataFactory.fillDefaults().grab(true, false).minSize(0, 0).hint(0, 0).applyTo(toolComposite);\r
- if(!hasExtraControls2)\r
- GridDataFactory.fillDefaults().grab(true, false).minSize(0, 0).hint(0, 0).applyTo(toolComposite2);\r
-\r
- GridDataFactory.fillDefaults().grab(true, true).span(2,1).applyTo(control);\r
-\r
- //tree.getTree().setLayout(new FillLayout()\r
- //this.setLayout(LayoutUtils.createNoBorderGridLayout(2, false));\r
-\r
- DropTarget target = new DropTarget(control, DND.DROP_COPY | DND.DROP_LINK);\r
- target.setTransfer(getAcceptedDataTypes());\r
- if (control instanceof Tree) {\r
- target.addDropListener(new DropTargetListener() {\r
-\r
- Tree tree = (Tree)explorer.getControl();\r
-\r
- @Override\r
- public void dragEnter(DropTargetEvent event) {\r
- event.detail = DND.DROP_COPY;\r
- }\r
-\r
- @Override\r
- public void dragLeave(DropTargetEvent event) {\r
- }\r
-\r
- @Override\r
- public void dragOperationChanged(DropTargetEvent event) {\r
- }\r
-\r
- @Override\r
- public void dragOver(DropTargetEvent event) {\r
- }\r
-\r
- @Override\r
- public void drop(DropTargetEvent event) {\r
- TreeItem item = tree.getItem(tree.toControl(event.x, event.y));\r
- if(item != null) {\r
- Object data = item.getData();\r
- if (data instanceof NodeContext)\r
- handleDrop(event.data, (NodeContext) data);\r
- else if (data instanceof IAdaptable) {\r
- IAdaptable a = (IAdaptable) data;\r
- handleDrop(event.data, (NodeContext) a.getAdapter(NodeContext.class));\r
- }\r
- } else\r
- handleDrop(event.data, null);\r
- }\r
-\r
- @Override\r
- public void dropAccept(DropTargetEvent event) {\r
- }\r
-\r
- });\r
- }\r
-\r
- // Add workbench listeners and make sure they are cleaned up\r
- setWorkbenchListeners();\r
- control.addListener(SWT.Dispose, new Listener() {\r
- @Override\r
- public void handleEvent(Event event) {\r
- doDispose();\r
- }\r
- });\r
- }\r
-\r
- @SuppressWarnings({ "rawtypes", "unchecked" })\r
- @Override\r
- public Object getAdapter(Class adapter) {\r
- if (GraphExplorer.class == adapter)\r
- return explorer;\r
- if (EvaluatorData.class == adapter)\r
- return evaluatorData;\r
- if (BrowseContext.class == adapter) {\r
- EvaluatorData ed = evaluatorData;\r
- return ed != null ? ed.getBrowseContext() : null;\r
- }\r
- if (adapter == IFilterAreaProvider.class)\r
- return filterArea;\r
- return explorer.getAdapter(adapter);\r
- }\r
-\r
- protected void doDispose() {\r
- //System.out.println(this + ".GraphExplorerComposite.doDispose()");\r
- removeWorkbenchListeners();\r
- userSelectedComparableFactoryQueryProcessor = null;\r
- userSelectedViewpointFactoryQueryProcessor = null;\r
- filterSelectionRequestQueryProcessor = null;\r
-\r
- disposeState = DisposeState.Disposing;\r
- try {\r
- //System.out.println(this + ".GraphExplorerViewBase.dispose()");\r
- if (contextProvider != null) {\r
- contextProvider.removeContextChangedListener(contextChangeListener);\r
- contextProvider = null;\r
- }\r
- sessionContextTracker.untrack();\r
- resourceManager = null;\r
- explorer = null;\r
- sessionContext = null;\r
- dragSource = null;\r
-// parent = null;\r
- } finally {\r
- disposeState = DisposeState.Disposed;\r
- }\r
- }\r
-\r
- @Override\r
- public void dispose() {\r
- doDispose();\r
- super.dispose();\r
- }\r
-\r
- protected StatePersistor getStatePersistor() {\r
- return persistor;\r
- }\r
- \r
- public void setStatePersistor(StatePersistor persistor) {\r
- this.persistor = persistor;\r
- }\r
- \r
- protected void initializeExplorer(GraphExplorer explorer, ISessionContext context) {\r
-\r
- if(explorer == null || explorer.isDisposed()) return;\r
- if(context == null) return;\r
- if(browseContexts == null) return;\r
-\r
- Session session = context != null ? context.getSession() : null;\r
- setupDragSource(session);\r
-\r
- if (session != null) {\r
- evaluatorData = createEvaluatorData(session);\r
- explorer.setDataSource(new AsyncReadGraphDataSource(session));\r
- explorer.setDataSource(new ReadGraphDataSource(session));\r
- }\r
- else {\r
- evaluatorData = new EvaluatorDataImpl();\r
- explorer.removeDataSource(AsyncReadGraph.class);\r
- explorer.removeDataSource(ReadGraph.class);\r
- }\r
-\r
- explorer.setPersistor(getStatePersistor());\r
- \r
- explorer.setProcessor(new ComparableFactoryResolver(evaluatorData));\r
- explorer.setProcessor(new ViewpointFactoryResolver(evaluatorData));\r
- explorer.setProcessor(new LabelerFactoryResolver(evaluatorData));\r
- explorer.setProcessor(new ImagerFactoryResolver(evaluatorData));\r
- explorer.setProcessor(new LabelDecoratorFactoryResolver(evaluatorData));\r
- explorer.setProcessor(new ImageDecoratorFactoryResolver(evaluatorData));\r
- explorer.setProcessor(new DefaultIsCheckedProcessor2(evaluatorData));\r
- explorer.setPrimitiveProcessor(new TypesQueryProcessor());\r
- explorer.setPrimitiveProcessor(new StandardContextTypesQueryProcessor());\r
- explorer.setPrimitiveProcessor(new InheritsQueryProcessor());\r
- explorer.setPrimitiveProcessor(new RelatedObjectsQueryProcessor());\r
-\r
- explorer.setPrimitiveProcessor(userSelectedViewpointFactoryQueryProcessor);\r
- explorer.setProcessor(new ComparableSelectorQueryProcessor());\r
- explorer.setPrimitiveProcessor(userSelectedComparableFactoryQueryProcessor);\r
- explorer.setPrimitiveProcessor(filterSelectionRequestQueryProcessor);\r
-\r
- initializeExplorerWithEvaluator(explorer, context, evaluatorData);\r
- }\r
-\r
- protected void initializeExplorerWithEvaluator(GraphExplorer explorer, ISessionContext context, EvaluatorData data) {\r
- }\r
-\r
- protected EvaluatorData createEvaluatorData(Session context) {\r
-\r
-// Set<String> browseContexts = getArgument("browseContexts");\r
-\r
- return Evaluators.load(context.getSession(), browseContexts, resourceManager, useNodeBrowseContexts, useNodeActionContexts);\r
-\r
- }\r
-\r
- protected Transfer[] getAcceptedDataTypes() {\r
- return new Transfer[] { LocalObjectTransfer.getTransfer(), FileTransfer.getInstance() };\r
- }\r
-\r
- protected void handleDrop(Object data, NodeContext target) {\r
- }\r
-\r
- DragSourceListenerFactory dragSourceListenerFactory = new DragSourceListenerFactory() {\r
-\r
- final Transfer[] transfers = new Transfer[] {LocalObjectTransfer.getTransfer(), TextTransfer.getInstance() };\r
-\r
- @Override\r
- public DragSourceListener get(ISelectionProvider selectionProvider) {\r
-\r
- LocalSelectionDragSourceListener ls = new LocalSelectionDragSourceListener(selectionProvider);\r
-\r
- return new DragSourceListener() {\r
- \r
- @Override\r
- public void dragStart(DragSourceEvent event) {\r
- ls.dragStart(event);\r
- }\r
- \r
- @Override\r
- public void dragSetData(DragSourceEvent event) {\r
- if(TextTransfer.getInstance().isSupportedType(event.dataType)) {\r
- try {\r
- event.data = WorkbenchSelectionUtils.getPossibleJSON(selectionProvider.getSelection());\r
- } catch (DatabaseException e) {\r
- event.data = "{ type:\"Exception\" }";\r
- Logger.defaultLogError(e);\r
- }\r
- } else if (LocalObjectTransfer.getTransfer().isSupportedType(event.dataType)) {\r
- ls.dragSetData(event);\r
- }\r
- }\r
- \r
- @Override\r
- public void dragFinished(DragSourceEvent event) {\r
- ls.dragFinished(event);\r
- }\r
- };\r
- }\r
-\r
- @Override\r
- public Transfer[] getTransfers() {\r
- return transfers;\r
- }\r
-\r
- };\r
-\r
- public void setDragSourceListenerFactory(DragSourceListenerFactory dragSourceListenerFactory) {\r
- this.dragSourceListenerFactory = dragSourceListenerFactory;\r
- }\r
-\r
- protected DragSourceListener setupDND(GraphExplorer explorer) {\r
-\r
- ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class);\r
-\r
- DragSourceListener listener = createDragSourceListener(selectionProvider);\r
-\r
- Control control = explorer.getControl();\r
- DragSource source = createDragSource(control);\r
- source.setTransfer(getTransfers());\r
- source.addDragListener(listener);\r
- source.setDragSourceEffect(new NoImageDragSourceEffect(control));\r
-\r
- return listener;\r
-\r
- }\r
-\r
- protected DragSourceListener createDragSourceListener(ISelectionProvider selectionProvider) {\r
- return dragSourceListenerFactory.get(selectionProvider);\r
- }\r
-\r
- private int dragStyle = DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT;\r
-\r
- protected void setDragStyle(int style) {\r
- this.dragStyle = style;\r
- }\r
-\r
- protected int getDragStyle() {\r
- return dragStyle;\r
- }\r
-\r
- protected DragSource createDragSource(Control control) {\r
- return new DragSource(control, getDragStyle());\r
- }\r
-\r
- protected Transfer[] getTransfers() {\r
- return dragSourceListenerFactory.getTransfers();\r
- }\r
-\r
- public EvaluatorData getEvaluatorData() {\r
- return evaluatorData;\r
- }\r
-\r
- public interface InputSource {\r
- /**\r
- * @param ctx the session context to read the input from. May be\r
- * <code>null</code> if there is no session.\r
- * @return the input object of a graph explorer. To indicate no input,\r
- * use {@link GraphExplorerConstants#EMPTY_INPUT}. Never return\r
- * <code>null</code>.\r
- */\r
- Object get(ISessionContext ctx, Object selection);\r
- }\r
- \r
- public interface FilterSource {\r
- \r
- \r
- \r
- }\r
-\r
- /**\r
- * The default hint tracker that will be active if\r
- * {@link GraphExplorerComposite#setSessionContextTracker(IHintTracker) is\r
- * not called.\r
- */\r
- public class SessionContextProjectTracker extends HintTracker {\r
- public SessionContextProjectTracker() {\r
- IHintListener activeProjectListener = new HintListenerAdapter() {\r
- @Override\r
- public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {\r
- applySessionContext(getSessionContext());\r
- }\r
- };\r
- addKeyHintListener(ProjectKeys.KEY_PROJECT, activeProjectListener);\r
- }\r
- }\r
-\r
- public class DirectInputSource implements InputSource {\r
- @Override\r
- public Object get(ISessionContext ctx, Object selection) {\r
- return selection;\r
- }\r
- }\r
- \r
- public static class SelectionFilterAreaSource implements FilterAreaSource {\r
-\r
- @Override\r
- public IFilterArea getFilterArea(Composite parent, GraphExplorer explorer) {\r
- FilterSelectionRequestQueryProcessor processor = (FilterSelectionRequestQueryProcessor)explorer.getPrimitiveProcessor(BuiltinKeys.SELECTION_REQUESTS);\r
- return new FilterArea(explorer, processor, parent, SWT.READ_ONLY);\r
- }\r
- \r
- }\r
-\r
- public static class RootFilterAreaSource implements FilterAreaSource {\r
-\r
- @Override\r
- public IFilterArea getFilterArea(Composite parent, GraphExplorer explorer) {\r
- FilterSelectionRequestQueryProcessor processor = (FilterSelectionRequestQueryProcessor)explorer.getPrimitiveProcessor(BuiltinKeys.SELECTION_REQUESTS);\r
- return new RootFilterArea(explorer, processor, parent, SWT.READ_ONLY);\r
- }\r
- \r
- }\r
-\r
- protected void setSessionContextTracker(IHintTracker tracker) {\r
- this.sessionContextTracker = tracker;\r
- }\r
-\r
- public void setInputSource(InputSource source) {\r
- this.inputSource = source;\r
- }\r
- \r
- public void setFilterAreaSource(FilterAreaSource provider) {\r
- this.filterAreaSource = provider;\r
- }\r
-\r
- public void setSelectionTransformation(BinaryFunction<Object[], GraphExplorer, Object[]> transformation) {\r
- this.selectionTransformation = transformation;\r
- if(explorer != null) explorer.setSelectionTransformation(transformation);\r
- }\r
-\r
- protected Set<String> getBrowseContexts() {\r
- return browseContexts;\r
- }\r
- \r
- public void setBrowseContexts(Set<String> contexts) {\r
- this.browseContexts = contexts;\r
- //initializeExplorer(explorer, getSessionContext());\r
- }\r
-\r
- public void setBrowseContexts(String ... contexts) {\r
- this.browseContexts = new HashSet<String>();\r
- for(String s : contexts) this.browseContexts.add(s);\r
- initializeExplorer(explorer, getSessionContext());\r
- }\r
-\r
- public void setContextMenuId(String contextMenuId) {\r
- this.contextMenuId = contextMenuId;\r
- }\r
-\r
-// protected IContextMenuInitializer getContextMenuInitializer() {\r
-// String contextMenuId = getContextMenuId();\r
-// if(contextMenuId != null) {\r
-// return new ContextMenuInitializer(contextMenuId);\r
-// } else {\r
-// return null;\r
-// }\r
-// }\r
-\r
- protected String getContextMenuId() {\r
- return this.contextMenuId;\r
- }\r
-\r
- public void setUiContexts(Set<String> uiContext) {\r
- this.uiContext = uiContext;\r
- }\r
-\r
- public Set<String> getUiContexts() {\r
- return uiContext;\r
- }\r
-\r
- protected InputSource getInputSource() {\r
- return inputSource;\r
- }\r
-\r
- protected Map<String, Object> getArguments() {\r
- return args;\r
- }\r
-\r
- @SuppressWarnings("unchecked")\r
- protected <T> T getArgument(String key) {\r
- return (T) args.get(key);\r
- }\r
-\r
- protected DisposeState getDisposeState() {\r
- return disposeState;\r
- }\r
-\r
- public ISessionContext getSessionContext() {\r
- return sessionContext;\r
- }\r
-\r
- public ISessionContextProvider getSessionContextProvider() {\r
- return contextProvider;\r
- }\r
-\r
- @Override\r
- public boolean setFocus() {\r
- if (explorer != null && !explorer.isDisposed())\r
- explorer.setFocus();\r
- return true;\r
- }\r
-\r
- public void setWorkbenchListeners() {\r
- if (workbenchSelectionListener == null && getSite() != null) {\r
- ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);\r
- getSite().setSelectionProvider(selectionProvider);\r
-\r
- // Listen to the workbench selection also to propagate it to\r
- // the explorer also.\r
- workbenchSelectionListener = new DefaultExplorerSelectionListener(site.getPage().getActivePart(), explorer);\r
- //System.out.println("ADD WORKBENCH SELECTION LISTENER: " + workbenchSelectionListener);\r
- getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(workbenchSelectionListener);\r
- }\r
- }\r
-\r
- protected void removeWorkbenchListeners() {\r
- //System.out.println("REMOVE WORKBENCH SELECTION LISTENER: " + workbenchSelectionListener);\r
- // Remember to remove the installed workbench selection listener\r
- if (workbenchSelectionListener != null) {\r
- getSite().getWorkbenchWindow().getSelectionService().removePostSelectionListener(workbenchSelectionListener);\r
- workbenchSelectionListener = null;\r
-\r
- ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);\r
- if(getSite().getSelectionProvider() == selectionProvider) getSite().setSelectionProvider(null);\r
- \r
- }\r
- }\r
-\r
- protected final void attachToSession() {\r
-\r
- // Track active ISessionContext changes\r
- //contextProvider = SimanticsUI.getSessionContextProvider(getViewSite().getWorkbenchWindow());\r
- contextProvider.addContextChangedListener(contextChangeListener);\r
-\r
- // Start tracking the current session context for input changes.\r
- // This will/must cause applySessionContext to get called.\r
- // Doing the applySessionContext initialization this way\r
- // instead of directly calling it will also make sure that\r
- // applySessionContext is only called once when first initialized,\r
- // and not twice like with the direct invocation.\r
- this.sessionContext = contextProvider.getSessionContext();\r
- sessionContextTracker.track(sessionContext);\r
- }\r
-\r
- // /////////////////////////////////////////////////////////////////////////\r
- // Override / implement these:\r
-\r
-// /**\r
-// * Returns an ID that is used for persisting a GraphExplorer instance.\r
-// *\r
-// * Used for </code>restoreState(IMemento)</code> and\r
-// * <code>restoreState(IMemento)</code> in OntologyExplorer. Must be unique\r
-// * within a workbench part.\r
-// *\r
-// * @return a unique name for this particular graph explorer view used for\r
-// * saving and restoring the state of this view part\r
-// */\r
-// public String getExplorerName() {\r
-// return "GraphExplorerViewBase";\r
-// }\r
-\r
- /**\r
- * Override this method to add controls to the view part. This is invoked\r
- * before attaching the view part to a database session.\r
- * \r
- * @param parent\r
- */\r
- protected void createControls(Composite parent) {\r
-\r
- }\r
-\r
- /**\r
- * Override this method and provide a proper context menu initializer if you\r
- * want to have this base class initialize one for you.\r
- * \r
- * @return the initializer to be used by {@link #createControls(Composite)}\r
- */\r
- protected IContextMenuInitializer getContextMenuInitializer() {\r
- String contextMenuId = getContextMenuId();\r
- if(contextMenuId != null) {\r
- return new ContextMenuInitializer(contextMenuId);\r
- } else {\r
- return null;\r
- }\r
- }\r
-\r
- /**\r
- * @param parent\r
- * @return\r
- */\r
- protected GraphExplorer createExplorerControl(Composite parent, Integer maxChildren) {\r
- GraphExplorerFactory factory = GraphExplorerFactory.getInstance();\r
- if(maxChildren != null) factory = factory.maxChildrenShown(maxChildren);\r
-\r
- GraphExplorer ge = factory\r
- .selectionDataResolver(new DefaultSelectionDataResolver())\r
- .selectionTransformation(selectionTransformation)\r
- .setServiceLocator(site)\r
- .create(parent, style);\r
-\r
- return ge;\r
- }\r
- \r
- protected GraphExplorer createExplorerControl2(Composite parent, Integer maxChildren) {\r
- GraphExplorerFactory factory = GraphExplorerFactory.getInstance();\r
- if(maxChildren != null) factory = factory.maxChildrenShown(maxChildren);\r
-\r
- GraphExplorer ge = factory\r
- .selectionDataResolver(new DefaultSelectionDataResolver())\r
- .selectionTransformation(selectionTransformation)\r
- .setServiceLocator(site)\r
- .create2(parent, style);\r
-\r
- return ge;\r
- }\r
- \r
- protected GraphExplorer createExplorerControl3(Composite parent, Integer maxChildren) {\r
- GraphExplorerFactory factory = GraphExplorerFactory.getInstance();\r
- if(maxChildren != null) factory = factory.maxChildrenShown(maxChildren);\r
-\r
- GraphExplorer ge = factory\r
- .selectionDataResolver(new DefaultSelectionDataResolver())\r
- .selectionTransformation(selectionTransformation)\r
- .setServiceLocator(site)\r
- .create3(parent, style);\r
-\r
- return ge;\r
- }\r
-\r
- protected void setupDragSource(Session session) {\r
- if (dragSource instanceof SessionContainer) {\r
- ((SessionContainer) dragSource).setSession(session);\r
- }\r
- }\r
-\r
- /**\r
- * Override to customize the addition of listeners a newly created\r
- * GraphExplorer.\r
- * \r
- * @param explorer\r
- */\r
- protected void addListeners(GraphExplorer explorer, IMenuManager menuManager) {\r
- addSelectionInputListeners(explorer, menuManager);\r
- }\r
-\r
- protected void addSelectionInputListeners(GraphExplorer explorer, IMenuManager menuManager) {\r
- // Consider ENTER presses to simulate mouse left button double clicks\r
- explorer.addListener(new DefaultKeyListener(contextProvider, explorer, new Function<String[]>() {\r
- @Override\r
- public String[] execute(Object... obj) {\r
- return getEditingColumn((NodeContext) obj[0]);\r
- }\r
- }));\r
- // Default double click handling\r
- explorer.addListener(new DefaultMouseListener(explorer));\r
- }\r
-\r
- protected String[] getEditingColumn(NodeContext context) {\r
- return editingColumn;\r
- }\r
- \r
- public void setEditingColumn(String... columnKeysInOrderOfTrial) {\r
- this.editingColumn = columnKeysInOrderOfTrial;\r
- }\r
-\r
- // Needed for preventing unnecessary re-initialization of the explorer with the same input.\r
- private Object currentInput;\r
- private Object currentRoot;\r
-\r
- /**\r
- * Invoke this to reinitialize the explorer and reset its input. The input\r
- * will be resolved from the specified ISessionContext based on the\r
- * {@link SessionContextInputSource} that is currently in use. If the input\r
- * is identical to the previous input, nothing will be done.\r
- * \r
- * @param context\r
- */\r
- public final boolean applySessionContext(ISessionContext context) {\r
-\r
- // If control is not alive anymore, do nothing.\r
- //System.out.println(this + ": applySessionContext(" + context + "), explorer=" + explorer);\r
- if (disposeState != DisposeState.Alive)\r
- return false;\r
-\r
- //System.out.println(this + ": initializeExplorer(" + explorer + ", " + context + ")");\r
- initializeExplorer(explorer, context);\r
-\r
-\r
- // Start tracking the session context.\r
- //\r
- // If this is not the same session that is currently tracked, it will\r
- // cause IHintListeners of the sessionContextTracker to fire.\r
- // For this we need the above input equality (identity) checking.\r
- // This is here just to make sure that we are tracking the correct\r
- // session context.\r
- sessionContextTracker.track(sessionContext);\r
-\r
- this.sessionContext = context;\r
- Object root = inputSource.get(context, currentInput);\r
- if (ObjectUtils.objectEquals(root, currentRoot))\r
- return false;\r
-\r
- currentRoot = root;\r
-\r
- //System.out.println(this + ": setRoot(" + input + ")");\r
- explorer.setUIContexts(uiContext);\r
- explorer.setRoot(root);\r
-\r
- return true;\r
-\r
- }\r
-\r
- protected boolean isImportantInput(Object previousSelection, Object selection) {\r
- return !ObjectUtils.objectEquals(previousSelection, selection);\r
- }\r
-\r
- public void setInput(Object selection, boolean force) {\r
-\r
- assert(created);\r
-\r
- if (isDisposed())\r
- return;\r
- if (sessionContext == null)\r
- return;\r
-\r
- // Check if this is a duplicate of the previous selection to reduce unnecessary flicker.\r
- if (!force && !isImportantInput(currentInput, selection))\r
- return;\r
-\r
- currentInput = selection;\r
-\r
- Object root = inputSource.get(sessionContext, selection);\r
-\r
- currentRoot = root;\r
-\r
- explorer.setUIContexts(uiContext);\r
-\r
- if (root == null) {\r
- explorer.setRoot(GraphExplorer.EMPTY_INPUT);\r
- } else {\r
- explorer.setRoot(root);\r
- }\r
-\r
- }\r
-\r
- public void setColumnsVisible(boolean visible) {\r
- explorer.setColumnsVisible(visible);\r
- }\r
-\r
- private int getColumnWidth(Column column, ExplorerState state) {\r
- // Get saved width from the persistor if there is one.\r
- if (state != null && state.columnWidths != null) {\r
- Integer width = state.columnWidths.get(column.getLabel());\r
- if (width != null)\r
- return width;\r
- }\r
- return column.getWidth();\r
- }\r
- \r
- public void setColumns(Column[] columns) {\r
-\r
- explorer.setColumns(columns, new Consumer<Map<Column, Object>>() {\r
-\r
- @Override\r
- public void accept(Map<Column, Object> objects) {\r
- ExplorerState state = null;\r
- if (persistor != null) {\r
- state = persistor.deserialize(\r
- Platform.getStateLocation(Activator.getDefault().getBundle()).toFile(),\r
- explorer.getRoot());\r
- }\r
-\r
- for(Map.Entry<Column, Object> entry : objects.entrySet()) {\r
- Column column = entry.getKey();\r
- TreeColumn treeColumn = (TreeColumn)entry.getValue();\r
-\r
- if (column.getWidth() < 0) {\r
- throw new IllegalArgumentException("Column minimum width cannot be < 0, got " + column.getWidth());\r
- }\r
-\r
- int width = getColumnWidth(column, state);\r
- if(column.hasGrab()) {\r
- \r
- ad.setColumnData(treeColumn, new ColumnWeightData(column.getWeight(), width));\r
-\r
- } else {\r
-\r
- ad.setColumnData(treeColumn, new ColumnWeightData(0, width));\r
-\r
- }\r
-\r
- }\r
- }\r
-\r
- });\r
-\r
- }\r
-\r
- @Override\r
- public void setInput(ISessionContext context, Object input) {\r
- setInput(input, false);\r
- }\r
-\r
- public void setMaxChildren(int maxChildren) {\r
- explorer.setMaxChildren(maxChildren);\r
- }\r
- \r
- public <T> void addListener(ExplorerMouseListenerImpl<T> listener) {\r
- \r
- support.register(listener);\r
- listener.register(explorer);\r
- explorer.addListener(listener);\r
- \r
- }\r
-\r
-// @Override\r
-// public Point computeSize(int wHint, int hHint) {\r
-// Point p = super.computeSize(wHint, hHint);\r
-// System.err.println("graphExplorerComposite.computeSize " + p);\r
-// return p;\r
-// }\r
-// \r
-// @Override\r
-// public Point computeSize(int wHint, int hHint, boolean changed) {\r
-// Point p = super.computeSize(wHint, hHint, changed);\r
-// System.err.println("graphExplorerComposite.computeSize " + p);\r
-// return p;\r
-// }\r
- \r
-}\r
+/*******************************************************************************
+ * 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
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * VTT Technical Research Centre of Finland - initial API and implementation
+ *******************************************************************************/
+package org.simantics.browsing.ui.swt.widgets;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.BiFunction;
+
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.layout.GridDataFactory;
+import org.eclipse.jface.layout.GridLayoutFactory;
+import org.eclipse.jface.layout.TreeColumnLayout;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.resource.LocalResourceManager;
+import org.eclipse.jface.viewers.ColumnWeightData;
+import org.eclipse.jface.viewers.ISelectionProvider;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.dnd.DragSource;
+import org.eclipse.swt.dnd.DragSourceEvent;
+import org.eclipse.swt.dnd.DragSourceListener;
+import org.eclipse.swt.dnd.DropTarget;
+import org.eclipse.swt.dnd.DropTargetEvent;
+import org.eclipse.swt.dnd.DropTargetListener;
+import org.eclipse.swt.dnd.FileTransfer;
+import org.eclipse.swt.dnd.TextTransfer;
+import org.eclipse.swt.dnd.Transfer;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.IWorkbenchSite;
+import org.eclipse.ui.contexts.IContextService;
+import org.simantics.Simantics;
+import org.simantics.browsing.ui.BuiltinKeys;
+import org.simantics.browsing.ui.Column;
+import org.simantics.browsing.ui.ExplorerState;
+import org.simantics.browsing.ui.GraphExplorer;
+import org.simantics.browsing.ui.GraphExplorer.TransientExplorerState;
+import org.simantics.browsing.ui.NodeContext;
+import org.simantics.browsing.ui.StatePersistor;
+import org.simantics.browsing.ui.common.AdaptableHintContext;
+import org.simantics.browsing.ui.common.ColumnKeys;
+import org.simantics.browsing.ui.common.EvaluatorData;
+import org.simantics.browsing.ui.common.EvaluatorDataImpl;
+import org.simantics.browsing.ui.common.processors.ComparableFactoryResolver;
+import org.simantics.browsing.ui.common.processors.ComparableSelectorQueryProcessor;
+import org.simantics.browsing.ui.common.processors.FilterSelectionRequestQueryProcessor;
+import org.simantics.browsing.ui.common.processors.ImageDecoratorFactoryResolver;
+import org.simantics.browsing.ui.common.processors.ImagerFactoryResolver;
+import org.simantics.browsing.ui.common.processors.LabelDecoratorFactoryResolver;
+import org.simantics.browsing.ui.common.processors.LabelerFactoryResolver;
+import org.simantics.browsing.ui.common.processors.UserSelectedComparableFactoryQueryProcessor;
+import org.simantics.browsing.ui.common.processors.UserSelectedViewpointFactoryQueryProcessor;
+import org.simantics.browsing.ui.common.processors.ViewpointFactoryResolver;
+import org.simantics.browsing.ui.common.state.ExplorerStates;
+import org.simantics.browsing.ui.common.views.FilterAreaSource;
+import org.simantics.browsing.ui.common.views.IFilterArea;
+import org.simantics.browsing.ui.common.views.IFilterAreaProvider;
+import org.simantics.browsing.ui.graph.impl.AsyncReadGraphDataSource;
+import org.simantics.browsing.ui.graph.impl.Evaluators;
+import org.simantics.browsing.ui.graph.impl.InheritsQueryProcessor;
+import org.simantics.browsing.ui.graph.impl.ReadGraphDataSource;
+import org.simantics.browsing.ui.graph.impl.RelatedObjectsQueryProcessor;
+import org.simantics.browsing.ui.graph.impl.SessionContextInputSource;
+import org.simantics.browsing.ui.model.browsecontexts.BrowseContext;
+import org.simantics.browsing.ui.model.nodetypes.NodeType;
+import org.simantics.browsing.ui.swt.ComparatorSelector;
+import org.simantics.browsing.ui.swt.ContextMenuInitializer;
+import org.simantics.browsing.ui.swt.DefaultExplorerSelectionListener;
+import org.simantics.browsing.ui.swt.DefaultIsCheckedProcessor2;
+import org.simantics.browsing.ui.swt.DefaultKeyListener;
+import org.simantics.browsing.ui.swt.DefaultMouseListener;
+import org.simantics.browsing.ui.swt.DefaultSelectionDataResolver;
+import org.simantics.browsing.ui.swt.FilterArea;
+import org.simantics.browsing.ui.swt.GraphExplorerFactory;
+import org.simantics.browsing.ui.swt.IContextMenuInitializer;
+import org.simantics.browsing.ui.swt.RootFilterArea;
+import org.simantics.browsing.ui.swt.StandardContextTypesQueryProcessor;
+import org.simantics.browsing.ui.swt.TypesQueryProcessor;
+import org.simantics.browsing.ui.swt.ViewpointSelector;
+import org.simantics.browsing.ui.swt.widgets.impl.Widget;
+import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;
+import org.simantics.db.AsyncReadGraph;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.SelectionHints;
+import org.simantics.db.layer0.request.PossibleVariable;
+import org.simantics.db.layer0.request.PossibleVariableRepresents;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.db.management.ISessionContext;
+import org.simantics.db.management.ISessionContextChangedListener;
+import org.simantics.db.management.ISessionContextProvider;
+import org.simantics.db.management.SessionContextChangedEvent;
+import org.simantics.project.ProjectKeys;
+import org.simantics.ui.SimanticsUI;
+import org.simantics.ui.dnd.LocalObjectTransfer;
+import org.simantics.ui.dnd.LocalSelectionDragSourceListener;
+import org.simantics.ui.dnd.NoImageDragSourceEffect;
+import org.simantics.ui.dnd.SessionContainer;
+import org.simantics.ui.selection.AnyResource;
+import org.simantics.ui.selection.AnyVariable;
+import org.simantics.ui.selection.ExplorerColumnContentType;
+import org.simantics.ui.selection.ExplorerInputContentType;
+import org.simantics.ui.selection.WorkbenchSelectionContentType;
+import org.simantics.ui.selection.WorkbenchSelectionElement;
+import org.simantics.ui.selection.WorkbenchSelectionUtils;
+import org.simantics.utils.ObjectUtils;
+import org.simantics.utils.datastructures.Function;
+import org.simantics.utils.datastructures.disposable.DisposeState;
+import org.simantics.utils.datastructures.hints.HintListenerAdapter;
+import org.simantics.utils.datastructures.hints.HintTracker;
+import org.simantics.utils.datastructures.hints.IHintContext.Key;
+import org.simantics.utils.datastructures.hints.IHintListener;
+import org.simantics.utils.datastructures.hints.IHintObservable;
+import org.simantics.utils.datastructures.hints.IHintTracker;
+import org.simantics.utils.ui.SWTUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class GraphExplorerComposite extends Composite implements Widget, IAdaptable {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(GraphExplorerComposite.class);
+
+ protected UserSelectedComparableFactoryQueryProcessor userSelectedComparableFactoryQueryProcessor;
+ protected UserSelectedViewpointFactoryQueryProcessor userSelectedViewpointFactoryQueryProcessor;
+ protected FilterSelectionRequestQueryProcessor filterSelectionRequestQueryProcessor;
+ protected IFilterArea filterArea;
+ protected EvaluatorData evaluatorData;
+
+ protected LocalResourceManager resourceManager;
+
+ protected ISelectionListener workbenchSelectionListener;
+
+ private final int style;
+
+ final private IWorkbenchSite site;
+
+ protected GraphExplorer explorer;
+
+ protected IMenuManager menuManager;
+
+ private final Map<String, Object> args;
+
+ protected ISessionContextProvider contextProvider;
+
+ private ISessionContext sessionContext;
+
+ private Object dragSource;
+
+ private IHintTracker sessionContextTracker = new SessionContextProjectTracker();
+
+ private InputSource inputSource = new DirectInputSource();
+ private FilterAreaSource filterAreaSource = new SelectionFilterAreaSource();
+
+ private final TreeColumnLayout ad;
+ private String[] editingColumn = ColumnKeys.KEYS_SINGLE;
+
+ private StatePersistor persistor = null;
+
+ private final Composite toolComposite;
+ private final Composite toolComposite2;
+ private final Composite explorerComposite;
+ final private WidgetSupport support;
+ private final boolean useNodeBrowseContexts;
+ private final boolean useNodeActionContexts;
+
+ static class SelectionElement extends AdaptableHintContext {
+
+ final public WorkbenchSelectionElement wse;
+ final public Object content;
+ final public Resource resource;
+ final public Variable variable;
+ final public Object input;
+ final public TransientExplorerState explorerState;
+
+ private WorkbenchSelectionElement extractWse(Object content) {
+ if(content instanceof NodeContext) {
+ NodeContext context = (NodeContext)content;
+ Object input = context.getConstant(NodeType.TYPE);
+ if(input instanceof NodeType)
+ return ((NodeType)input).getWorkbenchSelectionElement(context);
+ }
+ return null;
+ }
+
+ private Resource extractResource(Object content) {
+ if(content instanceof NodeContext) {
+ NodeContext context = (NodeContext)content;
+ Object input = context.getConstant(BuiltinKeys.INPUT);
+ if(input instanceof Resource) return (Resource)input;
+ if(input instanceof IAdaptable) {
+ Resource var = (Resource)((IAdaptable)input).getAdapter(Resource.class);
+ if(var != null) return var;
+ }
+ }
+ return null;
+ }
+
+ private Variable extractVariable(Object content) {
+ if(content instanceof NodeContext) {
+ NodeContext context = (NodeContext)content;
+ Object input = context.getConstant(BuiltinKeys.INPUT);
+ if(input instanceof Variable) return (Variable)input;
+ if(input instanceof IAdaptable) {
+ Variable var = (Variable)((IAdaptable)input).getAdapter(Variable.class);
+ if(var != null) return var;
+ }
+ }
+ return null;
+ }
+
+ private Object extractInput(Object content) {
+ if(content instanceof NodeContext) {
+ NodeContext context = (NodeContext)content;
+ return context.getConstant(BuiltinKeys.INPUT);
+ }
+ return null;
+ }
+
+ public SelectionElement(GraphExplorer explorer, Key[] keys, Object content) {
+ super(keys);
+ this.content = content;
+ this.wse = extractWse(content);
+ this.resource = extractResource(content);
+ this.variable = extractVariable(content);
+ this.input = extractInput(content);
+ this.explorerState = explorer.getTransientState();
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <T> T getContent(WorkbenchSelectionContentType<T> contentType) {
+ if (wse != null) {
+ T result = wse.getContent(contentType);
+ if (result != null)
+ return result;
+ }
+
+ if (contentType instanceof AnyResource) {
+ if (resource != null)
+ return (T) resource;
+ if (variable == null)
+ return null;
+ try {
+ return (T) ((AnyResource) contentType).processor.syncRequest(new PossibleVariableRepresents(variable));
+ } catch (DatabaseException e) {
+ LOGGER.error("Unexpected error occurred while resolving Resource from Variable " + variable, e);
+ }
+ }
+ else if (contentType instanceof AnyVariable) {
+ if (variable != null)
+ return (T) variable;
+ if (resource == null)
+ return null;
+ try {
+ return (T) ((AnyVariable) contentType).processor.syncRequest(new PossibleVariable(resource));
+ } catch (DatabaseException e) {
+ LOGGER.error("Unexpected error occurred while resolving Variable from Resource " + resource, e);
+ }
+ } else if (contentType instanceof ExplorerInputContentType) {
+ return (T) input;
+ } else if (contentType instanceof ExplorerColumnContentType) {
+ return (T) explorerState.getActiveColumn();
+ }
+ return null;
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public Object getAdapter(Class adapter) {
+ if(WorkbenchSelectionElement.class == adapter) {
+ return wse;
+ }
+ if(NodeContext.class == adapter) {
+ if(content instanceof NodeContext)
+ return (NodeContext)content;
+ else
+ return null;
+ }
+ return super.getAdapter(adapter);
+ }
+
+ }
+ private BiFunction<GraphExplorer, Object[], Object[]> selectionTransformation = new BiFunction<GraphExplorer, Object[], Object[]>() {
+
+ private Key[] KEYS = new Key[] { SelectionHints.KEY_MAIN };
+
+ @Override
+ public Object[] apply(GraphExplorer explorer, Object[] objects) {
+ Object[] result = new Object[objects.length];
+ for (int i = 0; i < objects.length; i++) {
+ SelectionElement context = new SelectionElement(explorer, KEYS, objects[i]);
+ context.setHint(SelectionHints.KEY_MAIN, objects[i]);
+ result[i] = context;
+ }
+ return result;
+ }
+
+ };
+
+ private Set<String> browseContexts = null;
+
+ private DisposeState disposeState = DisposeState.Alive;
+
+ private boolean created = false;
+
+ protected String contextMenuId = null;
+
+ protected Set<String> uiContext = null;
+
+ protected ISessionContextChangedListener contextChangeListener = new ISessionContextChangedListener() {
+ @Override
+ public void sessionContextChanged(SessionContextChangedEvent event) {
+ sessionContext = event.getNewValue();
+ sessionContextTracker.track(sessionContext);
+ }
+ };
+
+ public GraphExplorerComposite(Map<String, Object> args, IWorkbenchSite site, Composite parent, WidgetSupport support, int style) {
+
+ super(parent, SWT.NONE);
+
+ if (args == null)
+ args = Collections.emptyMap();
+
+ this.args = args;
+ this.site = site;
+ this.style = style;
+ this.resourceManager = new LocalResourceManager(JFaceResources.getResources(parent.getDisplay()), this);
+
+ contextProvider = getSessionContextProvider(site);
+
+ Integer maxChildren = (Integer)args.get("maxChildren");
+
+ GridLayoutFactory.fillDefaults().equalWidth(false).numColumns(1).margins(0,0).spacing(0,0).applyTo(this);
+
+ toolComposite = new Composite(this, SWT.NONE);
+// toolComposite.setBackground(toolComposite.getDisplay().getSystemColor(SWT.COLOR_DARK_YELLOW));
+// GridDataFactory.fillDefaults().grab(true, false).minSize(1, 1).applyTo(toolComposite);
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(toolComposite);
+ GridLayoutFactory.fillDefaults().applyTo(toolComposite);
+
+ ad = new TreeColumnLayout();
+ explorerComposite = new Composite(this, SWT.NONE);
+ explorerComposite.setLayout(ad);
+ GridDataFactory.fillDefaults().grab(true, true).minSize(1, 50).applyTo(explorerComposite);
+
+ if (args.containsKey("treeView") && Boolean.TRUE.equals(args.get("treeView"))) {
+ explorer = createExplorerControl2(explorerComposite, maxChildren);
+ } else if (args.containsKey("natTable") && Boolean.TRUE.equals(args.get("natTable"))) {
+ explorer = createExplorerControl3(explorerComposite, maxChildren);
+ } else {
+ explorer = createExplorerControl(explorerComposite, maxChildren);
+ }
+
+ if (args.containsKey("useNodeBrowseContexts") && Boolean.TRUE.equals(args.get("useNodeBrowseContexts"))) {
+ useNodeBrowseContexts = true;
+ } else {
+ useNodeBrowseContexts = false;
+ }
+
+ if (args.containsKey("useNodeActionContexts") && Boolean.TRUE.equals(args.get("useNodeActionContexts"))) {
+ useNodeActionContexts = true;
+ } else {
+ useNodeActionContexts = false;
+ }
+
+ toolComposite2 = new Composite(this, SWT.NONE);
+// toolComposite2.setBackground(toolComposite2.getDisplay().getSystemColor(SWT.COLOR_DARK_YELLOW));
+// GridDataFactory.fillDefaults().grab(true, false).minSize(1, 1).applyTo(toolComposite);
+ GridDataFactory.fillDefaults().grab(true, false).applyTo(toolComposite2);
+ GridLayoutFactory.fillDefaults().applyTo(toolComposite2);
+
+ this.support = support;
+
+ if (support != null)
+ support.register(this);
+
+ }
+
+ public GraphExplorerComposite(Map<String, Object> args, IWorkbenchSite site, Composite parent, int style) {
+
+ this(args, site, parent, null, style);
+
+ }
+
+ public ISessionContextProvider getSessionContextProvider(IWorkbenchSite site) {
+ if(site != null)
+ return SimanticsUI.getSessionContextProvider(site.getWorkbenchWindow());
+ else
+ return Simantics.getSessionContextProvider();
+ }
+
+ public GraphExplorer getExplorer() {
+ return explorer;
+ }
+
+ public Composite getExplorerComposite() {
+ return explorerComposite;
+ }
+
+ public <T> T getExplorerControl() {
+ return explorer.getControl();
+ }
+
+ public void addListenerToControl(int eventType, Listener listener) {
+ ((Control)explorer.getControl()).addListener(eventType, listener);
+ }
+
+ public void removeListenerFromControl(int eventType, Listener listener) {
+ ((Control)explorer.getControl()).removeListener(eventType, listener);
+ }
+
+ public void finish() {
+ created = true;
+ createControls(site);
+ attachToSession();
+ }
+
+ IWorkbenchSite getSite() {
+ return site;
+ }
+
+ protected void activateUiContexts() {
+ Collection<String> contexts = getUiContexts();
+ if (contexts == null || contexts.isEmpty())
+ return;
+ IWorkbenchSite site = getSite();
+ if (site != null) {
+ IContextService cs = (IContextService) getSite().getService(IContextService.class);
+ for (String context : contexts)
+ cs.activateContext(context);
+ }
+ }
+
+ protected void createControls(IWorkbenchSite site) {
+
+ // Initialize explorer control.
+// GridDataFactory.fillDefaults().grab(true, true).applyTo(explorer.getControl());
+
+ Control control = explorer.getControl();
+
+ // Initialize context menu if an initializer is provided.
+ IContextMenuInitializer cmi = getContextMenuInitializer();
+ if (cmi != null) {
+ ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class);
+ menuManager = cmi.createContextMenu(control, selectionProvider, site);
+ }
+
+ // Initialize UI contexts
+ activateUiContexts();
+
+ // Initialize DND.
+ dragSource = setupDND(explorer);
+
+ // Listeners are only added once per listener, not every time the
+ // session context changes.
+ addListeners(explorer, menuManager);
+
+ userSelectedComparableFactoryQueryProcessor = new UserSelectedComparableFactoryQueryProcessor();
+ userSelectedViewpointFactoryQueryProcessor = new UserSelectedViewpointFactoryQueryProcessor();
+ filterSelectionRequestQueryProcessor = new FilterSelectionRequestQueryProcessor();
+
+ explorer.setPrimitiveProcessor(filterSelectionRequestQueryProcessor);
+
+ boolean hasExtraControls = false;
+ boolean hasExtraControls2 = false;
+
+ Boolean displaySelectors = (Boolean)args.get("displaySelectors");
+ if(displaySelectors == null || displaySelectors == true) {
+
+ @SuppressWarnings("unused")
+ ComparatorSelector comparatorSelector = new ComparatorSelector(explorer, userSelectedComparableFactoryQueryProcessor, toolComposite, SWT.READ_ONLY);
+// comparatorSelector.moveAbove(control);
+
+ @SuppressWarnings("unused")
+ ViewpointSelector viewpointSelector = new ViewpointSelector(explorer, userSelectedViewpointFactoryQueryProcessor, toolComposite, SWT.READ_ONLY);
+// viewpointSelector.moveAbove(control);
+
+ hasExtraControls = true;
+
+ }
+
+ Boolean displayFilter = (Boolean)args.get("displayFilter");
+ if(displayFilter == null || displayFilter == true) {
+
+
+ filterArea = filterAreaSource.getFilterArea(toolComposite, explorer);
+// filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, toolComposite, SWT.READ_ONLY);
+ //filterArea.moveAbove(control);
+
+ hasExtraControls = true;
+
+ }
+
+ Boolean displayFilter2 = (Boolean)args.get("displayFilter2");
+ if(displayFilter2 != null && displayFilter2 == true) {
+
+ filterArea = filterAreaSource.getFilterArea(toolComposite2, explorer);
+// filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, toolComposite2, SWT.READ_ONLY);
+// //filterArea.moveAbove(control);
+
+ hasExtraControls2 = true;
+
+ }
+
+// filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, this, SWT.READ_ONLY);
+// filterArea.moveAbove(control);
+
+ if(!hasExtraControls)
+ GridDataFactory.fillDefaults().grab(true, false).minSize(0, 0).hint(0, 0).applyTo(toolComposite);
+ if(!hasExtraControls2)
+ GridDataFactory.fillDefaults().grab(true, false).minSize(0, 0).hint(0, 0).applyTo(toolComposite2);
+
+ GridDataFactory.fillDefaults().grab(true, true).span(2,1).applyTo(control);
+
+ //tree.getTree().setLayout(new FillLayout()
+ //this.setLayout(LayoutUtils.createNoBorderGridLayout(2, false));
+
+ DropTarget target = new DropTarget(control, DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK | DND.DROP_DEFAULT);
+ target.setTransfer(getAcceptedDataTypes());
+ if (control instanceof Tree) {
+ target.addDropListener(new DropTargetListener() {
+
+ Tree tree = (Tree)explorer.getControl();
+
+ @Override
+ public void dragEnter(DropTargetEvent event) {
+ event.detail = DND.DROP_COPY;
+ }
+
+ @Override
+ public void dragLeave(DropTargetEvent event) {
+ }
+
+ @Override
+ public void dragOperationChanged(DropTargetEvent event) {
+ }
+
+ @Override
+ public void dragOver(DropTargetEvent event) {
+ }
+
+ @Override
+ public void drop(DropTargetEvent event) {
+ TreeItem item = tree.getItem(tree.toControl(event.x, event.y));
+ if(item != null) {
+ Object data = item.getData();
+ if (data instanceof NodeContext)
+ handleDrop(event.data, (NodeContext) data);
+ else if (data instanceof IAdaptable) {
+ IAdaptable a = (IAdaptable) data;
+ handleDrop(event.data, (NodeContext) a.getAdapter(NodeContext.class));
+ }
+ } else
+ handleDrop(event.data, null);
+ }
+
+ @Override
+ public void dropAccept(DropTargetEvent event) {
+ }
+
+ });
+ }
+
+ // Add workbench listeners and make sure they are cleaned up
+ setWorkbenchListeners();
+ control.addListener(SWT.Dispose, new Listener() {
+ @Override
+ public void handleEvent(Event event) {
+ doDispose();
+ }
+ });
+ }
+
+ @SuppressWarnings({ "rawtypes", "unchecked" })
+ @Override
+ public Object getAdapter(Class adapter) {
+ if (GraphExplorer.class == adapter)
+ return explorer;
+ if (EvaluatorData.class == adapter)
+ return evaluatorData;
+ if (BrowseContext.class == adapter) {
+ EvaluatorData ed = evaluatorData;
+ return ed != null ? ed.getBrowseContext() : null;
+ }
+ if (adapter == IFilterAreaProvider.class)
+ return filterArea;
+ return explorer.getAdapter(adapter);
+ }
+
+ protected void doDispose() {
+ //System.out.println(this + ".GraphExplorerComposite.doDispose()");
+ removeWorkbenchListeners();
+ userSelectedComparableFactoryQueryProcessor = null;
+ userSelectedViewpointFactoryQueryProcessor = null;
+ filterSelectionRequestQueryProcessor = null;
+
+ disposeState = DisposeState.Disposing;
+ try {
+ //System.out.println(this + ".GraphExplorerViewBase.dispose()");
+ if (contextProvider != null) {
+ contextProvider.removeContextChangedListener(contextChangeListener);
+ contextProvider = null;
+ }
+ sessionContextTracker.untrack();
+ resourceManager = null;
+ explorer = null;
+ sessionContext = null;
+ dragSource = null;
+// parent = null;
+ } finally {
+ disposeState = DisposeState.Disposed;
+ }
+ }
+
+ @Override
+ public void dispose() {
+ doDispose();
+ super.dispose();
+ }
+
+ protected StatePersistor getStatePersistor() {
+ return persistor;
+ }
+
+ public void setStatePersistor(StatePersistor persistor) {
+ this.persistor = persistor;
+ }
+
+ protected void initializeExplorer(GraphExplorer explorer, ISessionContext context) {
+
+ if(explorer == null || explorer.isDisposed()) return;
+ if(context == null) return;
+ if(browseContexts == null) return;
+
+ Session session = context != null ? context.getSession() : null;
+ setupDragSource(session);
+
+ if (session != null) {
+ evaluatorData = createEvaluatorData(session);
+ explorer.setDataSource(new AsyncReadGraphDataSource(session));
+ explorer.setDataSource(new ReadGraphDataSource(session));
+ }
+ else {
+ evaluatorData = new EvaluatorDataImpl();
+ explorer.removeDataSource(AsyncReadGraph.class);
+ explorer.removeDataSource(ReadGraph.class);
+ }
+
+ explorer.setPersistor(getStatePersistor());
+
+ explorer.setProcessor(new ComparableFactoryResolver(evaluatorData));
+ explorer.setProcessor(new ViewpointFactoryResolver(evaluatorData));
+ explorer.setProcessor(new LabelerFactoryResolver(evaluatorData));
+ explorer.setProcessor(new ImagerFactoryResolver(evaluatorData));
+ explorer.setProcessor(new LabelDecoratorFactoryResolver(evaluatorData));
+ explorer.setProcessor(new ImageDecoratorFactoryResolver(evaluatorData));
+ explorer.setProcessor(new DefaultIsCheckedProcessor2(evaluatorData));
+ explorer.setPrimitiveProcessor(new TypesQueryProcessor());
+ explorer.setPrimitiveProcessor(new StandardContextTypesQueryProcessor());
+ explorer.setPrimitiveProcessor(new InheritsQueryProcessor());
+ explorer.setPrimitiveProcessor(new RelatedObjectsQueryProcessor());
+
+ explorer.setPrimitiveProcessor(userSelectedViewpointFactoryQueryProcessor);
+ explorer.setProcessor(new ComparableSelectorQueryProcessor());
+ explorer.setPrimitiveProcessor(userSelectedComparableFactoryQueryProcessor);
+ explorer.setPrimitiveProcessor(filterSelectionRequestQueryProcessor);
+
+ initializeExplorerWithEvaluator(explorer, context, evaluatorData);
+ }
+
+ protected void initializeExplorerWithEvaluator(GraphExplorer explorer, ISessionContext context, EvaluatorData data) {
+ }
+
+ protected EvaluatorData createEvaluatorData(Session context) {
+
+// Set<String> browseContexts = getArgument("browseContexts");
+
+ return Evaluators.load(context.getSession(), browseContexts, resourceManager, useNodeBrowseContexts, useNodeActionContexts);
+
+ }
+
+ protected Transfer[] getAcceptedDataTypes() {
+ return new Transfer[] { LocalObjectTransfer.getTransfer(), FileTransfer.getInstance(), TextTransfer.getInstance() };
+ }
+
+ protected void handleDrop(Object data, NodeContext target) {
+ }
+
+ DragSourceListenerFactory dragSourceListenerFactory = new DragSourceListenerFactory() {
+
+ final Transfer[] transfers = new Transfer[] {LocalObjectTransfer.getTransfer(), TextTransfer.getInstance() };
+
+ @Override
+ public DragSourceListener get(ISelectionProvider selectionProvider) {
+
+ LocalSelectionDragSourceListener ls = new LocalSelectionDragSourceListener(selectionProvider);
+
+ return new DragSourceListener() {
+
+ @Override
+ public void dragStart(DragSourceEvent event) {
+ ls.dragStart(event);
+ }
+
+ @Override
+ public void dragSetData(DragSourceEvent event) {
+ if(TextTransfer.getInstance().isSupportedType(event.dataType)) {
+ try {
+ event.data = WorkbenchSelectionUtils.getPossibleJSON(selectionProvider.getSelection());
+ } catch (DatabaseException e) {
+ event.data = "{ type:\"Exception\" }";
+ LOGGER.error("Failed to get current selection as JSON.", e);
+ }
+ } else if (LocalObjectTransfer.getTransfer().isSupportedType(event.dataType)) {
+ ls.dragSetData(event);
+ }
+ }
+
+ @Override
+ public void dragFinished(DragSourceEvent event) {
+ ls.dragFinished(event);
+ }
+ };
+ }
+
+ @Override
+ public Transfer[] getTransfers() {
+ return transfers;
+ }
+
+ };
+
+ public void setDragSourceListenerFactory(DragSourceListenerFactory dragSourceListenerFactory) {
+ this.dragSourceListenerFactory = dragSourceListenerFactory;
+ }
+
+ protected DragSourceListener setupDND(GraphExplorer explorer) {
+
+ ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class);
+
+ DragSourceListener listener = createDragSourceListener(selectionProvider);
+
+ Control control = explorer.getControl();
+ DragSource source = createDragSource(control);
+ source.setTransfer(getTransfers());
+ source.addDragListener(listener);
+ source.setDragSourceEffect(new NoImageDragSourceEffect(control));
+
+ return listener;
+
+ }
+
+ protected DragSourceListener createDragSourceListener(ISelectionProvider selectionProvider) {
+ return dragSourceListenerFactory.get(selectionProvider);
+ }
+
+ private int dragStyle = DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT;
+
+ protected void setDragStyle(int style) {
+ this.dragStyle = style;
+ }
+
+ protected int getDragStyle() {
+ return dragStyle;
+ }
+
+ protected DragSource createDragSource(Control control) {
+ return new DragSource(control, getDragStyle());
+ }
+
+ protected Transfer[] getTransfers() {
+ return dragSourceListenerFactory.getTransfers();
+ }
+
+ public EvaluatorData getEvaluatorData() {
+ return evaluatorData;
+ }
+
+ public interface InputSource {
+ /**
+ * @param ctx the session context to read the input from. May be
+ * <code>null</code> if there is no session.
+ * @return the input object of a graph explorer. To indicate no input,
+ * use {@link GraphExplorerConstants#EMPTY_INPUT}. Never return
+ * <code>null</code>.
+ */
+ Object get(ISessionContext ctx, Object selection);
+ }
+
+ public interface FilterSource {
+
+
+
+ }
+
+ /**
+ * The default hint tracker that will be active if
+ * {@link GraphExplorerComposite#setSessionContextTracker(IHintTracker) is
+ * not called.
+ */
+ public class SessionContextProjectTracker extends HintTracker {
+ public SessionContextProjectTracker() {
+ IHintListener activeProjectListener = new HintListenerAdapter() {
+ @Override
+ public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
+ applySessionContext(getSessionContext());
+ }
+ };
+ addKeyHintListener(ProjectKeys.KEY_PROJECT, activeProjectListener);
+ }
+ }
+
+ public class DirectInputSource implements InputSource {
+ @Override
+ public Object get(ISessionContext ctx, Object selection) {
+ return selection;
+ }
+ }
+
+ public static class SelectionFilterAreaSource implements FilterAreaSource {
+
+ @Override
+ public IFilterArea getFilterArea(Composite parent, GraphExplorer explorer) {
+ FilterSelectionRequestQueryProcessor processor = (FilterSelectionRequestQueryProcessor)explorer.getPrimitiveProcessor(BuiltinKeys.SELECTION_REQUESTS);
+ return new FilterArea(explorer, processor, parent, SWT.READ_ONLY);
+ }
+
+ }
+
+ public static class RootFilterAreaSource implements FilterAreaSource {
+
+ @Override
+ public IFilterArea getFilterArea(Composite parent, GraphExplorer explorer) {
+ FilterSelectionRequestQueryProcessor processor = (FilterSelectionRequestQueryProcessor)explorer.getPrimitiveProcessor(BuiltinKeys.SELECTION_REQUESTS);
+ return new RootFilterArea(explorer, processor, parent, SWT.READ_ONLY);
+ }
+
+ }
+
+ protected void setSessionContextTracker(IHintTracker tracker) {
+ this.sessionContextTracker = tracker;
+ }
+
+ public void setInputSource(InputSource source) {
+ this.inputSource = source;
+ }
+
+ public void setFilterAreaSource(FilterAreaSource provider) {
+ this.filterAreaSource = provider;
+ }
+
+ public void setSelectionTransformation(BiFunction<GraphExplorer, Object[], Object[]> transformation) {
+ this.selectionTransformation = transformation;
+ if(explorer != null) explorer.setSelectionTransformation(transformation);
+ }
+
+ protected Set<String> getBrowseContexts() {
+ return browseContexts;
+ }
+
+ public void setBrowseContexts(Set<String> contexts) {
+ this.browseContexts = contexts;
+ //initializeExplorer(explorer, getSessionContext());
+ }
+
+ public void setBrowseContexts(String ... contexts) {
+ this.browseContexts = new HashSet<String>();
+ for(String s : contexts) this.browseContexts.add(s);
+ initializeExplorer(explorer, getSessionContext());
+ }
+
+ public void setContextMenuId(String contextMenuId) {
+ this.contextMenuId = contextMenuId;
+ }
+
+// protected IContextMenuInitializer getContextMenuInitializer() {
+// String contextMenuId = getContextMenuId();
+// if(contextMenuId != null) {
+// return new ContextMenuInitializer(contextMenuId);
+// } else {
+// return null;
+// }
+// }
+
+ protected String getContextMenuId() {
+ return this.contextMenuId;
+ }
+
+ public void setUiContexts(Set<String> uiContext) {
+ this.uiContext = uiContext;
+ }
+
+ public Set<String> getUiContexts() {
+ return uiContext;
+ }
+
+ protected InputSource getInputSource() {
+ return inputSource;
+ }
+
+ protected Map<String, Object> getArguments() {
+ return args;
+ }
+
+ @SuppressWarnings("unchecked")
+ protected <T> T getArgument(String key) {
+ return (T) args.get(key);
+ }
+
+ protected DisposeState getDisposeState() {
+ return disposeState;
+ }
+
+ public ISessionContext getSessionContext() {
+ return sessionContext;
+ }
+
+ public ISessionContextProvider getSessionContextProvider() {
+ return contextProvider;
+ }
+
+ @Override
+ public boolean setFocus() {
+ if (explorer != null && !explorer.isDisposed())
+ explorer.setFocus();
+ return true;
+ }
+
+ public void setWorkbenchListeners() {
+ if (workbenchSelectionListener == null && getSite() != null) {
+ ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);
+ getSite().setSelectionProvider(selectionProvider);
+
+ // Listen to the workbench selection also to propagate it to
+ // the explorer also.
+ workbenchSelectionListener = new DefaultExplorerSelectionListener(site.getPage().getActivePart(), explorer);
+ //System.out.println("ADD WORKBENCH SELECTION LISTENER: " + workbenchSelectionListener);
+ getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(workbenchSelectionListener);
+ }
+ }
+
+ protected void removeWorkbenchListeners() {
+ //System.out.println("REMOVE WORKBENCH SELECTION LISTENER: " + workbenchSelectionListener);
+ // Remember to remove the installed workbench selection listener
+ if (workbenchSelectionListener != null) {
+ getSite().getWorkbenchWindow().getSelectionService().removePostSelectionListener(workbenchSelectionListener);
+ workbenchSelectionListener = null;
+
+ ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);
+ if(getSite().getSelectionProvider() == selectionProvider) getSite().setSelectionProvider(null);
+
+ }
+ }
+
+ protected final void attachToSession() {
+
+ // Track active ISessionContext changes
+ //contextProvider = SimanticsUI.getSessionContextProvider(getViewSite().getWorkbenchWindow());
+ contextProvider.addContextChangedListener(contextChangeListener);
+
+ // Start tracking the current session context for input changes.
+ // This will/must cause applySessionContext to get called.
+ // Doing the applySessionContext initialization this way
+ // instead of directly calling it will also make sure that
+ // applySessionContext is only called once when first initialized,
+ // and not twice like with the direct invocation.
+ this.sessionContext = contextProvider.getSessionContext();
+ sessionContextTracker.track(sessionContext);
+ }
+
+ // /////////////////////////////////////////////////////////////////////////
+ // Override / implement these:
+
+// /**
+// * Returns an ID that is used for persisting a GraphExplorer instance.
+// *
+// * Used for </code>restoreState(IMemento)</code> and
+// * <code>restoreState(IMemento)</code> in OntologyExplorer. Must be unique
+// * within a workbench part.
+// *
+// * @return a unique name for this particular graph explorer view used for
+// * saving and restoring the state of this view part
+// */
+// public String getExplorerName() {
+// return "GraphExplorerViewBase";
+// }
+
+ /**
+ * Override this method to add controls to the view part. This is invoked
+ * before attaching the view part to a database session.
+ *
+ * @param parent
+ */
+ protected void createControls(Composite parent) {
+
+ }
+
+ /**
+ * Override this method and provide a proper context menu initializer if you
+ * want to have this base class initialize one for you.
+ *
+ * @return the initializer to be used by {@link #createControls(Composite)}
+ */
+ protected IContextMenuInitializer getContextMenuInitializer() {
+ String contextMenuId = getContextMenuId();
+ if(contextMenuId != null) {
+ return new ContextMenuInitializer(contextMenuId);
+ } else {
+ return null;
+ }
+ }
+
+ /**
+ * @param parent
+ * @return
+ */
+ protected GraphExplorer createExplorerControl(Composite parent, Integer maxChildren) {
+ GraphExplorerFactory factory = GraphExplorerFactory.getInstance();
+ if(maxChildren != null) factory = factory.maxChildrenShown(maxChildren);
+
+ GraphExplorer ge = factory
+ .selectionDataResolver(new DefaultSelectionDataResolver())
+ .selectionTransformation(selectionTransformation)
+ .setServiceLocator(site)
+ .create(parent, style);
+
+ return ge;
+ }
+
+ protected GraphExplorer createExplorerControl2(Composite parent, Integer maxChildren) {
+ GraphExplorerFactory factory = GraphExplorerFactory.getInstance();
+ if(maxChildren != null) factory = factory.maxChildrenShown(maxChildren);
+
+ GraphExplorer ge = factory
+ .selectionDataResolver(new DefaultSelectionDataResolver())
+ .selectionTransformation(selectionTransformation)
+ .setServiceLocator(site)
+ .create2(parent, style);
+
+ return ge;
+ }
+
+ protected GraphExplorer createExplorerControl3(Composite parent, Integer maxChildren) {
+ GraphExplorerFactory factory = GraphExplorerFactory.getInstance();
+ if(maxChildren != null) factory = factory.maxChildrenShown(maxChildren);
+
+ GraphExplorer ge = factory
+ .selectionDataResolver(new DefaultSelectionDataResolver())
+ .selectionTransformation(selectionTransformation)
+ .setServiceLocator(site)
+ .create3(parent, style);
+
+ return ge;
+ }
+
+ protected void setupDragSource(Session session) {
+ if (dragSource instanceof SessionContainer) {
+ ((SessionContainer) dragSource).setSession(session);
+ }
+ }
+
+ /**
+ * Override to customize the addition of listeners a newly created
+ * GraphExplorer.
+ *
+ * @param explorer
+ */
+ protected void addListeners(GraphExplorer explorer, IMenuManager menuManager) {
+ addSelectionInputListeners(explorer, menuManager);
+ }
+
+ protected void addSelectionInputListeners(GraphExplorer explorer, IMenuManager menuManager) {
+ // Consider ENTER presses to simulate mouse left button double clicks
+ explorer.addListener(new DefaultKeyListener(contextProvider, explorer, new Function<String[]>() {
+ @Override
+ public String[] execute(Object... obj) {
+ return getEditingColumn((NodeContext) obj[0]);
+ }
+ }));
+ // Default double click handling
+ explorer.addListener(new DefaultMouseListener(explorer));
+ }
+
+ protected String[] getEditingColumn(NodeContext context) {
+ return editingColumn;
+ }
+
+ public void setEditingColumn(String... columnKeysInOrderOfTrial) {
+ this.editingColumn = columnKeysInOrderOfTrial;
+ }
+
+ // Needed for preventing unnecessary re-initialization of the explorer with the same input.
+ private Object currentInput;
+ private Object currentRoot;
+
+ /**
+ * Invoke this to reinitialize the explorer and reset its input. The input
+ * will be resolved from the specified ISessionContext based on the
+ * {@link SessionContextInputSource} that is currently in use. If the input
+ * is identical to the previous input, nothing will be done.
+ *
+ * @param context
+ */
+ public final boolean applySessionContext(ISessionContext context) {
+
+ // If control is not alive anymore, do nothing.
+ //System.out.println(this + ": applySessionContext(" + context + "), explorer=" + explorer);
+ if (disposeState != DisposeState.Alive)
+ return false;
+
+ //System.out.println(this + ": initializeExplorer(" + explorer + ", " + context + ")");
+ initializeExplorer(explorer, context);
+
+
+ // Start tracking the session context.
+ //
+ // If this is not the same session that is currently tracked, it will
+ // cause IHintListeners of the sessionContextTracker to fire.
+ // For this we need the above input equality (identity) checking.
+ // This is here just to make sure that we are tracking the correct
+ // session context.
+ sessionContextTracker.track(sessionContext);
+
+ this.sessionContext = context;
+ Object root = inputSource.get(context, currentInput);
+ if (ObjectUtils.objectEquals(root, currentRoot))
+ return false;
+
+ currentRoot = root;
+
+ //System.out.println(this + ": setRoot(" + input + ")");
+ explorer.setUIContexts(uiContext);
+ explorer.setRoot(root);
+
+ return true;
+
+ }
+
+ protected boolean isImportantInput(Object previousSelection, Object selection) {
+ return !ObjectUtils.objectEquals(previousSelection, selection);
+ }
+
+ public void setInput(Object selection, boolean force) {
+
+ assert(created);
+
+ if (isDisposed())
+ return;
+ if (sessionContext == null)
+ return;
+
+ // Check if this is a duplicate of the previous selection to reduce unnecessary flicker.
+ if (!force && !isImportantInput(currentInput, selection))
+ return;
+
+ currentInput = selection;
+
+ Object root = inputSource.get(sessionContext, selection);
+
+ currentRoot = root;
+
+ explorer.setUIContexts(uiContext);
+
+ if (root == null) {
+ explorer.setRoot(GraphExplorer.EMPTY_INPUT);
+ } else {
+ explorer.setRoot(root);
+ }
+
+ }
+
+ public void setColumnsVisible(boolean visible) {
+ explorer.setColumnsVisible(visible);
+ }
+
+ private int getColumnWidth(Column column, ExplorerState state) {
+ // Get saved width from the persistor if there is one.
+ if (state != null && state.columnWidths != null) {
+ Integer width = state.columnWidths.get(column.getLabel());
+ if (width != null)
+ return width;
+ }
+ return column.getWidth();
+ }
+
+ protected void restoreColumnSizes(Map<Column, Object> columns) {
+ if (persistor != null) {
+ setColumnData(columns, null);
+ ExplorerStates.scheduleRead(explorer.getRoot(), persistor).thenAccept(state -> {
+ SWTUtils.asyncExec(GraphExplorerComposite.this, () -> {
+ if (explorerComposite.isDisposed())
+ setColumnData(columns, state);
+ });
+ });
+ } else {
+ setColumnData(columns, null);
+ }
+ }
+
+ protected void setColumnData(Map<Column, Object> columns, ExplorerState state) {
+ columns.forEach((column, widget) -> {
+ org.eclipse.swt.widgets.Widget columnWidget = (org.eclipse.swt.widgets.Widget) widget;
+ ad.setColumnData(columnWidget,
+ new ColumnWeightData(
+ column.hasGrab() ? column.getWeight() : 0,
+ getColumnWidth(column, state)));
+ });
+ }
+
+ public void setColumns(Column[] columns) {
+ // ColumnWeightData does not support column weight/width < 0
+ for (Column column : columns) {
+ if (column.getWeight() < 0)
+ throw new IllegalArgumentException("Column weight must be >= 0, got " + column.getWeight() + " for " + column);
+ if (column.getWidth() < 0)
+ throw new IllegalArgumentException("Column minimum width must be >= 0, got " + column.getWidth() + " for " + column);
+ }
+ explorer.setColumns(columns, this::restoreColumnSizes);
+ }
+
+ @Override
+ public void setInput(ISessionContext context, Object input) {
+ setInput(input, false);
+ }
+
+ public void setMaxChildren(int maxChildren) {
+ explorer.setMaxChildren(maxChildren);
+ }
+
+ public <T> void addListener(ExplorerMouseListenerImpl<T> listener) {
+
+ support.register(listener);
+ listener.register(explorer);
+ explorer.addListener(listener);
+
+ }
+
+// @Override
+// public Point computeSize(int wHint, int hHint) {
+// Point p = super.computeSize(wHint, hHint);
+// System.err.println("graphExplorerComposite.computeSize " + p);
+// return p;
+// }
+//
+// @Override
+// public Point computeSize(int wHint, int hHint, boolean changed) {
+// Point p = super.computeSize(wHint, hHint, changed);
+// System.err.println("graphExplorerComposite.computeSize " + p);
+// return p;
+// }
+
+}