1 /*******************************************************************************
2 * Copyright (c) 2007, 2012 Association for Decentralized Information Management
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.browsing.ui.swt.widgets;
14 import java.util.Collection;
15 import java.util.Collections;
16 import java.util.HashSet;
19 import java.util.function.Consumer;
21 import org.eclipse.core.runtime.IAdaptable;
22 import org.eclipse.core.runtime.Platform;
23 import org.eclipse.jface.action.IMenuManager;
24 import org.eclipse.jface.layout.GridDataFactory;
25 import org.eclipse.jface.layout.GridLayoutFactory;
26 import org.eclipse.jface.layout.TreeColumnLayout;
27 import org.eclipse.jface.resource.JFaceResources;
28 import org.eclipse.jface.resource.LocalResourceManager;
29 import org.eclipse.jface.viewers.ColumnWeightData;
30 import org.eclipse.jface.viewers.ISelectionProvider;
31 import org.eclipse.swt.SWT;
32 import org.eclipse.swt.dnd.DND;
33 import org.eclipse.swt.dnd.DragSource;
34 import org.eclipse.swt.dnd.DragSourceEvent;
35 import org.eclipse.swt.dnd.DragSourceListener;
36 import org.eclipse.swt.dnd.DropTarget;
37 import org.eclipse.swt.dnd.DropTargetEvent;
38 import org.eclipse.swt.dnd.DropTargetListener;
39 import org.eclipse.swt.dnd.FileTransfer;
40 import org.eclipse.swt.dnd.TextTransfer;
41 import org.eclipse.swt.dnd.Transfer;
42 import org.eclipse.swt.widgets.Composite;
43 import org.eclipse.swt.widgets.Control;
44 import org.eclipse.swt.widgets.Event;
45 import org.eclipse.swt.widgets.Listener;
46 import org.eclipse.swt.widgets.Tree;
47 import org.eclipse.swt.widgets.TreeColumn;
48 import org.eclipse.swt.widgets.TreeItem;
49 import org.eclipse.ui.ISelectionListener;
50 import org.eclipse.ui.IWorkbenchSite;
51 import org.eclipse.ui.contexts.IContextService;
52 import org.simantics.browsing.ui.BuiltinKeys;
53 import org.simantics.browsing.ui.Column;
54 import org.simantics.browsing.ui.ExplorerState;
55 import org.simantics.browsing.ui.GraphExplorer;
56 import org.simantics.browsing.ui.GraphExplorer.TransientExplorerState;
57 import org.simantics.browsing.ui.NodeContext;
58 import org.simantics.browsing.ui.StatePersistor;
59 import org.simantics.browsing.ui.common.ColumnKeys;
60 import org.simantics.browsing.ui.common.EvaluatorData;
61 import org.simantics.browsing.ui.common.EvaluatorDataImpl;
62 import org.simantics.browsing.ui.common.processors.ComparableFactoryResolver;
63 import org.simantics.browsing.ui.common.processors.ComparableSelectorQueryProcessor;
64 import org.simantics.browsing.ui.common.processors.FilterSelectionRequestQueryProcessor;
65 import org.simantics.browsing.ui.common.processors.ImageDecoratorFactoryResolver;
66 import org.simantics.browsing.ui.common.processors.ImagerFactoryResolver;
67 import org.simantics.browsing.ui.common.processors.LabelDecoratorFactoryResolver;
68 import org.simantics.browsing.ui.common.processors.LabelerFactoryResolver;
69 import org.simantics.browsing.ui.common.processors.UserSelectedComparableFactoryQueryProcessor;
70 import org.simantics.browsing.ui.common.processors.UserSelectedViewpointFactoryQueryProcessor;
71 import org.simantics.browsing.ui.common.processors.ViewpointFactoryResolver;
72 import org.simantics.browsing.ui.common.views.FilterAreaSource;
73 import org.simantics.browsing.ui.common.views.IFilterArea;
74 import org.simantics.browsing.ui.common.views.IFilterAreaProvider;
75 import org.simantics.browsing.ui.graph.impl.AsyncReadGraphDataSource;
76 import org.simantics.browsing.ui.graph.impl.Evaluators;
77 import org.simantics.browsing.ui.graph.impl.InheritsQueryProcessor;
78 import org.simantics.browsing.ui.graph.impl.ReadGraphDataSource;
79 import org.simantics.browsing.ui.graph.impl.RelatedObjectsQueryProcessor;
80 import org.simantics.browsing.ui.graph.impl.SessionContextInputSource;
81 import org.simantics.browsing.ui.model.browsecontexts.BrowseContext;
82 import org.simantics.browsing.ui.model.nodetypes.NodeType;
83 import org.simantics.browsing.ui.swt.Activator;
84 import org.simantics.browsing.ui.swt.AdaptableHintContext;
85 import org.simantics.browsing.ui.swt.ComparatorSelector;
86 import org.simantics.browsing.ui.swt.ContextMenuInitializer;
87 import org.simantics.browsing.ui.swt.DefaultExplorerSelectionListener;
88 import org.simantics.browsing.ui.swt.DefaultIsCheckedProcessor2;
89 import org.simantics.browsing.ui.swt.DefaultKeyListener;
90 import org.simantics.browsing.ui.swt.DefaultMouseListener;
91 import org.simantics.browsing.ui.swt.DefaultSelectionDataResolver;
92 import org.simantics.browsing.ui.swt.FilterArea;
93 import org.simantics.browsing.ui.swt.GraphExplorerFactory;
94 import org.simantics.browsing.ui.swt.IContextMenuInitializer;
95 import org.simantics.browsing.ui.swt.RootFilterArea;
96 import org.simantics.browsing.ui.swt.StandardContextTypesQueryProcessor;
97 import org.simantics.browsing.ui.swt.TypesQueryProcessor;
98 import org.simantics.browsing.ui.swt.ViewpointSelector;
99 import org.simantics.browsing.ui.swt.widgets.impl.Widget;
100 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;
101 import org.simantics.db.AsyncReadGraph;
102 import org.simantics.db.ReadGraph;
103 import org.simantics.db.Resource;
104 import org.simantics.db.Session;
105 import org.simantics.db.common.request.ResourceRead;
106 import org.simantics.db.common.utils.Logger;
107 import org.simantics.db.exception.DatabaseException;
108 import org.simantics.db.layer0.SelectionHints;
109 import org.simantics.db.layer0.variable.Variable;
110 import org.simantics.db.layer0.variable.Variables;
111 import org.simantics.db.management.ISessionContext;
112 import org.simantics.db.management.ISessionContextChangedListener;
113 import org.simantics.db.management.ISessionContextProvider;
114 import org.simantics.db.management.SessionContextChangedEvent;
115 import org.simantics.project.ProjectKeys;
116 import org.simantics.ui.SimanticsUI;
117 import org.simantics.ui.dnd.LocalObjectTransfer;
118 import org.simantics.ui.dnd.LocalSelectionDragSourceListener;
119 import org.simantics.ui.dnd.NoImageDragSourceEffect;
120 import org.simantics.ui.dnd.SessionContainer;
121 import org.simantics.ui.selection.AnyResource;
122 import org.simantics.ui.selection.AnyVariable;
123 import org.simantics.ui.selection.ExplorerColumnContentType;
124 import org.simantics.ui.selection.ExplorerInputContentType;
125 import org.simantics.ui.selection.WorkbenchSelectionContentType;
126 import org.simantics.ui.selection.WorkbenchSelectionElement;
127 import org.simantics.ui.selection.WorkbenchSelectionUtils;
128 import org.simantics.utils.ObjectUtils;
129 import org.simantics.utils.datastructures.BinaryFunction;
130 import org.simantics.utils.datastructures.Function;
131 import org.simantics.utils.datastructures.disposable.DisposeState;
132 import org.simantics.utils.datastructures.hints.HintListenerAdapter;
133 import org.simantics.utils.datastructures.hints.HintTracker;
134 import org.simantics.utils.datastructures.hints.IHintContext.Key;
135 import org.simantics.utils.datastructures.hints.IHintListener;
136 import org.simantics.utils.datastructures.hints.IHintObservable;
137 import org.simantics.utils.datastructures.hints.IHintTracker;
140 public class GraphExplorerComposite extends Composite implements Widget, IAdaptable {
142 protected UserSelectedComparableFactoryQueryProcessor userSelectedComparableFactoryQueryProcessor;
143 protected UserSelectedViewpointFactoryQueryProcessor userSelectedViewpointFactoryQueryProcessor;
144 protected FilterSelectionRequestQueryProcessor filterSelectionRequestQueryProcessor;
145 protected IFilterArea filterArea;
146 protected EvaluatorData evaluatorData;
148 protected LocalResourceManager resourceManager;
150 protected ISelectionListener workbenchSelectionListener;
152 private final int style;
154 final private IWorkbenchSite site;
156 protected GraphExplorer explorer;
158 protected IMenuManager menuManager;
160 private final Map<String, Object> args;
162 protected ISessionContextProvider contextProvider;
164 private ISessionContext sessionContext;
166 private Object dragSource;
168 private IHintTracker sessionContextTracker = new SessionContextProjectTracker();
170 private InputSource inputSource = new DirectInputSource();
171 private FilterAreaSource filterAreaSource = new SelectionFilterAreaSource();
173 private final TreeColumnLayout ad;
174 private String[] editingColumn = ColumnKeys.KEYS_SINGLE;
176 private StatePersistor persistor = null;
178 private final Composite toolComposite;
179 private final Composite toolComposite2;
180 private final Composite explorerComposite;
181 final private WidgetSupport support;
182 private final boolean useNodeBrowseContexts;
183 private final boolean useNodeActionContexts;
185 static class SelectionElement extends AdaptableHintContext {
187 final public WorkbenchSelectionElement wse;
188 final public Object content;
189 final public Resource resource;
190 final public Variable variable;
191 final public Object input;
192 final public TransientExplorerState explorerState;
194 private WorkbenchSelectionElement extractWse(Object content) {
195 if(content instanceof NodeContext) {
196 NodeContext context = (NodeContext)content;
197 Object input = context.getConstant(NodeType.TYPE);
198 if(input instanceof NodeType)
199 return ((NodeType)input).getWorkbenchSelectionElement(context);
204 private Resource extractResource(Object content) {
205 if(content instanceof NodeContext) {
206 NodeContext context = (NodeContext)content;
207 Object input = context.getConstant(BuiltinKeys.INPUT);
208 if(input instanceof Resource) return (Resource)input;
209 if(input instanceof IAdaptable) {
210 Resource var = (Resource)((IAdaptable)input).getAdapter(Resource.class);
211 if(var != null) return var;
217 private Variable extractVariable(Object content) {
218 if(content instanceof NodeContext) {
219 NodeContext context = (NodeContext)content;
220 Object input = context.getConstant(BuiltinKeys.INPUT);
221 if(input instanceof Variable) return (Variable)input;
222 if(input instanceof IAdaptable) {
223 Variable var = (Variable)((IAdaptable)input).getAdapter(Variable.class);
224 if(var != null) return var;
230 private Object extractInput(Object content) {
231 if(content instanceof NodeContext) {
232 NodeContext context = (NodeContext)content;
233 return context.getConstant(BuiltinKeys.INPUT);
238 public SelectionElement(GraphExplorer explorer, Key[] keys, Object content) {
240 this.content = content;
241 this.wse = extractWse(content);
242 this.resource = extractResource(content);
243 this.variable = extractVariable(content);
244 this.input = extractInput(content);
245 this.explorerState = explorer.getTransientState();
248 @SuppressWarnings("unchecked")
250 public <T> T getContent(WorkbenchSelectionContentType<T> contentType) {
253 T result = wse.getContent(contentType);
254 if(result != null) return result;
257 if(contentType instanceof AnyResource) return (T)resource;
258 else if(contentType instanceof AnyVariable) {
259 AnyVariable type = (AnyVariable)contentType;
262 if(variable != null) return (T)variable;
264 if(resource == null) return null;
266 return (T) type.processor.sync(new ResourceRead<Variable>(resource) {
268 public Variable perform(ReadGraph graph) throws DatabaseException {
269 return Variables.getPossibleVariable(graph, resource);
273 } catch (DatabaseException e) {
274 Logger.defaultLogError(e);
276 } else if (contentType instanceof ExplorerInputContentType) {
278 } else if (contentType instanceof ExplorerColumnContentType) {
279 return (T)explorerState.getActiveColumn();
284 @SuppressWarnings("rawtypes")
286 public Object getAdapter(Class adapter) {
287 if(WorkbenchSelectionElement.class == adapter) {
290 if(NodeContext.class == adapter) {
291 if(content instanceof NodeContext)
292 return (NodeContext)content;
296 return super.getAdapter(adapter);
300 private BinaryFunction<Object[], GraphExplorer, Object[]> selectionTransformation = new BinaryFunction<Object[], GraphExplorer, Object[]>() {
302 private Key[] KEYS = new Key[] { SelectionHints.KEY_MAIN };
305 public Object[] call(GraphExplorer explorer, Object[] objects) {
306 Object[] result = new Object[objects.length];
307 for (int i = 0; i < objects.length; i++) {
308 SelectionElement context = new SelectionElement(explorer, KEYS, objects[i]);
309 context.setHint(SelectionHints.KEY_MAIN, objects[i]);
317 private Set<String> browseContexts = null;
319 private DisposeState disposeState = DisposeState.Alive;
321 private boolean created = false;
323 protected String contextMenuId = null;
325 protected Set<String> uiContext = null;
327 protected ISessionContextChangedListener contextChangeListener = new ISessionContextChangedListener() {
329 public void sessionContextChanged(SessionContextChangedEvent event) {
330 sessionContext = event.getNewValue();
331 sessionContextTracker.track(sessionContext);
335 public GraphExplorerComposite(Map<String, Object> args, IWorkbenchSite site, Composite parent, WidgetSupport support, int style) {
337 super(parent, SWT.NONE);
340 args = Collections.emptyMap();
345 this.resourceManager = new LocalResourceManager(JFaceResources.getResources(parent.getDisplay()), this);
347 contextProvider = getSessionContextProvider(site);
349 Integer maxChildren = (Integer)args.get("maxChildren");
351 GridLayoutFactory.fillDefaults().equalWidth(false).numColumns(1).margins(0,0).spacing(0,0).applyTo(this);
353 toolComposite = new Composite(this, SWT.NONE);
354 // toolComposite.setBackground(toolComposite.getDisplay().getSystemColor(SWT.COLOR_DARK_YELLOW));
355 // GridDataFactory.fillDefaults().grab(true, false).minSize(1, 1).applyTo(toolComposite);
356 GridDataFactory.fillDefaults().grab(true, false).applyTo(toolComposite);
357 GridLayoutFactory.fillDefaults().applyTo(toolComposite);
359 ad = new TreeColumnLayout();
360 explorerComposite = new Composite(this, SWT.NONE);
361 explorerComposite.setLayout(ad);
362 GridDataFactory.fillDefaults().grab(true, true).minSize(1, 50).applyTo(explorerComposite);
364 if (args.containsKey("treeView") && Boolean.TRUE.equals(args.get("treeView"))) {
365 explorer = createExplorerControl2(explorerComposite, maxChildren);
366 } else if (args.containsKey("natTable") && Boolean.TRUE.equals(args.get("natTable"))) {
367 explorer = createExplorerControl3(explorerComposite, maxChildren);
369 explorer = createExplorerControl(explorerComposite, maxChildren);
372 if (args.containsKey("useNodeBrowseContexts") && Boolean.TRUE.equals(args.get("useNodeBrowseContexts"))) {
373 useNodeBrowseContexts = true;
375 useNodeBrowseContexts = false;
378 if (args.containsKey("useNodeActionContexts") && Boolean.TRUE.equals(args.get("useNodeActionContexts"))) {
379 useNodeActionContexts = true;
381 useNodeActionContexts = false;
384 toolComposite2 = new Composite(this, SWT.NONE);
385 // toolComposite2.setBackground(toolComposite2.getDisplay().getSystemColor(SWT.COLOR_DARK_YELLOW));
386 // GridDataFactory.fillDefaults().grab(true, false).minSize(1, 1).applyTo(toolComposite);
387 GridDataFactory.fillDefaults().grab(true, false).applyTo(toolComposite2);
388 GridLayoutFactory.fillDefaults().applyTo(toolComposite2);
390 this.support = support;
393 support.register(this);
397 public GraphExplorerComposite(Map<String, Object> args, IWorkbenchSite site, Composite parent, int style) {
399 this(args, site, parent, null, style);
403 public ISessionContextProvider getSessionContextProvider(IWorkbenchSite site) {
405 return SimanticsUI.getSessionContextProvider(site.getWorkbenchWindow());
407 return SimanticsUI.getSessionContextProvider();
410 public GraphExplorer getExplorer() {
414 public Composite getExplorerComposite() {
415 return explorerComposite;
418 public <T> T getExplorerControl() {
419 return explorer.getControl();
422 public void addListenerToControl(int eventType, Listener listener) {
423 ((Control)explorer.getControl()).addListener(eventType, listener);
426 public void finish() {
428 createControls(site);
432 IWorkbenchSite getSite() {
436 protected void activateUiContexts() {
437 Collection<String> contexts = getUiContexts();
438 if (contexts == null || contexts.isEmpty())
440 IWorkbenchSite site = getSite();
442 IContextService cs = (IContextService) getSite().getService(IContextService.class);
443 for (String context : contexts)
444 cs.activateContext(context);
448 protected void createControls(IWorkbenchSite site) {
450 // Initialize explorer control.
451 // GridDataFactory.fillDefaults().grab(true, true).applyTo(explorer.getControl());
453 Control control = explorer.getControl();
455 // Initialize context menu if an initializer is provided.
456 IContextMenuInitializer cmi = getContextMenuInitializer();
458 ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class);
459 menuManager = cmi.createContextMenu(control, selectionProvider, site);
462 // Initialize UI contexts
463 activateUiContexts();
466 dragSource = setupDND(explorer);
468 // Listeners are only added once per listener, not every time the
469 // session context changes.
470 addListeners(explorer, menuManager);
472 userSelectedComparableFactoryQueryProcessor = new UserSelectedComparableFactoryQueryProcessor();
473 userSelectedViewpointFactoryQueryProcessor = new UserSelectedViewpointFactoryQueryProcessor();
474 filterSelectionRequestQueryProcessor = new FilterSelectionRequestQueryProcessor();
476 explorer.setPrimitiveProcessor(filterSelectionRequestQueryProcessor);
478 boolean hasExtraControls = false;
479 boolean hasExtraControls2 = false;
481 Boolean displaySelectors = (Boolean)args.get("displaySelectors");
482 if(displaySelectors == null || displaySelectors == true) {
484 @SuppressWarnings("unused")
485 ComparatorSelector comparatorSelector = new ComparatorSelector(explorer, userSelectedComparableFactoryQueryProcessor, toolComposite, SWT.READ_ONLY);
486 // comparatorSelector.moveAbove(control);
488 @SuppressWarnings("unused")
489 ViewpointSelector viewpointSelector = new ViewpointSelector(explorer, userSelectedViewpointFactoryQueryProcessor, toolComposite, SWT.READ_ONLY);
490 // viewpointSelector.moveAbove(control);
492 hasExtraControls = true;
496 Boolean displayFilter = (Boolean)args.get("displayFilter");
497 if(displayFilter == null || displayFilter == true) {
500 filterArea = filterAreaSource.getFilterArea(toolComposite, explorer);
501 // filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, toolComposite, SWT.READ_ONLY);
502 //filterArea.moveAbove(control);
504 hasExtraControls = true;
508 Boolean displayFilter2 = (Boolean)args.get("displayFilter2");
509 if(displayFilter2 != null && displayFilter2 == true) {
511 filterArea = filterAreaSource.getFilterArea(toolComposite2, explorer);
512 // filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, toolComposite2, SWT.READ_ONLY);
513 // //filterArea.moveAbove(control);
515 hasExtraControls2 = true;
519 // filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, this, SWT.READ_ONLY);
520 // filterArea.moveAbove(control);
522 if(!hasExtraControls)
523 GridDataFactory.fillDefaults().grab(true, false).minSize(0, 0).hint(0, 0).applyTo(toolComposite);
524 if(!hasExtraControls2)
525 GridDataFactory.fillDefaults().grab(true, false).minSize(0, 0).hint(0, 0).applyTo(toolComposite2);
527 GridDataFactory.fillDefaults().grab(true, true).span(2,1).applyTo(control);
529 //tree.getTree().setLayout(new FillLayout()
530 //this.setLayout(LayoutUtils.createNoBorderGridLayout(2, false));
532 DropTarget target = new DropTarget(control, DND.DROP_COPY | DND.DROP_LINK);
533 target.setTransfer(getAcceptedDataTypes());
534 if (control instanceof Tree) {
535 target.addDropListener(new DropTargetListener() {
537 Tree tree = (Tree)explorer.getControl();
540 public void dragEnter(DropTargetEvent event) {
541 event.detail = DND.DROP_COPY;
545 public void dragLeave(DropTargetEvent event) {
549 public void dragOperationChanged(DropTargetEvent event) {
553 public void dragOver(DropTargetEvent event) {
557 public void drop(DropTargetEvent event) {
558 TreeItem item = tree.getItem(tree.toControl(event.x, event.y));
560 Object data = item.getData();
561 if (data instanceof NodeContext)
562 handleDrop(event.data, (NodeContext) data);
563 else if (data instanceof IAdaptable) {
564 IAdaptable a = (IAdaptable) data;
565 handleDrop(event.data, (NodeContext) a.getAdapter(NodeContext.class));
568 handleDrop(event.data, null);
572 public void dropAccept(DropTargetEvent event) {
578 // Add workbench listeners and make sure they are cleaned up
579 setWorkbenchListeners();
580 control.addListener(SWT.Dispose, new Listener() {
582 public void handleEvent(Event event) {
588 @SuppressWarnings({ "rawtypes", "unchecked" })
590 public Object getAdapter(Class adapter) {
591 if (GraphExplorer.class == adapter)
593 if (EvaluatorData.class == adapter)
594 return evaluatorData;
595 if (BrowseContext.class == adapter) {
596 EvaluatorData ed = evaluatorData;
597 return ed != null ? ed.getBrowseContext() : null;
599 if (adapter == IFilterAreaProvider.class)
601 return explorer.getAdapter(adapter);
604 protected void doDispose() {
605 //System.out.println(this + ".GraphExplorerComposite.doDispose()");
606 removeWorkbenchListeners();
607 userSelectedComparableFactoryQueryProcessor = null;
608 userSelectedViewpointFactoryQueryProcessor = null;
609 filterSelectionRequestQueryProcessor = null;
611 disposeState = DisposeState.Disposing;
613 //System.out.println(this + ".GraphExplorerViewBase.dispose()");
614 if (contextProvider != null) {
615 contextProvider.removeContextChangedListener(contextChangeListener);
616 contextProvider = null;
618 sessionContextTracker.untrack();
619 resourceManager = null;
621 sessionContext = null;
625 disposeState = DisposeState.Disposed;
630 public void dispose() {
635 protected StatePersistor getStatePersistor() {
639 public void setStatePersistor(StatePersistor persistor) {
640 this.persistor = persistor;
643 protected void initializeExplorer(GraphExplorer explorer, ISessionContext context) {
645 if(explorer == null || explorer.isDisposed()) return;
646 if(context == null) return;
647 if(browseContexts == null) return;
649 Session session = context != null ? context.getSession() : null;
650 setupDragSource(session);
652 if (session != null) {
653 evaluatorData = createEvaluatorData(session);
654 explorer.setDataSource(new AsyncReadGraphDataSource(session));
655 explorer.setDataSource(new ReadGraphDataSource(session));
658 evaluatorData = new EvaluatorDataImpl();
659 explorer.removeDataSource(AsyncReadGraph.class);
660 explorer.removeDataSource(ReadGraph.class);
663 explorer.setPersistor(getStatePersistor());
665 explorer.setProcessor(new ComparableFactoryResolver(evaluatorData));
666 explorer.setProcessor(new ViewpointFactoryResolver(evaluatorData));
667 explorer.setProcessor(new LabelerFactoryResolver(evaluatorData));
668 explorer.setProcessor(new ImagerFactoryResolver(evaluatorData));
669 explorer.setProcessor(new LabelDecoratorFactoryResolver(evaluatorData));
670 explorer.setProcessor(new ImageDecoratorFactoryResolver(evaluatorData));
671 explorer.setProcessor(new DefaultIsCheckedProcessor2(evaluatorData));
672 explorer.setPrimitiveProcessor(new TypesQueryProcessor());
673 explorer.setPrimitiveProcessor(new StandardContextTypesQueryProcessor());
674 explorer.setPrimitiveProcessor(new InheritsQueryProcessor());
675 explorer.setPrimitiveProcessor(new RelatedObjectsQueryProcessor());
677 explorer.setPrimitiveProcessor(userSelectedViewpointFactoryQueryProcessor);
678 explorer.setProcessor(new ComparableSelectorQueryProcessor());
679 explorer.setPrimitiveProcessor(userSelectedComparableFactoryQueryProcessor);
680 explorer.setPrimitiveProcessor(filterSelectionRequestQueryProcessor);
682 initializeExplorerWithEvaluator(explorer, context, evaluatorData);
685 protected void initializeExplorerWithEvaluator(GraphExplorer explorer, ISessionContext context, EvaluatorData data) {
688 protected EvaluatorData createEvaluatorData(Session context) {
690 // Set<String> browseContexts = getArgument("browseContexts");
692 return Evaluators.load(context.getSession(), browseContexts, resourceManager, useNodeBrowseContexts, useNodeActionContexts);
696 protected Transfer[] getAcceptedDataTypes() {
697 return new Transfer[] { LocalObjectTransfer.getTransfer(), FileTransfer.getInstance() };
700 protected void handleDrop(Object data, NodeContext target) {
703 DragSourceListenerFactory dragSourceListenerFactory = new DragSourceListenerFactory() {
705 final Transfer[] transfers = new Transfer[] {LocalObjectTransfer.getTransfer(), TextTransfer.getInstance() };
708 public DragSourceListener get(ISelectionProvider selectionProvider) {
710 LocalSelectionDragSourceListener ls = new LocalSelectionDragSourceListener(selectionProvider);
712 return new DragSourceListener() {
715 public void dragStart(DragSourceEvent event) {
720 public void dragSetData(DragSourceEvent event) {
721 if(TextTransfer.getInstance().isSupportedType(event.dataType)) {
723 event.data = WorkbenchSelectionUtils.getPossibleJSON(selectionProvider.getSelection());
724 } catch (DatabaseException e) {
725 event.data = "{ type:\"Exception\" }";
726 Logger.defaultLogError(e);
728 } else if (LocalObjectTransfer.getTransfer().isSupportedType(event.dataType)) {
729 ls.dragSetData(event);
734 public void dragFinished(DragSourceEvent event) {
735 ls.dragFinished(event);
741 public Transfer[] getTransfers() {
747 public void setDragSourceListenerFactory(DragSourceListenerFactory dragSourceListenerFactory) {
748 this.dragSourceListenerFactory = dragSourceListenerFactory;
751 protected DragSourceListener setupDND(GraphExplorer explorer) {
753 ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class);
755 DragSourceListener listener = createDragSourceListener(selectionProvider);
757 Control control = explorer.getControl();
758 DragSource source = createDragSource(control);
759 source.setTransfer(getTransfers());
760 source.addDragListener(listener);
761 source.setDragSourceEffect(new NoImageDragSourceEffect(control));
767 protected DragSourceListener createDragSourceListener(ISelectionProvider selectionProvider) {
768 return dragSourceListenerFactory.get(selectionProvider);
771 private int dragStyle = DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT;
773 protected void setDragStyle(int style) {
774 this.dragStyle = style;
777 protected int getDragStyle() {
781 protected DragSource createDragSource(Control control) {
782 return new DragSource(control, getDragStyle());
785 protected Transfer[] getTransfers() {
786 return dragSourceListenerFactory.getTransfers();
789 public EvaluatorData getEvaluatorData() {
790 return evaluatorData;
793 public interface InputSource {
795 * @param ctx the session context to read the input from. May be
796 * <code>null</code> if there is no session.
797 * @return the input object of a graph explorer. To indicate no input,
798 * use {@link GraphExplorerConstants#EMPTY_INPUT}. Never return
801 Object get(ISessionContext ctx, Object selection);
804 public interface FilterSource {
811 * The default hint tracker that will be active if
812 * {@link GraphExplorerComposite#setSessionContextTracker(IHintTracker) is
815 public class SessionContextProjectTracker extends HintTracker {
816 public SessionContextProjectTracker() {
817 IHintListener activeProjectListener = new HintListenerAdapter() {
819 public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
820 applySessionContext(getSessionContext());
823 addKeyHintListener(ProjectKeys.KEY_PROJECT, activeProjectListener);
827 public class DirectInputSource implements InputSource {
829 public Object get(ISessionContext ctx, Object selection) {
834 public static class SelectionFilterAreaSource implements FilterAreaSource {
837 public IFilterArea getFilterArea(Composite parent, GraphExplorer explorer) {
838 FilterSelectionRequestQueryProcessor processor = (FilterSelectionRequestQueryProcessor)explorer.getPrimitiveProcessor(BuiltinKeys.SELECTION_REQUESTS);
839 return new FilterArea(explorer, processor, parent, SWT.READ_ONLY);
844 public static class RootFilterAreaSource implements FilterAreaSource {
847 public IFilterArea getFilterArea(Composite parent, GraphExplorer explorer) {
848 FilterSelectionRequestQueryProcessor processor = (FilterSelectionRequestQueryProcessor)explorer.getPrimitiveProcessor(BuiltinKeys.SELECTION_REQUESTS);
849 return new RootFilterArea(explorer, processor, parent, SWT.READ_ONLY);
854 protected void setSessionContextTracker(IHintTracker tracker) {
855 this.sessionContextTracker = tracker;
858 public void setInputSource(InputSource source) {
859 this.inputSource = source;
862 public void setFilterAreaSource(FilterAreaSource provider) {
863 this.filterAreaSource = provider;
866 public void setSelectionTransformation(BinaryFunction<Object[], GraphExplorer, Object[]> transformation) {
867 this.selectionTransformation = transformation;
868 if(explorer != null) explorer.setSelectionTransformation(transformation);
871 protected Set<String> getBrowseContexts() {
872 return browseContexts;
875 public void setBrowseContexts(Set<String> contexts) {
876 this.browseContexts = contexts;
877 //initializeExplorer(explorer, getSessionContext());
880 public void setBrowseContexts(String ... contexts) {
881 this.browseContexts = new HashSet<String>();
882 for(String s : contexts) this.browseContexts.add(s);
883 initializeExplorer(explorer, getSessionContext());
886 public void setContextMenuId(String contextMenuId) {
887 this.contextMenuId = contextMenuId;
890 // protected IContextMenuInitializer getContextMenuInitializer() {
891 // String contextMenuId = getContextMenuId();
892 // if(contextMenuId != null) {
893 // return new ContextMenuInitializer(contextMenuId);
899 protected String getContextMenuId() {
900 return this.contextMenuId;
903 public void setUiContexts(Set<String> uiContext) {
904 this.uiContext = uiContext;
907 public Set<String> getUiContexts() {
911 protected InputSource getInputSource() {
915 protected Map<String, Object> getArguments() {
919 @SuppressWarnings("unchecked")
920 protected <T> T getArgument(String key) {
921 return (T) args.get(key);
924 protected DisposeState getDisposeState() {
928 public ISessionContext getSessionContext() {
929 return sessionContext;
932 public ISessionContextProvider getSessionContextProvider() {
933 return contextProvider;
937 public boolean setFocus() {
938 if (explorer != null && !explorer.isDisposed())
943 public void setWorkbenchListeners() {
944 if (workbenchSelectionListener == null && getSite() != null) {
945 ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);
946 getSite().setSelectionProvider(selectionProvider);
948 // Listen to the workbench selection also to propagate it to
949 // the explorer also.
950 workbenchSelectionListener = new DefaultExplorerSelectionListener(site.getPage().getActivePart(), explorer);
951 //System.out.println("ADD WORKBENCH SELECTION LISTENER: " + workbenchSelectionListener);
952 getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(workbenchSelectionListener);
956 protected void removeWorkbenchListeners() {
957 //System.out.println("REMOVE WORKBENCH SELECTION LISTENER: " + workbenchSelectionListener);
958 // Remember to remove the installed workbench selection listener
959 if (workbenchSelectionListener != null) {
960 getSite().getWorkbenchWindow().getSelectionService().removePostSelectionListener(workbenchSelectionListener);
961 workbenchSelectionListener = null;
963 ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);
964 if(getSite().getSelectionProvider() == selectionProvider) getSite().setSelectionProvider(null);
969 protected final void attachToSession() {
971 // Track active ISessionContext changes
972 //contextProvider = SimanticsUI.getSessionContextProvider(getViewSite().getWorkbenchWindow());
973 contextProvider.addContextChangedListener(contextChangeListener);
975 // Start tracking the current session context for input changes.
976 // This will/must cause applySessionContext to get called.
977 // Doing the applySessionContext initialization this way
978 // instead of directly calling it will also make sure that
979 // applySessionContext is only called once when first initialized,
980 // and not twice like with the direct invocation.
981 this.sessionContext = contextProvider.getSessionContext();
982 sessionContextTracker.track(sessionContext);
985 // /////////////////////////////////////////////////////////////////////////
986 // Override / implement these:
989 // * Returns an ID that is used for persisting a GraphExplorer instance.
991 // * Used for </code>restoreState(IMemento)</code> and
992 // * <code>restoreState(IMemento)</code> in OntologyExplorer. Must be unique
993 // * within a workbench part.
995 // * @return a unique name for this particular graph explorer view used for
996 // * saving and restoring the state of this view part
998 // public String getExplorerName() {
999 // return "GraphExplorerViewBase";
1003 * Override this method to add controls to the view part. This is invoked
1004 * before attaching the view part to a database session.
1008 protected void createControls(Composite parent) {
1013 * Override this method and provide a proper context menu initializer if you
1014 * want to have this base class initialize one for you.
1016 * @return the initializer to be used by {@link #createControls(Composite)}
1018 protected IContextMenuInitializer getContextMenuInitializer() {
1019 String contextMenuId = getContextMenuId();
1020 if(contextMenuId != null) {
1021 return new ContextMenuInitializer(contextMenuId);
1031 protected GraphExplorer createExplorerControl(Composite parent, Integer maxChildren) {
1032 GraphExplorerFactory factory = GraphExplorerFactory.getInstance();
1033 if(maxChildren != null) factory = factory.maxChildrenShown(maxChildren);
1035 GraphExplorer ge = factory
1036 .selectionDataResolver(new DefaultSelectionDataResolver())
1037 .selectionTransformation(selectionTransformation)
1038 .setServiceLocator(site)
1039 .create(parent, style);
1044 protected GraphExplorer createExplorerControl2(Composite parent, Integer maxChildren) {
1045 GraphExplorerFactory factory = GraphExplorerFactory.getInstance();
1046 if(maxChildren != null) factory = factory.maxChildrenShown(maxChildren);
1048 GraphExplorer ge = factory
1049 .selectionDataResolver(new DefaultSelectionDataResolver())
1050 .selectionTransformation(selectionTransformation)
1051 .setServiceLocator(site)
1052 .create2(parent, style);
1057 protected GraphExplorer createExplorerControl3(Composite parent, Integer maxChildren) {
1058 GraphExplorerFactory factory = GraphExplorerFactory.getInstance();
1059 if(maxChildren != null) factory = factory.maxChildrenShown(maxChildren);
1061 GraphExplorer ge = factory
1062 .selectionDataResolver(new DefaultSelectionDataResolver())
1063 .selectionTransformation(selectionTransformation)
1064 .setServiceLocator(site)
1065 .create3(parent, style);
1070 protected void setupDragSource(Session session) {
1071 if (dragSource instanceof SessionContainer) {
1072 ((SessionContainer) dragSource).setSession(session);
1077 * Override to customize the addition of listeners a newly created
1082 protected void addListeners(GraphExplorer explorer, IMenuManager menuManager) {
1083 addSelectionInputListeners(explorer, menuManager);
1086 protected void addSelectionInputListeners(GraphExplorer explorer, IMenuManager menuManager) {
1087 // Consider ENTER presses to simulate mouse left button double clicks
1088 explorer.addListener(new DefaultKeyListener(contextProvider, explorer, new Function<String[]>() {
1090 public String[] execute(Object... obj) {
1091 return getEditingColumn((NodeContext) obj[0]);
1094 // Default double click handling
1095 explorer.addListener(new DefaultMouseListener(explorer));
1098 protected String[] getEditingColumn(NodeContext context) {
1099 return editingColumn;
1102 public void setEditingColumn(String... columnKeysInOrderOfTrial) {
1103 this.editingColumn = columnKeysInOrderOfTrial;
1106 // Needed for preventing unnecessary re-initialization of the explorer with the same input.
1107 private Object currentInput;
1108 private Object currentRoot;
1111 * Invoke this to reinitialize the explorer and reset its input. The input
1112 * will be resolved from the specified ISessionContext based on the
1113 * {@link SessionContextInputSource} that is currently in use. If the input
1114 * is identical to the previous input, nothing will be done.
1118 public final boolean applySessionContext(ISessionContext context) {
1120 // If control is not alive anymore, do nothing.
1121 //System.out.println(this + ": applySessionContext(" + context + "), explorer=" + explorer);
1122 if (disposeState != DisposeState.Alive)
1125 //System.out.println(this + ": initializeExplorer(" + explorer + ", " + context + ")");
1126 initializeExplorer(explorer, context);
1129 // Start tracking the session context.
1131 // If this is not the same session that is currently tracked, it will
1132 // cause IHintListeners of the sessionContextTracker to fire.
1133 // For this we need the above input equality (identity) checking.
1134 // This is here just to make sure that we are tracking the correct
1136 sessionContextTracker.track(sessionContext);
1138 this.sessionContext = context;
1139 Object root = inputSource.get(context, currentInput);
1140 if (ObjectUtils.objectEquals(root, currentRoot))
1145 //System.out.println(this + ": setRoot(" + input + ")");
1146 explorer.setUIContexts(uiContext);
1147 explorer.setRoot(root);
1153 protected boolean isImportantInput(Object previousSelection, Object selection) {
1154 return !ObjectUtils.objectEquals(previousSelection, selection);
1157 public void setInput(Object selection, boolean force) {
1163 if (sessionContext == null)
1166 // Check if this is a duplicate of the previous selection to reduce unnecessary flicker.
1167 if (!force && !isImportantInput(currentInput, selection))
1170 currentInput = selection;
1172 Object root = inputSource.get(sessionContext, selection);
1176 explorer.setUIContexts(uiContext);
1179 explorer.setRoot(GraphExplorer.EMPTY_INPUT);
1181 explorer.setRoot(root);
1186 public void setColumnsVisible(boolean visible) {
1187 explorer.setColumnsVisible(visible);
1190 private int getColumnWidth(Column column, ExplorerState state) {
1191 // Get saved width from the persistor if there is one.
1192 if (state != null && state.columnWidths != null) {
1193 Integer width = state.columnWidths.get(column.getLabel());
1197 return column.getWidth();
1200 public void setColumns(Column[] columns) {
1202 explorer.setColumns(columns, new Consumer<Map<Column, Object>>() {
1205 public void accept(Map<Column, Object> objects) {
1206 ExplorerState state = null;
1207 if (persistor != null) {
1208 state = persistor.deserialize(
1209 Platform.getStateLocation(Activator.getDefault().getBundle()).toFile(),
1210 explorer.getRoot());
1213 for(Map.Entry<Column, Object> entry : objects.entrySet()) {
1214 Column column = entry.getKey();
1215 TreeColumn treeColumn = (TreeColumn)entry.getValue();
1217 if (column.getWidth() < 0) {
1218 throw new IllegalArgumentException("Column minimum width cannot be < 0, got " + column.getWidth());
1221 int width = getColumnWidth(column, state);
1222 if(column.hasGrab()) {
1224 ad.setColumnData(treeColumn, new ColumnWeightData(column.getWeight(), width));
1228 ad.setColumnData(treeColumn, new ColumnWeightData(0, width));
1240 public void setInput(ISessionContext context, Object input) {
1241 setInput(input, false);
1244 public void setMaxChildren(int maxChildren) {
1245 explorer.setMaxChildren(maxChildren);
1248 public <T> void addListener(ExplorerMouseListenerImpl<T> listener) {
1250 support.register(listener);
1251 listener.register(explorer);
1252 explorer.addListener(listener);
1257 // public Point computeSize(int wHint, int hHint) {
1258 // Point p = super.computeSize(wHint, hHint);
1259 // System.err.println("graphExplorerComposite.computeSize " + p);
1264 // public Point computeSize(int wHint, int hHint, boolean changed) {
1265 // Point p = super.computeSize(wHint, hHint, changed);
1266 // System.err.println("graphExplorerComposite.computeSize " + p);