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.BiFunction;
20 import java.util.function.Consumer;
22 import org.eclipse.core.runtime.IAdaptable;
23 import org.eclipse.core.runtime.Platform;
24 import org.eclipse.jface.action.IMenuManager;
25 import org.eclipse.jface.layout.GridDataFactory;
26 import org.eclipse.jface.layout.GridLayoutFactory;
27 import org.eclipse.jface.layout.TreeColumnLayout;
28 import org.eclipse.jface.resource.JFaceResources;
29 import org.eclipse.jface.resource.LocalResourceManager;
30 import org.eclipse.jface.viewers.ColumnWeightData;
31 import org.eclipse.jface.viewers.ISelectionProvider;
32 import org.eclipse.swt.SWT;
33 import org.eclipse.swt.dnd.DND;
34 import org.eclipse.swt.dnd.DragSource;
35 import org.eclipse.swt.dnd.DragSourceEvent;
36 import org.eclipse.swt.dnd.DragSourceListener;
37 import org.eclipse.swt.dnd.DropTarget;
38 import org.eclipse.swt.dnd.DropTargetEvent;
39 import org.eclipse.swt.dnd.DropTargetListener;
40 import org.eclipse.swt.dnd.FileTransfer;
41 import org.eclipse.swt.dnd.TextTransfer;
42 import org.eclipse.swt.dnd.Transfer;
43 import org.eclipse.swt.widgets.Composite;
44 import org.eclipse.swt.widgets.Control;
45 import org.eclipse.swt.widgets.Event;
46 import org.eclipse.swt.widgets.Listener;
47 import org.eclipse.swt.widgets.Tree;
48 import org.eclipse.swt.widgets.TreeColumn;
49 import org.eclipse.swt.widgets.TreeItem;
50 import org.eclipse.ui.ISelectionListener;
51 import org.eclipse.ui.IWorkbenchSite;
52 import org.eclipse.ui.contexts.IContextService;
53 import org.simantics.Simantics;
54 import org.simantics.browsing.ui.BuiltinKeys;
55 import org.simantics.browsing.ui.Column;
56 import org.simantics.browsing.ui.ExplorerState;
57 import org.simantics.browsing.ui.GraphExplorer;
58 import org.simantics.browsing.ui.GraphExplorer.TransientExplorerState;
59 import org.simantics.browsing.ui.NodeContext;
60 import org.simantics.browsing.ui.StatePersistor;
61 import org.simantics.browsing.ui.common.AdaptableHintContext;
62 import org.simantics.browsing.ui.common.ColumnKeys;
63 import org.simantics.browsing.ui.common.EvaluatorData;
64 import org.simantics.browsing.ui.common.EvaluatorDataImpl;
65 import org.simantics.browsing.ui.common.processors.ComparableFactoryResolver;
66 import org.simantics.browsing.ui.common.processors.ComparableSelectorQueryProcessor;
67 import org.simantics.browsing.ui.common.processors.FilterSelectionRequestQueryProcessor;
68 import org.simantics.browsing.ui.common.processors.ImageDecoratorFactoryResolver;
69 import org.simantics.browsing.ui.common.processors.ImagerFactoryResolver;
70 import org.simantics.browsing.ui.common.processors.LabelDecoratorFactoryResolver;
71 import org.simantics.browsing.ui.common.processors.LabelerFactoryResolver;
72 import org.simantics.browsing.ui.common.processors.UserSelectedComparableFactoryQueryProcessor;
73 import org.simantics.browsing.ui.common.processors.UserSelectedViewpointFactoryQueryProcessor;
74 import org.simantics.browsing.ui.common.processors.ViewpointFactoryResolver;
75 import org.simantics.browsing.ui.common.views.FilterAreaSource;
76 import org.simantics.browsing.ui.common.views.IFilterArea;
77 import org.simantics.browsing.ui.common.views.IFilterAreaProvider;
78 import org.simantics.browsing.ui.graph.impl.AsyncReadGraphDataSource;
79 import org.simantics.browsing.ui.graph.impl.Evaluators;
80 import org.simantics.browsing.ui.graph.impl.InheritsQueryProcessor;
81 import org.simantics.browsing.ui.graph.impl.ReadGraphDataSource;
82 import org.simantics.browsing.ui.graph.impl.RelatedObjectsQueryProcessor;
83 import org.simantics.browsing.ui.graph.impl.SessionContextInputSource;
84 import org.simantics.browsing.ui.model.browsecontexts.BrowseContext;
85 import org.simantics.browsing.ui.model.nodetypes.NodeType;
86 import org.simantics.browsing.ui.swt.Activator;
87 import org.simantics.browsing.ui.swt.ComparatorSelector;
88 import org.simantics.browsing.ui.swt.ContextMenuInitializer;
89 import org.simantics.browsing.ui.swt.DefaultExplorerSelectionListener;
90 import org.simantics.browsing.ui.swt.DefaultIsCheckedProcessor2;
91 import org.simantics.browsing.ui.swt.DefaultKeyListener;
92 import org.simantics.browsing.ui.swt.DefaultMouseListener;
93 import org.simantics.browsing.ui.swt.DefaultSelectionDataResolver;
94 import org.simantics.browsing.ui.swt.FilterArea;
95 import org.simantics.browsing.ui.swt.GraphExplorerFactory;
96 import org.simantics.browsing.ui.swt.IContextMenuInitializer;
97 import org.simantics.browsing.ui.swt.RootFilterArea;
98 import org.simantics.browsing.ui.swt.StandardContextTypesQueryProcessor;
99 import org.simantics.browsing.ui.swt.TypesQueryProcessor;
100 import org.simantics.browsing.ui.swt.ViewpointSelector;
101 import org.simantics.browsing.ui.swt.widgets.impl.Widget;
102 import org.simantics.browsing.ui.swt.widgets.impl.WidgetSupport;
103 import org.simantics.db.AsyncReadGraph;
104 import org.simantics.db.ReadGraph;
105 import org.simantics.db.Resource;
106 import org.simantics.db.Session;
107 import org.simantics.db.exception.DatabaseException;
108 import org.simantics.db.layer0.SelectionHints;
109 import org.simantics.db.layer0.request.PossibleVariable;
110 import org.simantics.db.layer0.request.PossibleVariableRepresents;
111 import org.simantics.db.layer0.variable.Variable;
112 import org.simantics.db.management.ISessionContext;
113 import org.simantics.db.management.ISessionContextChangedListener;
114 import org.simantics.db.management.ISessionContextProvider;
115 import org.simantics.db.management.SessionContextChangedEvent;
116 import org.simantics.project.ProjectKeys;
117 import org.simantics.ui.SimanticsUI;
118 import org.simantics.ui.dnd.LocalObjectTransfer;
119 import org.simantics.ui.dnd.LocalSelectionDragSourceListener;
120 import org.simantics.ui.dnd.NoImageDragSourceEffect;
121 import org.simantics.ui.dnd.SessionContainer;
122 import org.simantics.ui.selection.AnyResource;
123 import org.simantics.ui.selection.AnyVariable;
124 import org.simantics.ui.selection.ExplorerColumnContentType;
125 import org.simantics.ui.selection.ExplorerInputContentType;
126 import org.simantics.ui.selection.WorkbenchSelectionContentType;
127 import org.simantics.ui.selection.WorkbenchSelectionElement;
128 import org.simantics.ui.selection.WorkbenchSelectionUtils;
129 import org.simantics.utils.ObjectUtils;
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;
138 import org.slf4j.Logger;
139 import org.slf4j.LoggerFactory;
142 public class GraphExplorerComposite extends Composite implements Widget, IAdaptable {
144 private static final Logger LOGGER = LoggerFactory.getLogger(GraphExplorerComposite.class);
146 protected UserSelectedComparableFactoryQueryProcessor userSelectedComparableFactoryQueryProcessor;
147 protected UserSelectedViewpointFactoryQueryProcessor userSelectedViewpointFactoryQueryProcessor;
148 protected FilterSelectionRequestQueryProcessor filterSelectionRequestQueryProcessor;
149 protected IFilterArea filterArea;
150 protected EvaluatorData evaluatorData;
152 protected LocalResourceManager resourceManager;
154 protected ISelectionListener workbenchSelectionListener;
156 private final int style;
158 final private IWorkbenchSite site;
160 protected GraphExplorer explorer;
162 protected IMenuManager menuManager;
164 private final Map<String, Object> args;
166 protected ISessionContextProvider contextProvider;
168 private ISessionContext sessionContext;
170 private Object dragSource;
172 private IHintTracker sessionContextTracker = new SessionContextProjectTracker();
174 private InputSource inputSource = new DirectInputSource();
175 private FilterAreaSource filterAreaSource = new SelectionFilterAreaSource();
177 private final TreeColumnLayout ad;
178 private String[] editingColumn = ColumnKeys.KEYS_SINGLE;
180 private StatePersistor persistor = null;
182 private final Composite toolComposite;
183 private final Composite toolComposite2;
184 private final Composite explorerComposite;
185 final private WidgetSupport support;
186 private final boolean useNodeBrowseContexts;
187 private final boolean useNodeActionContexts;
189 static class SelectionElement extends AdaptableHintContext {
191 final public WorkbenchSelectionElement wse;
192 final public Object content;
193 final public Resource resource;
194 final public Variable variable;
195 final public Object input;
196 final public TransientExplorerState explorerState;
198 private WorkbenchSelectionElement extractWse(Object content) {
199 if(content instanceof NodeContext) {
200 NodeContext context = (NodeContext)content;
201 Object input = context.getConstant(NodeType.TYPE);
202 if(input instanceof NodeType)
203 return ((NodeType)input).getWorkbenchSelectionElement(context);
208 private Resource extractResource(Object content) {
209 if(content instanceof NodeContext) {
210 NodeContext context = (NodeContext)content;
211 Object input = context.getConstant(BuiltinKeys.INPUT);
212 if(input instanceof Resource) return (Resource)input;
213 if(input instanceof IAdaptable) {
214 Resource var = (Resource)((IAdaptable)input).getAdapter(Resource.class);
215 if(var != null) return var;
221 private Variable extractVariable(Object content) {
222 if(content instanceof NodeContext) {
223 NodeContext context = (NodeContext)content;
224 Object input = context.getConstant(BuiltinKeys.INPUT);
225 if(input instanceof Variable) return (Variable)input;
226 if(input instanceof IAdaptable) {
227 Variable var = (Variable)((IAdaptable)input).getAdapter(Variable.class);
228 if(var != null) return var;
234 private Object extractInput(Object content) {
235 if(content instanceof NodeContext) {
236 NodeContext context = (NodeContext)content;
237 return context.getConstant(BuiltinKeys.INPUT);
242 public SelectionElement(GraphExplorer explorer, Key[] keys, Object content) {
244 this.content = content;
245 this.wse = extractWse(content);
246 this.resource = extractResource(content);
247 this.variable = extractVariable(content);
248 this.input = extractInput(content);
249 this.explorerState = explorer.getTransientState();
252 @SuppressWarnings("unchecked")
254 public <T> T getContent(WorkbenchSelectionContentType<T> contentType) {
256 T result = wse.getContent(contentType);
261 if (contentType instanceof AnyResource) {
262 if (resource != null)
264 if (variable == null)
267 return (T) ((AnyResource) contentType).processor.syncRequest(new PossibleVariableRepresents(variable));
268 } catch (DatabaseException e) {
269 LOGGER.error("Unexpected error occurred while resolving Resource from Variable " + variable, e);
272 else if (contentType instanceof AnyVariable) {
273 if (variable != null)
275 if (resource == null)
278 return (T) ((AnyVariable) contentType).processor.syncRequest(new PossibleVariable(resource));
279 } catch (DatabaseException e) {
280 LOGGER.error("Unexpected error occurred while resolving Variable from Resource " + resource, e);
282 } else if (contentType instanceof ExplorerInputContentType) {
284 } else if (contentType instanceof ExplorerColumnContentType) {
285 return (T) explorerState.getActiveColumn();
290 @SuppressWarnings("rawtypes")
292 public Object getAdapter(Class adapter) {
293 if(WorkbenchSelectionElement.class == adapter) {
296 if(NodeContext.class == adapter) {
297 if(content instanceof NodeContext)
298 return (NodeContext)content;
302 return super.getAdapter(adapter);
306 private BiFunction<GraphExplorer, Object[], Object[]> selectionTransformation = new BiFunction<GraphExplorer, Object[], Object[]>() {
308 private Key[] KEYS = new Key[] { SelectionHints.KEY_MAIN };
311 public Object[] apply(GraphExplorer explorer, Object[] objects) {
312 Object[] result = new Object[objects.length];
313 for (int i = 0; i < objects.length; i++) {
314 SelectionElement context = new SelectionElement(explorer, KEYS, objects[i]);
315 context.setHint(SelectionHints.KEY_MAIN, objects[i]);
323 private Set<String> browseContexts = null;
325 private DisposeState disposeState = DisposeState.Alive;
327 private boolean created = false;
329 protected String contextMenuId = null;
331 protected Set<String> uiContext = null;
333 protected ISessionContextChangedListener contextChangeListener = new ISessionContextChangedListener() {
335 public void sessionContextChanged(SessionContextChangedEvent event) {
336 sessionContext = event.getNewValue();
337 sessionContextTracker.track(sessionContext);
341 public GraphExplorerComposite(Map<String, Object> args, IWorkbenchSite site, Composite parent, WidgetSupport support, int style) {
343 super(parent, SWT.NONE);
346 args = Collections.emptyMap();
351 this.resourceManager = new LocalResourceManager(JFaceResources.getResources(parent.getDisplay()), this);
353 contextProvider = getSessionContextProvider(site);
355 Integer maxChildren = (Integer)args.get("maxChildren");
357 GridLayoutFactory.fillDefaults().equalWidth(false).numColumns(1).margins(0,0).spacing(0,0).applyTo(this);
359 toolComposite = new Composite(this, SWT.NONE);
360 // toolComposite.setBackground(toolComposite.getDisplay().getSystemColor(SWT.COLOR_DARK_YELLOW));
361 // GridDataFactory.fillDefaults().grab(true, false).minSize(1, 1).applyTo(toolComposite);
362 GridDataFactory.fillDefaults().grab(true, false).applyTo(toolComposite);
363 GridLayoutFactory.fillDefaults().applyTo(toolComposite);
365 ad = new TreeColumnLayout();
366 explorerComposite = new Composite(this, SWT.NONE);
367 explorerComposite.setLayout(ad);
368 GridDataFactory.fillDefaults().grab(true, true).minSize(1, 50).applyTo(explorerComposite);
370 if (args.containsKey("treeView") && Boolean.TRUE.equals(args.get("treeView"))) {
371 explorer = createExplorerControl2(explorerComposite, maxChildren);
372 } else if (args.containsKey("natTable") && Boolean.TRUE.equals(args.get("natTable"))) {
373 explorer = createExplorerControl3(explorerComposite, maxChildren);
375 explorer = createExplorerControl(explorerComposite, maxChildren);
378 if (args.containsKey("useNodeBrowseContexts") && Boolean.TRUE.equals(args.get("useNodeBrowseContexts"))) {
379 useNodeBrowseContexts = true;
381 useNodeBrowseContexts = false;
384 if (args.containsKey("useNodeActionContexts") && Boolean.TRUE.equals(args.get("useNodeActionContexts"))) {
385 useNodeActionContexts = true;
387 useNodeActionContexts = false;
390 toolComposite2 = new Composite(this, SWT.NONE);
391 // toolComposite2.setBackground(toolComposite2.getDisplay().getSystemColor(SWT.COLOR_DARK_YELLOW));
392 // GridDataFactory.fillDefaults().grab(true, false).minSize(1, 1).applyTo(toolComposite);
393 GridDataFactory.fillDefaults().grab(true, false).applyTo(toolComposite2);
394 GridLayoutFactory.fillDefaults().applyTo(toolComposite2);
396 this.support = support;
399 support.register(this);
403 public GraphExplorerComposite(Map<String, Object> args, IWorkbenchSite site, Composite parent, int style) {
405 this(args, site, parent, null, style);
409 public ISessionContextProvider getSessionContextProvider(IWorkbenchSite site) {
411 return SimanticsUI.getSessionContextProvider(site.getWorkbenchWindow());
413 return Simantics.getSessionContextProvider();
416 public GraphExplorer getExplorer() {
420 public Composite getExplorerComposite() {
421 return explorerComposite;
424 public <T> T getExplorerControl() {
425 return explorer.getControl();
428 public void addListenerToControl(int eventType, Listener listener) {
429 ((Control)explorer.getControl()).addListener(eventType, listener);
432 public void finish() {
434 createControls(site);
438 IWorkbenchSite getSite() {
442 protected void activateUiContexts() {
443 Collection<String> contexts = getUiContexts();
444 if (contexts == null || contexts.isEmpty())
446 IWorkbenchSite site = getSite();
448 IContextService cs = (IContextService) getSite().getService(IContextService.class);
449 for (String context : contexts)
450 cs.activateContext(context);
454 protected void createControls(IWorkbenchSite site) {
456 // Initialize explorer control.
457 // GridDataFactory.fillDefaults().grab(true, true).applyTo(explorer.getControl());
459 Control control = explorer.getControl();
461 // Initialize context menu if an initializer is provided.
462 IContextMenuInitializer cmi = getContextMenuInitializer();
464 ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class);
465 menuManager = cmi.createContextMenu(control, selectionProvider, site);
468 // Initialize UI contexts
469 activateUiContexts();
472 dragSource = setupDND(explorer);
474 // Listeners are only added once per listener, not every time the
475 // session context changes.
476 addListeners(explorer, menuManager);
478 userSelectedComparableFactoryQueryProcessor = new UserSelectedComparableFactoryQueryProcessor();
479 userSelectedViewpointFactoryQueryProcessor = new UserSelectedViewpointFactoryQueryProcessor();
480 filterSelectionRequestQueryProcessor = new FilterSelectionRequestQueryProcessor();
482 explorer.setPrimitiveProcessor(filterSelectionRequestQueryProcessor);
484 boolean hasExtraControls = false;
485 boolean hasExtraControls2 = false;
487 Boolean displaySelectors = (Boolean)args.get("displaySelectors");
488 if(displaySelectors == null || displaySelectors == true) {
490 @SuppressWarnings("unused")
491 ComparatorSelector comparatorSelector = new ComparatorSelector(explorer, userSelectedComparableFactoryQueryProcessor, toolComposite, SWT.READ_ONLY);
492 // comparatorSelector.moveAbove(control);
494 @SuppressWarnings("unused")
495 ViewpointSelector viewpointSelector = new ViewpointSelector(explorer, userSelectedViewpointFactoryQueryProcessor, toolComposite, SWT.READ_ONLY);
496 // viewpointSelector.moveAbove(control);
498 hasExtraControls = true;
502 Boolean displayFilter = (Boolean)args.get("displayFilter");
503 if(displayFilter == null || displayFilter == true) {
506 filterArea = filterAreaSource.getFilterArea(toolComposite, explorer);
507 // filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, toolComposite, SWT.READ_ONLY);
508 //filterArea.moveAbove(control);
510 hasExtraControls = true;
514 Boolean displayFilter2 = (Boolean)args.get("displayFilter2");
515 if(displayFilter2 != null && displayFilter2 == true) {
517 filterArea = filterAreaSource.getFilterArea(toolComposite2, explorer);
518 // filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, toolComposite2, SWT.READ_ONLY);
519 // //filterArea.moveAbove(control);
521 hasExtraControls2 = true;
525 // filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, this, SWT.READ_ONLY);
526 // filterArea.moveAbove(control);
528 if(!hasExtraControls)
529 GridDataFactory.fillDefaults().grab(true, false).minSize(0, 0).hint(0, 0).applyTo(toolComposite);
530 if(!hasExtraControls2)
531 GridDataFactory.fillDefaults().grab(true, false).minSize(0, 0).hint(0, 0).applyTo(toolComposite2);
533 GridDataFactory.fillDefaults().grab(true, true).span(2,1).applyTo(control);
535 //tree.getTree().setLayout(new FillLayout()
536 //this.setLayout(LayoutUtils.createNoBorderGridLayout(2, false));
538 DropTarget target = new DropTarget(control, DND.DROP_COPY | DND.DROP_MOVE | DND.DROP_LINK | DND.DROP_DEFAULT);
539 target.setTransfer(getAcceptedDataTypes());
540 if (control instanceof Tree) {
541 target.addDropListener(new DropTargetListener() {
543 Tree tree = (Tree)explorer.getControl();
546 public void dragEnter(DropTargetEvent event) {
547 event.detail = DND.DROP_COPY;
551 public void dragLeave(DropTargetEvent event) {
555 public void dragOperationChanged(DropTargetEvent event) {
559 public void dragOver(DropTargetEvent event) {
563 public void drop(DropTargetEvent event) {
564 TreeItem item = tree.getItem(tree.toControl(event.x, event.y));
566 Object data = item.getData();
567 if (data instanceof NodeContext)
568 handleDrop(event.data, (NodeContext) data);
569 else if (data instanceof IAdaptable) {
570 IAdaptable a = (IAdaptable) data;
571 handleDrop(event.data, (NodeContext) a.getAdapter(NodeContext.class));
574 handleDrop(event.data, null);
578 public void dropAccept(DropTargetEvent event) {
584 // Add workbench listeners and make sure they are cleaned up
585 setWorkbenchListeners();
586 control.addListener(SWT.Dispose, new Listener() {
588 public void handleEvent(Event event) {
594 @SuppressWarnings({ "rawtypes", "unchecked" })
596 public Object getAdapter(Class adapter) {
597 if (GraphExplorer.class == adapter)
599 if (EvaluatorData.class == adapter)
600 return evaluatorData;
601 if (BrowseContext.class == adapter) {
602 EvaluatorData ed = evaluatorData;
603 return ed != null ? ed.getBrowseContext() : null;
605 if (adapter == IFilterAreaProvider.class)
607 return explorer.getAdapter(adapter);
610 protected void doDispose() {
611 //System.out.println(this + ".GraphExplorerComposite.doDispose()");
612 removeWorkbenchListeners();
613 userSelectedComparableFactoryQueryProcessor = null;
614 userSelectedViewpointFactoryQueryProcessor = null;
615 filterSelectionRequestQueryProcessor = null;
617 disposeState = DisposeState.Disposing;
619 //System.out.println(this + ".GraphExplorerViewBase.dispose()");
620 if (contextProvider != null) {
621 contextProvider.removeContextChangedListener(contextChangeListener);
622 contextProvider = null;
624 sessionContextTracker.untrack();
625 resourceManager = null;
627 sessionContext = null;
631 disposeState = DisposeState.Disposed;
636 public void dispose() {
641 protected StatePersistor getStatePersistor() {
645 public void setStatePersistor(StatePersistor persistor) {
646 this.persistor = persistor;
649 protected void initializeExplorer(GraphExplorer explorer, ISessionContext context) {
651 if(explorer == null || explorer.isDisposed()) return;
652 if(context == null) return;
653 if(browseContexts == null) return;
655 Session session = context != null ? context.getSession() : null;
656 setupDragSource(session);
658 if (session != null) {
659 evaluatorData = createEvaluatorData(session);
660 explorer.setDataSource(new AsyncReadGraphDataSource(session));
661 explorer.setDataSource(new ReadGraphDataSource(session));
664 evaluatorData = new EvaluatorDataImpl();
665 explorer.removeDataSource(AsyncReadGraph.class);
666 explorer.removeDataSource(ReadGraph.class);
669 explorer.setPersistor(getStatePersistor());
671 explorer.setProcessor(new ComparableFactoryResolver(evaluatorData));
672 explorer.setProcessor(new ViewpointFactoryResolver(evaluatorData));
673 explorer.setProcessor(new LabelerFactoryResolver(evaluatorData));
674 explorer.setProcessor(new ImagerFactoryResolver(evaluatorData));
675 explorer.setProcessor(new LabelDecoratorFactoryResolver(evaluatorData));
676 explorer.setProcessor(new ImageDecoratorFactoryResolver(evaluatorData));
677 explorer.setProcessor(new DefaultIsCheckedProcessor2(evaluatorData));
678 explorer.setPrimitiveProcessor(new TypesQueryProcessor());
679 explorer.setPrimitiveProcessor(new StandardContextTypesQueryProcessor());
680 explorer.setPrimitiveProcessor(new InheritsQueryProcessor());
681 explorer.setPrimitiveProcessor(new RelatedObjectsQueryProcessor());
683 explorer.setPrimitiveProcessor(userSelectedViewpointFactoryQueryProcessor);
684 explorer.setProcessor(new ComparableSelectorQueryProcessor());
685 explorer.setPrimitiveProcessor(userSelectedComparableFactoryQueryProcessor);
686 explorer.setPrimitiveProcessor(filterSelectionRequestQueryProcessor);
688 initializeExplorerWithEvaluator(explorer, context, evaluatorData);
691 protected void initializeExplorerWithEvaluator(GraphExplorer explorer, ISessionContext context, EvaluatorData data) {
694 protected EvaluatorData createEvaluatorData(Session context) {
696 // Set<String> browseContexts = getArgument("browseContexts");
698 return Evaluators.load(context.getSession(), browseContexts, resourceManager, useNodeBrowseContexts, useNodeActionContexts);
702 protected Transfer[] getAcceptedDataTypes() {
703 return new Transfer[] { LocalObjectTransfer.getTransfer(), FileTransfer.getInstance(), TextTransfer.getInstance() };
706 protected void handleDrop(Object data, NodeContext target) {
709 DragSourceListenerFactory dragSourceListenerFactory = new DragSourceListenerFactory() {
711 final Transfer[] transfers = new Transfer[] {LocalObjectTransfer.getTransfer(), TextTransfer.getInstance() };
714 public DragSourceListener get(ISelectionProvider selectionProvider) {
716 LocalSelectionDragSourceListener ls = new LocalSelectionDragSourceListener(selectionProvider);
718 return new DragSourceListener() {
721 public void dragStart(DragSourceEvent event) {
726 public void dragSetData(DragSourceEvent event) {
727 if(TextTransfer.getInstance().isSupportedType(event.dataType)) {
729 event.data = WorkbenchSelectionUtils.getPossibleJSON(selectionProvider.getSelection());
730 } catch (DatabaseException e) {
731 event.data = "{ type:\"Exception\" }";
732 LOGGER.error("Failed to get current selection as JSON.", e);
734 } else if (LocalObjectTransfer.getTransfer().isSupportedType(event.dataType)) {
735 ls.dragSetData(event);
740 public void dragFinished(DragSourceEvent event) {
741 ls.dragFinished(event);
747 public Transfer[] getTransfers() {
753 public void setDragSourceListenerFactory(DragSourceListenerFactory dragSourceListenerFactory) {
754 this.dragSourceListenerFactory = dragSourceListenerFactory;
757 protected DragSourceListener setupDND(GraphExplorer explorer) {
759 ISelectionProvider selectionProvider = (ISelectionProvider)explorer.getAdapter(ISelectionProvider.class);
761 DragSourceListener listener = createDragSourceListener(selectionProvider);
763 Control control = explorer.getControl();
764 DragSource source = createDragSource(control);
765 source.setTransfer(getTransfers());
766 source.addDragListener(listener);
767 source.setDragSourceEffect(new NoImageDragSourceEffect(control));
773 protected DragSourceListener createDragSourceListener(ISelectionProvider selectionProvider) {
774 return dragSourceListenerFactory.get(selectionProvider);
777 private int dragStyle = DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT;
779 protected void setDragStyle(int style) {
780 this.dragStyle = style;
783 protected int getDragStyle() {
787 protected DragSource createDragSource(Control control) {
788 return new DragSource(control, getDragStyle());
791 protected Transfer[] getTransfers() {
792 return dragSourceListenerFactory.getTransfers();
795 public EvaluatorData getEvaluatorData() {
796 return evaluatorData;
799 public interface InputSource {
801 * @param ctx the session context to read the input from. May be
802 * <code>null</code> if there is no session.
803 * @return the input object of a graph explorer. To indicate no input,
804 * use {@link GraphExplorerConstants#EMPTY_INPUT}. Never return
807 Object get(ISessionContext ctx, Object selection);
810 public interface FilterSource {
817 * The default hint tracker that will be active if
818 * {@link GraphExplorerComposite#setSessionContextTracker(IHintTracker) is
821 public class SessionContextProjectTracker extends HintTracker {
822 public SessionContextProjectTracker() {
823 IHintListener activeProjectListener = new HintListenerAdapter() {
825 public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
826 applySessionContext(getSessionContext());
829 addKeyHintListener(ProjectKeys.KEY_PROJECT, activeProjectListener);
833 public class DirectInputSource implements InputSource {
835 public Object get(ISessionContext ctx, Object selection) {
840 public static class SelectionFilterAreaSource implements FilterAreaSource {
843 public IFilterArea getFilterArea(Composite parent, GraphExplorer explorer) {
844 FilterSelectionRequestQueryProcessor processor = (FilterSelectionRequestQueryProcessor)explorer.getPrimitiveProcessor(BuiltinKeys.SELECTION_REQUESTS);
845 return new FilterArea(explorer, processor, parent, SWT.READ_ONLY);
850 public static class RootFilterAreaSource implements FilterAreaSource {
853 public IFilterArea getFilterArea(Composite parent, GraphExplorer explorer) {
854 FilterSelectionRequestQueryProcessor processor = (FilterSelectionRequestQueryProcessor)explorer.getPrimitiveProcessor(BuiltinKeys.SELECTION_REQUESTS);
855 return new RootFilterArea(explorer, processor, parent, SWT.READ_ONLY);
860 protected void setSessionContextTracker(IHintTracker tracker) {
861 this.sessionContextTracker = tracker;
864 public void setInputSource(InputSource source) {
865 this.inputSource = source;
868 public void setFilterAreaSource(FilterAreaSource provider) {
869 this.filterAreaSource = provider;
872 public void setSelectionTransformation(BiFunction<GraphExplorer, Object[], Object[]> transformation) {
873 this.selectionTransformation = transformation;
874 if(explorer != null) explorer.setSelectionTransformation(transformation);
877 protected Set<String> getBrowseContexts() {
878 return browseContexts;
881 public void setBrowseContexts(Set<String> contexts) {
882 this.browseContexts = contexts;
883 //initializeExplorer(explorer, getSessionContext());
886 public void setBrowseContexts(String ... contexts) {
887 this.browseContexts = new HashSet<String>();
888 for(String s : contexts) this.browseContexts.add(s);
889 initializeExplorer(explorer, getSessionContext());
892 public void setContextMenuId(String contextMenuId) {
893 this.contextMenuId = contextMenuId;
896 // protected IContextMenuInitializer getContextMenuInitializer() {
897 // String contextMenuId = getContextMenuId();
898 // if(contextMenuId != null) {
899 // return new ContextMenuInitializer(contextMenuId);
905 protected String getContextMenuId() {
906 return this.contextMenuId;
909 public void setUiContexts(Set<String> uiContext) {
910 this.uiContext = uiContext;
913 public Set<String> getUiContexts() {
917 protected InputSource getInputSource() {
921 protected Map<String, Object> getArguments() {
925 @SuppressWarnings("unchecked")
926 protected <T> T getArgument(String key) {
927 return (T) args.get(key);
930 protected DisposeState getDisposeState() {
934 public ISessionContext getSessionContext() {
935 return sessionContext;
938 public ISessionContextProvider getSessionContextProvider() {
939 return contextProvider;
943 public boolean setFocus() {
944 if (explorer != null && !explorer.isDisposed())
949 public void setWorkbenchListeners() {
950 if (workbenchSelectionListener == null && getSite() != null) {
951 ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);
952 getSite().setSelectionProvider(selectionProvider);
954 // Listen to the workbench selection also to propagate it to
955 // the explorer also.
956 workbenchSelectionListener = new DefaultExplorerSelectionListener(site.getPage().getActivePart(), explorer);
957 //System.out.println("ADD WORKBENCH SELECTION LISTENER: " + workbenchSelectionListener);
958 getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(workbenchSelectionListener);
962 protected void removeWorkbenchListeners() {
963 //System.out.println("REMOVE WORKBENCH SELECTION LISTENER: " + workbenchSelectionListener);
964 // Remember to remove the installed workbench selection listener
965 if (workbenchSelectionListener != null) {
966 getSite().getWorkbenchWindow().getSelectionService().removePostSelectionListener(workbenchSelectionListener);
967 workbenchSelectionListener = null;
969 ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);
970 if(getSite().getSelectionProvider() == selectionProvider) getSite().setSelectionProvider(null);
975 protected final void attachToSession() {
977 // Track active ISessionContext changes
978 //contextProvider = SimanticsUI.getSessionContextProvider(getViewSite().getWorkbenchWindow());
979 contextProvider.addContextChangedListener(contextChangeListener);
981 // Start tracking the current session context for input changes.
982 // This will/must cause applySessionContext to get called.
983 // Doing the applySessionContext initialization this way
984 // instead of directly calling it will also make sure that
985 // applySessionContext is only called once when first initialized,
986 // and not twice like with the direct invocation.
987 this.sessionContext = contextProvider.getSessionContext();
988 sessionContextTracker.track(sessionContext);
991 // /////////////////////////////////////////////////////////////////////////
992 // Override / implement these:
995 // * Returns an ID that is used for persisting a GraphExplorer instance.
997 // * Used for </code>restoreState(IMemento)</code> and
998 // * <code>restoreState(IMemento)</code> in OntologyExplorer. Must be unique
999 // * within a workbench part.
1001 // * @return a unique name for this particular graph explorer view used for
1002 // * saving and restoring the state of this view part
1004 // public String getExplorerName() {
1005 // return "GraphExplorerViewBase";
1009 * Override this method to add controls to the view part. This is invoked
1010 * before attaching the view part to a database session.
1014 protected void createControls(Composite parent) {
1019 * Override this method and provide a proper context menu initializer if you
1020 * want to have this base class initialize one for you.
1022 * @return the initializer to be used by {@link #createControls(Composite)}
1024 protected IContextMenuInitializer getContextMenuInitializer() {
1025 String contextMenuId = getContextMenuId();
1026 if(contextMenuId != null) {
1027 return new ContextMenuInitializer(contextMenuId);
1037 protected GraphExplorer createExplorerControl(Composite parent, Integer maxChildren) {
1038 GraphExplorerFactory factory = GraphExplorerFactory.getInstance();
1039 if(maxChildren != null) factory = factory.maxChildrenShown(maxChildren);
1041 GraphExplorer ge = factory
1042 .selectionDataResolver(new DefaultSelectionDataResolver())
1043 .selectionTransformation(selectionTransformation)
1044 .setServiceLocator(site)
1045 .create(parent, style);
1050 protected GraphExplorer createExplorerControl2(Composite parent, Integer maxChildren) {
1051 GraphExplorerFactory factory = GraphExplorerFactory.getInstance();
1052 if(maxChildren != null) factory = factory.maxChildrenShown(maxChildren);
1054 GraphExplorer ge = factory
1055 .selectionDataResolver(new DefaultSelectionDataResolver())
1056 .selectionTransformation(selectionTransformation)
1057 .setServiceLocator(site)
1058 .create2(parent, style);
1063 protected GraphExplorer createExplorerControl3(Composite parent, Integer maxChildren) {
1064 GraphExplorerFactory factory = GraphExplorerFactory.getInstance();
1065 if(maxChildren != null) factory = factory.maxChildrenShown(maxChildren);
1067 GraphExplorer ge = factory
1068 .selectionDataResolver(new DefaultSelectionDataResolver())
1069 .selectionTransformation(selectionTransformation)
1070 .setServiceLocator(site)
1071 .create3(parent, style);
1076 protected void setupDragSource(Session session) {
1077 if (dragSource instanceof SessionContainer) {
1078 ((SessionContainer) dragSource).setSession(session);
1083 * Override to customize the addition of listeners a newly created
1088 protected void addListeners(GraphExplorer explorer, IMenuManager menuManager) {
1089 addSelectionInputListeners(explorer, menuManager);
1092 protected void addSelectionInputListeners(GraphExplorer explorer, IMenuManager menuManager) {
1093 // Consider ENTER presses to simulate mouse left button double clicks
1094 explorer.addListener(new DefaultKeyListener(contextProvider, explorer, new Function<String[]>() {
1096 public String[] execute(Object... obj) {
1097 return getEditingColumn((NodeContext) obj[0]);
1100 // Default double click handling
1101 explorer.addListener(new DefaultMouseListener(explorer));
1104 protected String[] getEditingColumn(NodeContext context) {
1105 return editingColumn;
1108 public void setEditingColumn(String... columnKeysInOrderOfTrial) {
1109 this.editingColumn = columnKeysInOrderOfTrial;
1112 // Needed for preventing unnecessary re-initialization of the explorer with the same input.
1113 private Object currentInput;
1114 private Object currentRoot;
1117 * Invoke this to reinitialize the explorer and reset its input. The input
1118 * will be resolved from the specified ISessionContext based on the
1119 * {@link SessionContextInputSource} that is currently in use. If the input
1120 * is identical to the previous input, nothing will be done.
1124 public final boolean applySessionContext(ISessionContext context) {
1126 // If control is not alive anymore, do nothing.
1127 //System.out.println(this + ": applySessionContext(" + context + "), explorer=" + explorer);
1128 if (disposeState != DisposeState.Alive)
1131 //System.out.println(this + ": initializeExplorer(" + explorer + ", " + context + ")");
1132 initializeExplorer(explorer, context);
1135 // Start tracking the session context.
1137 // If this is not the same session that is currently tracked, it will
1138 // cause IHintListeners of the sessionContextTracker to fire.
1139 // For this we need the above input equality (identity) checking.
1140 // This is here just to make sure that we are tracking the correct
1142 sessionContextTracker.track(sessionContext);
1144 this.sessionContext = context;
1145 Object root = inputSource.get(context, currentInput);
1146 if (ObjectUtils.objectEquals(root, currentRoot))
1151 //System.out.println(this + ": setRoot(" + input + ")");
1152 explorer.setUIContexts(uiContext);
1153 explorer.setRoot(root);
1159 protected boolean isImportantInput(Object previousSelection, Object selection) {
1160 return !ObjectUtils.objectEquals(previousSelection, selection);
1163 public void setInput(Object selection, boolean force) {
1169 if (sessionContext == null)
1172 // Check if this is a duplicate of the previous selection to reduce unnecessary flicker.
1173 if (!force && !isImportantInput(currentInput, selection))
1176 currentInput = selection;
1178 Object root = inputSource.get(sessionContext, selection);
1182 explorer.setUIContexts(uiContext);
1185 explorer.setRoot(GraphExplorer.EMPTY_INPUT);
1187 explorer.setRoot(root);
1192 public void setColumnsVisible(boolean visible) {
1193 explorer.setColumnsVisible(visible);
1196 private int getColumnWidth(Column column, ExplorerState state) {
1197 // Get saved width from the persistor if there is one.
1198 if (state != null && state.columnWidths != null) {
1199 Integer width = state.columnWidths.get(column.getLabel());
1203 return column.getWidth();
1206 public void setColumns(Column[] columns) {
1208 explorer.setColumns(columns, new Consumer<Map<Column, Object>>() {
1211 public void accept(Map<Column, Object> objects) {
1212 ExplorerState state = null;
1213 if (persistor != null) {
1214 state = persistor.deserialize(
1215 Platform.getStateLocation(Activator.getDefault().getBundle()).toFile(),
1216 explorer.getRoot());
1219 for(Map.Entry<Column, Object> entry : objects.entrySet()) {
1220 Column column = entry.getKey();
1221 TreeColumn treeColumn = (TreeColumn)entry.getValue();
1223 if (column.getWidth() < 0) {
1224 throw new IllegalArgumentException("Column minimum width cannot be < 0, got " + column.getWidth());
1227 int width = getColumnWidth(column, state);
1228 if(column.hasGrab()) {
1230 ad.setColumnData(treeColumn, new ColumnWeightData(column.getWeight(), width));
1234 ad.setColumnData(treeColumn, new ColumnWeightData(0, width));
1246 public void setInput(ISessionContext context, Object input) {
1247 setInput(input, false);
1250 public void setMaxChildren(int maxChildren) {
1251 explorer.setMaxChildren(maxChildren);
1254 public <T> void addListener(ExplorerMouseListenerImpl<T> listener) {
1256 support.register(listener);
1257 listener.register(explorer);
1258 explorer.addListener(listener);
1263 // public Point computeSize(int wHint, int hHint) {
1264 // Point p = super.computeSize(wHint, hHint);
1265 // System.err.println("graphExplorerComposite.computeSize " + p);
1270 // public Point computeSize(int wHint, int hHint, boolean changed) {
1271 // Point p = super.computeSize(wHint, hHint, changed);
1272 // System.err.println("graphExplorerComposite.computeSize " + p);