X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.browsing.ui.swt%2Fsrc%2Forg%2Fsimantics%2Fbrowsing%2Fui%2Fswt%2Fwidgets%2FGraphExplorerComposite.java;fp=bundles%2Forg.simantics.browsing.ui.swt%2Fsrc%2Forg%2Fsimantics%2Fbrowsing%2Fui%2Fswt%2Fwidgets%2FGraphExplorerComposite.java;h=5e324fa760d25fea3e0e8a298299806f7d337d0c;hb=969bd23cab98a79ca9101af33334000879fb60c5;hp=0000000000000000000000000000000000000000;hpb=866dba5cd5a3929bbeae85991796acb212338a08;p=simantics%2Fplatform.git 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 new file mode 100644 index 000000000..5e324fa76 --- /dev/null +++ b/bundles/org.simantics.browsing.ui.swt/src/org/simantics/browsing/ui/swt/widgets/GraphExplorerComposite.java @@ -0,0 +1,1253 @@ +/******************************************************************************* + * 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 { + 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) { + ((Tree)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()); + 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 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; +// } + +}