1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.browsing.ui.platform;
\r
14 import java.lang.reflect.Constructor;
\r
15 import java.util.Collection;
\r
16 import java.util.Collections;
\r
17 import java.util.HashSet;
\r
18 import java.util.Set;
\r
20 import org.eclipse.core.runtime.IConfigurationElement;
\r
21 import org.eclipse.core.runtime.Platform;
\r
22 import org.eclipse.jface.layout.GridDataFactory;
\r
23 import org.eclipse.jface.viewers.ISelectionProvider;
\r
24 import org.eclipse.swt.SWT;
\r
25 import org.eclipse.swt.dnd.DND;
\r
26 import org.eclipse.swt.dnd.DragSource;
\r
27 import org.eclipse.swt.dnd.DragSourceListener;
\r
28 import org.eclipse.swt.dnd.DropTarget;
\r
29 import org.eclipse.swt.dnd.DropTargetAdapter;
\r
30 import org.eclipse.swt.dnd.DropTargetEvent;
\r
31 import org.eclipse.swt.dnd.FileTransfer;
\r
32 import org.eclipse.swt.dnd.Transfer;
\r
33 import org.eclipse.swt.widgets.Composite;
\r
34 import org.eclipse.swt.widgets.Control;
\r
35 import org.eclipse.swt.widgets.Tree;
\r
36 import org.eclipse.swt.widgets.TreeItem;
\r
37 import org.eclipse.ui.IWorkbenchPartSite;
\r
38 import org.eclipse.ui.PlatformUI;
\r
39 import org.eclipse.ui.contexts.IContextService;
\r
40 import org.osgi.framework.Bundle;
\r
41 import org.simantics.browsing.ui.BuiltinKeys;
\r
42 import org.simantics.browsing.ui.GraphExplorer;
\r
43 import org.simantics.browsing.ui.NodeContext;
\r
44 import org.simantics.browsing.ui.common.EvaluatorData;
\r
45 import org.simantics.browsing.ui.common.EvaluatorDataImpl;
\r
46 import org.simantics.browsing.ui.common.node.IDropTargetNode;
\r
47 import org.simantics.browsing.ui.common.processors.ComparableFactoryResolver;
\r
48 import org.simantics.browsing.ui.common.processors.ComparableSelectorQueryProcessor;
\r
49 import org.simantics.browsing.ui.common.processors.FilterSelectionRequestQueryProcessor;
\r
50 import org.simantics.browsing.ui.common.processors.ImageDecoratorFactoryResolver;
\r
51 import org.simantics.browsing.ui.common.processors.ImagerFactoryResolver;
\r
52 import org.simantics.browsing.ui.common.processors.LabelDecoratorFactoryResolver;
\r
53 import org.simantics.browsing.ui.common.processors.LabelerFactoryResolver;
\r
54 import org.simantics.browsing.ui.common.processors.UserSelectedComparableFactoryQueryProcessor;
\r
55 import org.simantics.browsing.ui.common.processors.UserSelectedViewpointFactoryQueryProcessor;
\r
56 import org.simantics.browsing.ui.common.processors.ViewpointFactoryResolver;
\r
57 import org.simantics.browsing.ui.common.views.IFilterAreaProvider;
\r
58 import org.simantics.browsing.ui.graph.impl.AsyncReadGraphDataSource;
\r
59 import org.simantics.browsing.ui.graph.impl.Evaluators;
\r
60 import org.simantics.browsing.ui.graph.impl.GraphExplorerHints;
\r
61 import org.simantics.browsing.ui.graph.impl.InheritsQueryProcessor;
\r
62 import org.simantics.browsing.ui.graph.impl.ReadGraphDataSource;
\r
63 import org.simantics.browsing.ui.graph.impl.RelatedObjectsQueryProcessor;
\r
64 import org.simantics.browsing.ui.swt.ComparatorSelector;
\r
65 import org.simantics.browsing.ui.swt.FilterArea;
\r
66 import org.simantics.browsing.ui.swt.GraphExplorerViewBase;
\r
67 import org.simantics.browsing.ui.swt.StandardContextTypesQueryProcessor;
\r
68 import org.simantics.browsing.ui.swt.TypesQueryProcessor;
\r
69 import org.simantics.browsing.ui.swt.ViewpointSelector;
\r
70 import org.simantics.db.AsyncReadGraph;
\r
71 import org.simantics.db.ReadGraph;
\r
72 import org.simantics.db.Session;
\r
73 import org.simantics.db.management.ISessionContext;
\r
74 import org.simantics.selectionview.StandardPropertyPage;
\r
75 import org.simantics.ui.dnd.LocalObjectTransfer;
\r
76 import org.simantics.ui.dnd.LocalSelectionDragSourceListener;
\r
77 import org.simantics.ui.dnd.NoImageDragSourceEffect;
\r
78 import org.simantics.ui.workbench.IPropertyPage;
\r
79 import org.simantics.utils.datastructures.hints.HintContext;
\r
80 import org.simantics.utils.datastructures.hints.IHintContext;
\r
81 import org.simantics.utils.ui.ErrorLogger;
\r
82 import org.simantics.utils.ui.LayoutUtils;
\r
87 * <li>{@link #createAuxiliaryControls(Composite, Control)} to customize the
\r
88 * creation of auxiliary controls around the graph explorer control, such as
\r
89 * comparator/viewpoint selectors and filter area.</li>
\r
90 * <li>{@link #getUiContexts()} to specify which
\r
91 * <code>org.eclipse.ui.context</code> extension point contexts should be
\r
92 * activated for this view site. May be empty.</li>
\r
93 * <li>{@link #getBrowseContexts()} to specify how the view
\r
94 * content/label/decoration production should be configured. May be empty, in
\r
95 * which case the browser will show nothing.</li>
\r
96 * <li>{@link #getContextMenuId()} to specify the ID of the context menu to be
\r
97 * create for this view part and registered with the workbench. May be
\r
98 * <code>null</code>, in which case a context menu will not be created nor
\r
99 * registered with the workbench.</li>
\r
102 * @author Tuukka Lehtonen
\r
103 * @deprecated in favor of org.simantics.views.swt.ModelledView
\r
106 public class GraphExplorerView extends GraphExplorerViewBase {
\r
108 protected UserSelectedComparableFactoryQueryProcessor userSelectedComparableFactoryQueryProcessor;
\r
109 protected UserSelectedViewpointFactoryQueryProcessor userSelectedViewpointFactoryQueryProcessor;
\r
110 protected FilterSelectionRequestQueryProcessor filterSelectionRequestQueryProcessor;
\r
111 protected FilterArea filterArea;
\r
112 protected IHintContext factoryHints = new HintContext();
\r
113 protected EvaluatorData evaluatorData;
\r
115 protected Set<String> browseContexts = Collections.emptySet();
\r
116 protected String contextMenuId;
\r
117 protected Set<String> uiContexts = Collections.emptySet();
\r
118 protected String propertyPageContributor;
\r
119 protected String propertyPageClassName;
\r
120 protected Set<String> propertyBrowseContexts = Collections.emptySet();
\r
122 protected boolean hideComparatorSelector = false;
\r
123 protected boolean hideViewpointSelector = false;
\r
124 protected boolean hideFilter = false;
\r
127 public void setInitializationData(IConfigurationElement cfig, String propertyName, Object data) {
\r
128 super.setInitializationData(cfig, propertyName, data);
\r
129 if (data instanceof String) {
\r
130 Set<String> browseContexts = new HashSet<String>();
\r
131 Set<String> uiContexts = new HashSet<String>();
\r
132 Set<String> propertyBrowseContexts = new HashSet<String>();
\r
134 String[] parameters = ((String) data).split(";");
\r
136 IContextService service = (IContextService) PlatformUI.getWorkbench().getService(IContextService.class);
\r
137 Set<String> definedContexts = new HashSet<String>();
\r
138 for (Object cid : service.getDefinedContextIds())
\r
139 definedContexts.add((String) cid);
\r
141 for (String parameter : parameters) {
\r
142 String[] keyValue = parameter.split("=");
\r
143 if (keyValue.length > 2) {
\r
144 ErrorLogger.defaultLogWarning("Invalid parameter '" + parameter + ". Complete view argument: " + data, null);
\r
147 String key = keyValue[0];
\r
148 String value = keyValue.length > 1 ? keyValue[1] : "";
\r
150 if ("browseContext".equals(key)) {
\r
151 browseContexts.add(value);
\r
152 } else if ("contextMenuId".equals(key)) {
\r
153 this.contextMenuId = value;
\r
154 } else if ("uiContext".equals(key)) {
\r
155 if (!definedContexts.contains(value)) {
\r
156 ErrorLogger.defaultLogWarning("Parameter '" + parameter + "' references a non-existent Eclipse UI context '" + value + "'. Complete view argument: " + data, null);
\r
159 uiContexts.add(value);
\r
160 } else if ("propertyBrowseContext".equals(key)) {
\r
161 propertyBrowseContexts.add(value);
\r
162 } else if ("propertyPageClass".equals(key)) {
\r
163 this.propertyPageContributor = cfig.getContributor().getName();
\r
164 this.propertyPageClassName = value;
\r
165 } else if ("hideComparatorSelector".equals(key)) {
\r
166 this.hideComparatorSelector = true;
\r
167 } else if ("hideViewpointSelector".equals(key)) {
\r
168 this.hideViewpointSelector = true;
\r
169 } else if ("hideFilter".equals(key)) {
\r
170 this.hideFilter = true;
\r
174 this.browseContexts = browseContexts;
\r
175 this.uiContexts = uiContexts;
\r
176 this.propertyBrowseContexts = propertyBrowseContexts;
\r
180 public GraphExplorer getExplorer() {
\r
184 public <T> T getBrowseContext() {
\r
185 return evaluatorData.getBrowseContext();
\r
190 * Override this to specify which browse contexts are considered active for
\r
191 * this browser. This information is read only once during view
\r
192 * initialization, no change listening is implemented.
\r
196 protected Set<String> getBrowseContexts() {
\r
197 return browseContexts;
\r
201 * @see org.simantics.browsing.ui.swt.GraphExplorerViewBase#getContextMenuId()
\r
204 protected String getContextMenuId() {
\r
205 return contextMenuId;
\r
209 * @return the set of <code>org.eclipse.ui.context</code> contexts to
\r
210 * activate for this view site
\r
212 protected Set<String> getUiContexts() {
\r
217 protected IPropertyPage getPropertyPage() {
\r
218 if (propertyPageContributor != null && propertyPageClassName != null) {
\r
220 Bundle b = Platform.getBundle(propertyPageContributor);
\r
222 ErrorLogger.defaultLogError("property page '" + propertyPageClassName + "' contributor bundle '"
\r
223 + propertyPageContributor + "' was not found in the platform.", null);
\r
226 Class<?> clazz = b.loadClass(propertyPageClassName);
\r
227 if (!IPropertyPage.class.isAssignableFrom(clazz)) {
\r
228 ErrorLogger.defaultLogError("property page class '" + propertyPageClassName + "' is not assignable to "
\r
229 + IPropertyPage.class + ".", null);
\r
232 Constructor<?> ctor = clazz.getConstructor(IWorkbenchPartSite.class);
\r
233 return (IPropertyPage) ctor.newInstance(getSite());
\r
234 } catch (Exception e) {
\r
235 ErrorLogger.defaultLogError("Failed to instantiate IPropertyPage implementation '" + propertyPageClassName
\r
236 + "' from bundle '" + propertyPageContributor + "'. See exception for details.", e);
\r
237 // Something failed, don't try to instantiate the property page anymore.
\r
238 propertyPageClassName = null;
\r
240 } else if (!propertyBrowseContexts.isEmpty()) {
\r
241 return new StandardPropertyPage(getSite(), new HashSet<String>(propertyBrowseContexts));
\r
247 protected void createControls(Composite parent) {
\r
248 super.createControls(parent);
\r
250 Control control = explorer.getControl();
\r
252 userSelectedComparableFactoryQueryProcessor = new UserSelectedComparableFactoryQueryProcessor();
\r
253 userSelectedViewpointFactoryQueryProcessor = new UserSelectedViewpointFactoryQueryProcessor();
\r
254 filterSelectionRequestQueryProcessor = new FilterSelectionRequestQueryProcessor();
\r
256 createAuxiliaryControls(parent, control);
\r
258 setupDropTarget(control);
\r
259 setWorkbenchListeners();
\r
260 activateUiContexts();
\r
263 protected void createAuxiliaryControls(Composite parent, Control explorerControl) {
\r
264 parent.setLayout(LayoutUtils.createNoBorderGridLayout(3, false));
\r
266 if (!hideComparatorSelector) {
\r
267 ComparatorSelector comparatorSelector = new ComparatorSelector(explorer, userSelectedComparableFactoryQueryProcessor, parent, SWT.READ_ONLY);
\r
268 comparatorSelector.moveAbove(explorerControl);
\r
271 if (!hideViewpointSelector) {
\r
272 ViewpointSelector viewpointSelector = new ViewpointSelector(explorer, userSelectedViewpointFactoryQueryProcessor, parent, SWT.READ_ONLY);
\r
273 viewpointSelector.moveAbove(explorerControl);
\r
277 filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, parent, SWT.READ_ONLY);
\r
278 filterArea.moveAbove(explorerControl);
\r
281 GridDataFactory.fillDefaults().grab(true, true).span(3,1).applyTo(explorerControl);
\r
284 protected void setupDropTarget(Control control) {
\r
285 DropTarget target = new DropTarget(control, DND.DROP_COPY | DND.DROP_LINK);
\r
286 target.setTransfer(getAcceptedDataTypes());
\r
287 target.addDropListener(new DropTargetAdapter() {
\r
288 Tree tree = (Tree) explorer.getControl();
\r
291 public void dragEnter(DropTargetEvent event) {
\r
292 event.detail = DND.DROP_COPY;
\r
296 public void drop(DropTargetEvent event) {
\r
297 TreeItem item = tree.getItem(tree.toControl(event.x, event.y));
\r
299 handleDrop(event.data, (NodeContext) item.getData());
\r
301 handleDrop(event.data, null);
\r
306 protected void activateUiContexts() {
\r
307 Collection<String> contexts = getUiContexts();
\r
308 if (!contexts.isEmpty()) {
\r
309 IContextService cs = (IContextService) getSite().getService(IContextService.class);
\r
310 for (String context : contexts)
\r
311 cs.activateContext(context);
\r
315 @SuppressWarnings("rawtypes")
\r
317 public Object getAdapter(Class adapter) {
\r
318 if (adapter == IFilterAreaProvider.class)
\r
320 return super.getAdapter(adapter);
\r
324 public void dispose() {
\r
325 //System.out.println(this + ".GraphExplorerViewBase2.dispose()");
\r
326 removeWorkbenchListeners();
\r
327 userSelectedComparableFactoryQueryProcessor = null;
\r
328 userSelectedViewpointFactoryQueryProcessor = null;
\r
329 filterSelectionRequestQueryProcessor = null;
\r
334 protected final void initializeExplorer(GraphExplorer explorer, ISessionContext context) {
\r
335 if (explorer.isDisposed())
\r
338 super.initializeExplorer(explorer, context);
\r
340 Session session = context != null ? context.getSession() : null;
\r
342 if (session != null) {
\r
343 evaluatorData = createEvaluatorData(session);
\r
344 factoryHints.setHint(GraphExplorerHints.KEY_SESSION_CONTEXT, context);
\r
345 explorer.setDataSource(new AsyncReadGraphDataSource(session));
\r
346 explorer.setDataSource(new ReadGraphDataSource(session));
\r
349 evaluatorData = new EvaluatorDataImpl();
\r
350 explorer.removeDataSource(AsyncReadGraph.class);
\r
351 explorer.removeDataSource(ReadGraph.class);
\r
352 factoryHints.removeHint(GraphExplorerHints.KEY_SESSION_CONTEXT);
\r
355 explorer.setProcessor(new ComparableFactoryResolver(evaluatorData));
\r
356 explorer.setProcessor(new ViewpointFactoryResolver(evaluatorData));
\r
357 explorer.setProcessor(new LabelerFactoryResolver(evaluatorData));
\r
358 explorer.setProcessor(new ImagerFactoryResolver(evaluatorData));
\r
359 explorer.setProcessor(new LabelDecoratorFactoryResolver(evaluatorData));
\r
360 explorer.setProcessor(new ImageDecoratorFactoryResolver(evaluatorData));
\r
361 explorer.setPrimitiveProcessor(new TypesQueryProcessor());
\r
362 explorer.setPrimitiveProcessor(new StandardContextTypesQueryProcessor());
\r
363 explorer.setPrimitiveProcessor(new InheritsQueryProcessor());
\r
364 explorer.setPrimitiveProcessor(new RelatedObjectsQueryProcessor());
\r
366 if(!hideViewpointSelector) {
\r
367 explorer.setPrimitiveProcessor(userSelectedViewpointFactoryQueryProcessor);
\r
368 explorer.setProcessor(new ComparableSelectorQueryProcessor());
\r
370 if(!hideComparatorSelector) {
\r
371 explorer.setPrimitiveProcessor(userSelectedComparableFactoryQueryProcessor);
\r
373 explorer.setPrimitiveProcessor(filterSelectionRequestQueryProcessor);
\r
375 initializeExplorerWithEvaluator(explorer, context, evaluatorData);
\r
378 protected void initializeExplorerWithEvaluator(GraphExplorer explorer, ISessionContext context, EvaluatorData data) {
\r
381 protected EvaluatorData createEvaluatorData(Session session) {
\r
382 return Evaluators.load(session, getBrowseContexts(), resourceManager);
\r
385 protected Transfer[] getAcceptedDataTypes() {
\r
386 return new Transfer[] { LocalObjectTransfer.getTransfer(), FileTransfer.getInstance() };
\r
389 protected void handleDrop(Object data, NodeContext target) {
\r
390 if (target != null) {
\r
391 Object input = target.getConstant(BuiltinKeys.INPUT);
\r
392 //System.out.println("DROPPED " + data + " ON " + target);
\r
393 if (input instanceof IDropTargetNode)
\r
394 ((IDropTargetNode) input).drop(data);
\r
399 protected Object createDragSource(GraphExplorer explorer) {
\r
400 ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);
\r
402 DragSourceListener listener = new LocalSelectionDragSourceListener(selectionProvider);
\r
404 Control control = explorer.getControl();
\r
405 DragSource source = new DragSource(control, DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT);
\r
406 source.setTransfer(new Transfer[] {LocalObjectTransfer.getTransfer()});
\r
407 source.addDragListener(listener);
\r
408 source.setDragSourceEffect(new NoImageDragSourceEffect(control));
\r
413 public EvaluatorData getEvaluatorData() {
\r
414 return evaluatorData;
\r