X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.browsing.ui.swt%2Fsrc%2Forg%2Fsimantics%2Fbrowsing%2Fui%2Fswt%2Fwidgets%2FGraphExplorerComposite.java;h=3ee82ae3b319b944c25b29337d68a27da05d7489;hp=a83c44ab1a3d39daa6573ae55bb0079fb775b4ec;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hpb=24e2b34260f219f0d1644ca7a138894980e25b14 diff --git a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/widgets/GraphExplorerComposite.java b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/widgets/GraphExplorerComposite.java index a83c44ab1..3ee82ae3b 100644 --- a/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/widgets/GraphExplorerComposite.java +++ b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/widgets/GraphExplorerComposite.java @@ -1,1270 +1,1270 @@ -/******************************************************************************* - * Copyright (c) 2007, 2012 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.Consumer; - -import org.eclipse.core.runtime.IAdaptable; -import org.eclipse.core.runtime.Platform; -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.TreeColumn; -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.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.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.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.Activator; -import org.simantics.browsing.ui.swt.AdaptableHintContext; -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.common.request.ResourceRead; -import org.simantics.db.common.utils.Logger; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.SelectionHints; -import org.simantics.db.layer0.variable.Variable; -import org.simantics.db.layer0.variable.Variables; -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.BinaryFunction; -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; - - -public class GraphExplorerComposite extends Composite implements Widget, IAdaptable { - - 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 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 getContent(WorkbenchSelectionContentType contentType) { - - if(wse != null) { - T result = wse.getContent(contentType); - if(result != null) return result; - } - - if(contentType instanceof AnyResource) return (T)resource; - else if(contentType instanceof AnyVariable) { - AnyVariable type = (AnyVariable)contentType; - try { - - if(variable != null) return (T)variable; - - if(resource == null) return null; - - return (T) type.processor.sync(new ResourceRead(resource) { - @Override - public Variable perform(ReadGraph graph) throws DatabaseException { - return Variables.getPossibleVariable(graph, resource); - } - - }); - } catch (DatabaseException e) { - Logger.defaultLogError(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 BinaryFunction selectionTransformation = new BinaryFunction() { - - private Key[] KEYS = new Key[] { SelectionHints.KEY_MAIN }; - - @Override - public Object[] call(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 browseContexts = null; - - private DisposeState disposeState = DisposeState.Alive; - - private boolean created = false; - - protected String contextMenuId = null; - - protected Set uiContext = null; - - protected ISessionContextChangedListener contextChangeListener = new ISessionContextChangedListener() { - @Override - public void sessionContextChanged(SessionContextChangedEvent event) { - sessionContext = event.getNewValue(); - sessionContextTracker.track(sessionContext); - } - }; - - public GraphExplorerComposite(Map 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 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 SimanticsUI.getSessionContextProvider(); - } - - public GraphExplorer getExplorer() { - return explorer; - } - - public Composite getExplorerComposite() { - return explorerComposite; - } - - public T getExplorerControl() { - return explorer.getControl(); - } - - public void addListenerToControl(int eventType, Listener listener) { - ((Control)explorer.getControl()).addListener(eventType, listener); - } - - public void finish() { - created = true; - createControls(site); - attachToSession(); - } - - IWorkbenchSite getSite() { - return site; - } - - protected void activateUiContexts() { - Collection 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_LINK); - 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 browseContexts = getArgument("browseContexts"); - - return Evaluators.load(context.getSession(), browseContexts, resourceManager, useNodeBrowseContexts, useNodeActionContexts); - - } - - protected Transfer[] getAcceptedDataTypes() { - return new Transfer[] { LocalObjectTransfer.getTransfer(), FileTransfer.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.defaultLogError(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 - * null if there is no session. - * @return the input object of a graph explorer. To indicate no input, - * use {@link GraphExplorerConstants#EMPTY_INPUT}. Never return - * null. - */ - 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(BinaryFunction transformation) { - this.selectionTransformation = transformation; - if(explorer != null) explorer.setSelectionTransformation(transformation); - } - - protected Set getBrowseContexts() { - return browseContexts; - } - - public void setBrowseContexts(Set contexts) { - this.browseContexts = contexts; - //initializeExplorer(explorer, getSessionContext()); - } - - public void setBrowseContexts(String ... contexts) { - this.browseContexts = new HashSet(); - 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 uiContext) { - this.uiContext = uiContext; - } - - public Set getUiContexts() { - return uiContext; - } - - protected InputSource getInputSource() { - return inputSource; - } - - protected Map getArguments() { - return args; - } - - @SuppressWarnings("unchecked") - protected 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 restoreState(IMemento) and -// * restoreState(IMemento) 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() { - @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(); - } - - public void setColumns(Column[] columns) { - - explorer.setColumns(columns, new Consumer>() { - - @Override - public void accept(Map objects) { - ExplorerState state = null; - if (persistor != null) { - state = persistor.deserialize( - Platform.getStateLocation(Activator.getDefault().getBundle()).toFile(), - explorer.getRoot()); - } - - for(Map.Entry entry : objects.entrySet()) { - Column column = entry.getKey(); - TreeColumn treeColumn = (TreeColumn)entry.getValue(); - - if (column.getWidth() < 0) { - throw new IllegalArgumentException("Column minimum width cannot be < 0, got " + column.getWidth()); - } - - int width = getColumnWidth(column, state); - if(column.hasGrab()) { - - ad.setColumnData(treeColumn, new ColumnWeightData(column.getWeight(), width)); - - } else { - - ad.setColumnData(treeColumn, new ColumnWeightData(0, width)); - - } - - } - } - - }); - - } - - @Override - public void setInput(ISessionContext context, Object input) { - setInput(input, false); - } - - public void setMaxChildren(int maxChildren) { - explorer.setMaxChildren(maxChildren); - } - - public void addListener(ExplorerMouseListenerImpl 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; -// } - -} +/******************************************************************************* + * Copyright (c) 2007, 2012 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.Consumer; + +import org.eclipse.core.runtime.IAdaptable; +import org.eclipse.core.runtime.Platform; +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.TreeColumn; +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.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.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.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.Activator; +import org.simantics.browsing.ui.swt.AdaptableHintContext; +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.common.request.ResourceRead; +import org.simantics.db.common.utils.Logger; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.SelectionHints; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.Variables; +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.BinaryFunction; +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; + + +public class GraphExplorerComposite extends Composite implements Widget, IAdaptable { + + 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 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 getContent(WorkbenchSelectionContentType contentType) { + + if(wse != null) { + T result = wse.getContent(contentType); + if(result != null) return result; + } + + if(contentType instanceof AnyResource) return (T)resource; + else if(contentType instanceof AnyVariable) { + AnyVariable type = (AnyVariable)contentType; + try { + + if(variable != null) return (T)variable; + + if(resource == null) return null; + + return (T) type.processor.sync(new ResourceRead(resource) { + @Override + public Variable perform(ReadGraph graph) throws DatabaseException { + return Variables.getPossibleVariable(graph, resource); + } + + }); + } catch (DatabaseException e) { + Logger.defaultLogError(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 BinaryFunction selectionTransformation = new BinaryFunction() { + + private Key[] KEYS = new Key[] { SelectionHints.KEY_MAIN }; + + @Override + public Object[] call(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 browseContexts = null; + + private DisposeState disposeState = DisposeState.Alive; + + private boolean created = false; + + protected String contextMenuId = null; + + protected Set uiContext = null; + + protected ISessionContextChangedListener contextChangeListener = new ISessionContextChangedListener() { + @Override + public void sessionContextChanged(SessionContextChangedEvent event) { + sessionContext = event.getNewValue(); + sessionContextTracker.track(sessionContext); + } + }; + + public GraphExplorerComposite(Map 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 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 SimanticsUI.getSessionContextProvider(); + } + + public GraphExplorer getExplorer() { + return explorer; + } + + public Composite getExplorerComposite() { + return explorerComposite; + } + + public T getExplorerControl() { + return explorer.getControl(); + } + + public void addListenerToControl(int eventType, Listener listener) { + ((Control)explorer.getControl()).addListener(eventType, listener); + } + + public void finish() { + created = true; + createControls(site); + attachToSession(); + } + + IWorkbenchSite getSite() { + return site; + } + + protected void activateUiContexts() { + Collection 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_LINK); + 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 browseContexts = getArgument("browseContexts"); + + return Evaluators.load(context.getSession(), browseContexts, resourceManager, useNodeBrowseContexts, useNodeActionContexts); + + } + + protected Transfer[] getAcceptedDataTypes() { + return new Transfer[] { LocalObjectTransfer.getTransfer(), FileTransfer.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.defaultLogError(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 + * null if there is no session. + * @return the input object of a graph explorer. To indicate no input, + * use {@link GraphExplorerConstants#EMPTY_INPUT}. Never return + * null. + */ + 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(BinaryFunction transformation) { + this.selectionTransformation = transformation; + if(explorer != null) explorer.setSelectionTransformation(transformation); + } + + protected Set getBrowseContexts() { + return browseContexts; + } + + public void setBrowseContexts(Set contexts) { + this.browseContexts = contexts; + //initializeExplorer(explorer, getSessionContext()); + } + + public void setBrowseContexts(String ... contexts) { + this.browseContexts = new HashSet(); + 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 uiContext) { + this.uiContext = uiContext; + } + + public Set getUiContexts() { + return uiContext; + } + + protected InputSource getInputSource() { + return inputSource; + } + + protected Map getArguments() { + return args; + } + + @SuppressWarnings("unchecked") + protected 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 restoreState(IMemento) and +// * restoreState(IMemento) 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() { + @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(); + } + + public void setColumns(Column[] columns) { + + explorer.setColumns(columns, new Consumer>() { + + @Override + public void accept(Map objects) { + ExplorerState state = null; + if (persistor != null) { + state = persistor.deserialize( + Platform.getStateLocation(Activator.getDefault().getBundle()).toFile(), + explorer.getRoot()); + } + + for(Map.Entry entry : objects.entrySet()) { + Column column = entry.getKey(); + TreeColumn treeColumn = (TreeColumn)entry.getValue(); + + if (column.getWidth() < 0) { + throw new IllegalArgumentException("Column minimum width cannot be < 0, got " + column.getWidth()); + } + + int width = getColumnWidth(column, state); + if(column.hasGrab()) { + + ad.setColumnData(treeColumn, new ColumnWeightData(column.getWeight(), width)); + + } else { + + ad.setColumnData(treeColumn, new ColumnWeightData(0, width)); + + } + + } + } + + }); + + } + + @Override + public void setInput(ISessionContext context, Object input) { + setInput(input, false); + } + + public void setMaxChildren(int maxChildren) { + explorer.setMaxChildren(maxChildren); + } + + public void addListener(ExplorerMouseListenerImpl 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; +// } + +}