]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.platform/src/org/simantics/browsing/ui/platform/GraphExplorerView.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.browsing.ui.platform / src / org / simantics / browsing / ui / platform / GraphExplorerView.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.browsing.ui.platform;
13
14 import java.lang.reflect.Constructor;
15 import java.util.Collection;
16 import java.util.Collections;
17 import java.util.HashSet;
18 import java.util.Set;
19
20 import org.eclipse.core.runtime.IConfigurationElement;
21 import org.eclipse.core.runtime.Platform;
22 import org.eclipse.jface.layout.GridDataFactory;
23 import org.eclipse.jface.viewers.ISelectionProvider;
24 import org.eclipse.swt.SWT;
25 import org.eclipse.swt.dnd.DND;
26 import org.eclipse.swt.dnd.DragSource;
27 import org.eclipse.swt.dnd.DragSourceListener;
28 import org.eclipse.swt.dnd.DropTarget;
29 import org.eclipse.swt.dnd.DropTargetAdapter;
30 import org.eclipse.swt.dnd.DropTargetEvent;
31 import org.eclipse.swt.dnd.FileTransfer;
32 import org.eclipse.swt.dnd.Transfer;
33 import org.eclipse.swt.widgets.Composite;
34 import org.eclipse.swt.widgets.Control;
35 import org.eclipse.swt.widgets.Tree;
36 import org.eclipse.swt.widgets.TreeItem;
37 import org.eclipse.ui.IWorkbenchPartSite;
38 import org.eclipse.ui.PlatformUI;
39 import org.eclipse.ui.contexts.IContextService;
40 import org.osgi.framework.Bundle;
41 import org.simantics.browsing.ui.BuiltinKeys;
42 import org.simantics.browsing.ui.GraphExplorer;
43 import org.simantics.browsing.ui.NodeContext;
44 import org.simantics.browsing.ui.common.EvaluatorData;
45 import org.simantics.browsing.ui.common.EvaluatorDataImpl;
46 import org.simantics.browsing.ui.common.node.IDropTargetNode;
47 import org.simantics.browsing.ui.common.processors.ComparableFactoryResolver;
48 import org.simantics.browsing.ui.common.processors.ComparableSelectorQueryProcessor;
49 import org.simantics.browsing.ui.common.processors.FilterSelectionRequestQueryProcessor;
50 import org.simantics.browsing.ui.common.processors.ImageDecoratorFactoryResolver;
51 import org.simantics.browsing.ui.common.processors.ImagerFactoryResolver;
52 import org.simantics.browsing.ui.common.processors.LabelDecoratorFactoryResolver;
53 import org.simantics.browsing.ui.common.processors.LabelerFactoryResolver;
54 import org.simantics.browsing.ui.common.processors.UserSelectedComparableFactoryQueryProcessor;
55 import org.simantics.browsing.ui.common.processors.UserSelectedViewpointFactoryQueryProcessor;
56 import org.simantics.browsing.ui.common.processors.ViewpointFactoryResolver;
57 import org.simantics.browsing.ui.common.views.IFilterAreaProvider;
58 import org.simantics.browsing.ui.graph.impl.AsyncReadGraphDataSource;
59 import org.simantics.browsing.ui.graph.impl.Evaluators;
60 import org.simantics.browsing.ui.graph.impl.GraphExplorerHints;
61 import org.simantics.browsing.ui.graph.impl.InheritsQueryProcessor;
62 import org.simantics.browsing.ui.graph.impl.ReadGraphDataSource;
63 import org.simantics.browsing.ui.graph.impl.RelatedObjectsQueryProcessor;
64 import org.simantics.browsing.ui.swt.ComparatorSelector;
65 import org.simantics.browsing.ui.swt.FilterArea;
66 import org.simantics.browsing.ui.swt.GraphExplorerViewBase;
67 import org.simantics.browsing.ui.swt.StandardContextTypesQueryProcessor;
68 import org.simantics.browsing.ui.swt.TypesQueryProcessor;
69 import org.simantics.browsing.ui.swt.ViewpointSelector;
70 import org.simantics.db.AsyncReadGraph;
71 import org.simantics.db.ReadGraph;
72 import org.simantics.db.Session;
73 import org.simantics.db.management.ISessionContext;
74 import org.simantics.selectionview.StandardPropertyPage;
75 import org.simantics.ui.dnd.LocalObjectTransfer;
76 import org.simantics.ui.dnd.LocalSelectionDragSourceListener;
77 import org.simantics.ui.dnd.NoImageDragSourceEffect;
78 import org.simantics.ui.workbench.IPropertyPage;
79 import org.simantics.utils.datastructures.hints.HintContext;
80 import org.simantics.utils.datastructures.hints.IHintContext;
81 import org.simantics.utils.ui.ErrorLogger;
82 import org.simantics.utils.ui.LayoutUtils;
83
84 /**
85  * Override:
86  * <ul>
87  * <li>{@link #createAuxiliaryControls(Composite, Control)} to customize the
88  * creation of auxiliary controls around the graph explorer control, such as
89  * comparator/viewpoint selectors and filter area.</li>
90  * <li>{@link #getUiContexts()} to specify which
91  * <code>org.eclipse.ui.context</code> extension point contexts should be
92  * activated for this view site. May be empty.</li>
93  * <li>{@link #getBrowseContexts()} to specify how the view
94  * content/label/decoration production should be configured. May be empty, in
95  * which case the browser will show nothing.</li>
96  * <li>{@link #getContextMenuId()} to specify the ID of the context menu to be
97  * create for this view part and registered with the workbench. May be
98  * <code>null</code>, in which case a context menu will not be created nor
99  * registered with the workbench.</li>
100  * </ul>
101  * 
102  * @author Tuukka Lehtonen
103  * @deprecated in favor of org.simantics.views.swt.ModelledView
104  * 
105  **/
106 public class GraphExplorerView extends GraphExplorerViewBase {
107
108     protected UserSelectedComparableFactoryQueryProcessor userSelectedComparableFactoryQueryProcessor;
109     protected UserSelectedViewpointFactoryQueryProcessor  userSelectedViewpointFactoryQueryProcessor;
110     protected FilterSelectionRequestQueryProcessor        filterSelectionRequestQueryProcessor;
111     protected FilterArea                                  filterArea;
112     protected IHintContext                                factoryHints = new HintContext();
113     protected EvaluatorData                               evaluatorData;
114
115     protected Set<String>                                 browseContexts = Collections.emptySet();
116     protected String                                      contextMenuId;
117     protected Set<String>                                 uiContexts = Collections.emptySet();
118     protected String                                      propertyPageContributor;
119     protected String                                      propertyPageClassName;
120     protected Set<String>                                 propertyBrowseContexts = Collections.emptySet();
121
122     protected boolean                                     hideComparatorSelector = false;
123     protected boolean                                     hideViewpointSelector = false;
124     protected boolean                                     hideFilter = false;
125
126     @Override
127     public void setInitializationData(IConfigurationElement cfig, String propertyName, Object data) {
128         super.setInitializationData(cfig, propertyName, data);
129         if (data instanceof String) {
130             Set<String> browseContexts = new HashSet<String>();
131             Set<String> uiContexts = new HashSet<String>();
132             Set<String> propertyBrowseContexts = new HashSet<String>();
133
134             String[] parameters = ((String) data).split(";");
135
136             IContextService service = (IContextService) PlatformUI.getWorkbench().getService(IContextService.class);
137             Set<String> definedContexts = new HashSet<String>();
138             for (Object cid : service.getDefinedContextIds())
139                 definedContexts.add((String) cid);
140
141             for (String parameter : parameters) {
142                 String[] keyValue = parameter.split("=");
143                 if (keyValue.length > 2) {
144                     ErrorLogger.defaultLogWarning("Invalid parameter '" + parameter + ". Complete view argument: " + data, null);
145                     continue;
146                 }
147                 String key = keyValue[0];
148                 String value = keyValue.length > 1 ? keyValue[1] : "";
149
150                 if ("browseContext".equals(key)) {
151                     browseContexts.add(value);
152                 } else if ("contextMenuId".equals(key)) {
153                     this.contextMenuId = value;
154                 } else if ("uiContext".equals(key)) {
155                     if (!definedContexts.contains(value)) {
156                         ErrorLogger.defaultLogWarning("Parameter '" + parameter + "' references a non-existent Eclipse UI context '" + value + "'. Complete view argument: " + data, null);
157                         continue;
158                     }
159                     uiContexts.add(value);
160                 } else if ("propertyBrowseContext".equals(key)) {
161                     propertyBrowseContexts.add(value);
162                 } else if ("propertyPageClass".equals(key)) {
163                     this.propertyPageContributor = cfig.getContributor().getName();
164                     this.propertyPageClassName = value;
165                 } else if ("hideComparatorSelector".equals(key)) {
166                     this.hideComparatorSelector = true;
167                 } else if ("hideViewpointSelector".equals(key)) {
168                     this.hideViewpointSelector = true;
169                 } else if ("hideFilter".equals(key)) {
170                     this.hideFilter = true;
171                 }
172             }
173
174             this.browseContexts = browseContexts;
175             this.uiContexts = uiContexts;
176             this.propertyBrowseContexts = propertyBrowseContexts;
177         }
178     }
179
180     public GraphExplorer getExplorer() {
181         return explorer;
182     }
183     
184     public <T> T getBrowseContext() {
185         return evaluatorData.getBrowseContext();
186     }
187     
188     
189     /**
190      * Override this to specify which browse contexts are considered active for
191      * this browser. This information is read only once during view
192      * initialization, no change listening is implemented.
193      * 
194      * @return
195      */
196     protected Set<String> getBrowseContexts() {
197         return browseContexts;
198     }
199
200     /* (non-Javadoc)
201      * @see org.simantics.browsing.ui.swt.GraphExplorerViewBase#getContextMenuId()
202      */
203     @Override
204     protected String getContextMenuId() {
205         return contextMenuId;
206     }
207
208     /**
209      * @return the set of <code>org.eclipse.ui.context</code> contexts to
210      *         activate for this view site
211      */
212     protected Set<String> getUiContexts() {
213         return uiContexts;
214     }
215
216     @Override
217     protected IPropertyPage getPropertyPage() {
218         if (propertyPageContributor != null && propertyPageClassName != null) {
219             try {
220                 Bundle b = Platform.getBundle(propertyPageContributor);
221                 if (b == null) {
222                     ErrorLogger.defaultLogError("property page '" + propertyPageClassName + "' contributor bundle '"
223                             + propertyPageContributor + "' was not found in the platform.", null);
224                     return null;
225                 }
226                 Class<?> clazz = b.loadClass(propertyPageClassName);
227                 if (!IPropertyPage.class.isAssignableFrom(clazz)) {
228                     ErrorLogger.defaultLogError("property page class '" + propertyPageClassName + "' is not assignable to "
229                             + IPropertyPage.class + ".", null);
230                     return null;
231                 }
232                 Constructor<?> ctor = clazz.getConstructor(IWorkbenchPartSite.class);
233                 return (IPropertyPage) ctor.newInstance(getSite());
234             } catch (Exception e) {
235                 ErrorLogger.defaultLogError("Failed to instantiate IPropertyPage implementation '" + propertyPageClassName
236                         + "' from bundle '" + propertyPageContributor + "'. See exception for details.", e);
237                 // Something failed, don't try to instantiate the property page anymore.
238                 propertyPageClassName = null;
239             }
240         } else if (!propertyBrowseContexts.isEmpty()) {
241             return new StandardPropertyPage(getSite(), new HashSet<String>(propertyBrowseContexts));
242         }
243         return null;
244     }
245
246     @Override
247     protected void createControls(Composite parent) {
248         super.createControls(parent);
249
250         Control control = explorer.getControl();
251
252         userSelectedComparableFactoryQueryProcessor = new UserSelectedComparableFactoryQueryProcessor();
253         userSelectedViewpointFactoryQueryProcessor = new UserSelectedViewpointFactoryQueryProcessor();
254         filterSelectionRequestQueryProcessor = new FilterSelectionRequestQueryProcessor();
255
256         createAuxiliaryControls(parent, control);
257
258         setupDropTarget(control);
259         setWorkbenchListeners();
260         activateUiContexts();
261     }
262
263     protected void createAuxiliaryControls(Composite parent, Control explorerControl) {
264         if (explorerControl instanceof Tree)
265                 parent.setLayout(LayoutUtils.createNoBorderGridLayout(3, false));
266
267         if (!hideComparatorSelector) {
268             ComparatorSelector comparatorSelector = new ComparatorSelector(explorer, userSelectedComparableFactoryQueryProcessor, parent, SWT.READ_ONLY);
269             comparatorSelector.moveAbove(explorerControl);
270         }
271
272         if (!hideViewpointSelector) {
273             ViewpointSelector viewpointSelector = new ViewpointSelector(explorer, userSelectedViewpointFactoryQueryProcessor, parent, SWT.READ_ONLY);
274             viewpointSelector.moveAbove(explorerControl);
275         }
276
277         if (!hideFilter) {
278             filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, parent, SWT.READ_ONLY);
279             filterArea.moveAbove(explorerControl);
280         }
281
282         GridDataFactory.fillDefaults().grab(true, true).span(3,1).applyTo(explorerControl);
283     }
284
285     protected void setupDropTarget(Control control) {
286         DropTarget target = new DropTarget(control, DND.DROP_COPY | DND.DROP_LINK);
287         target.setTransfer(getAcceptedDataTypes());
288         target.addDropListener(new DropTargetAdapter() {
289             Tree tree = (Tree) explorer.getControl();
290
291             @Override
292             public void dragEnter(DropTargetEvent event) {
293                 event.detail = DND.DROP_COPY;
294             }
295
296             @Override
297             public void drop(DropTargetEvent event) {
298                 TreeItem item = tree.getItem(tree.toControl(event.x, event.y));
299                 if (item != null)
300                     handleDrop(event.data, (NodeContext) item.getData());
301                 else
302                     handleDrop(event.data, null);
303             }
304         });
305     }
306
307     protected void activateUiContexts() {
308         Collection<String> contexts = getUiContexts();
309         if (!contexts.isEmpty()) {
310             IContextService cs = (IContextService) getSite().getService(IContextService.class);
311             for (String context : contexts)
312                 cs.activateContext(context);
313         }
314     }
315
316     @SuppressWarnings("rawtypes")
317     @Override
318     public Object getAdapter(Class adapter) {
319         if (adapter == IFilterAreaProvider.class)
320             return filterArea;
321         return super.getAdapter(adapter);
322     }
323
324     @Override
325     public void dispose() {
326         //System.out.println(this + ".GraphExplorerViewBase2.dispose()");
327         removeWorkbenchListeners();
328         userSelectedComparableFactoryQueryProcessor = null;
329         userSelectedViewpointFactoryQueryProcessor = null;
330         filterSelectionRequestQueryProcessor = null;
331         super.dispose();
332     }
333
334     @Override
335     protected final void initializeExplorer(GraphExplorer explorer, ISessionContext context) {
336         if (explorer.isDisposed())
337             return;
338
339         super.initializeExplorer(explorer, context);
340
341         Session session = context != null ? context.getSession() : null;
342
343         if (session != null) {
344             evaluatorData = createEvaluatorData(session);
345             factoryHints.setHint(GraphExplorerHints.KEY_SESSION_CONTEXT, context);
346             explorer.setDataSource(new AsyncReadGraphDataSource(session));
347             explorer.setDataSource(new ReadGraphDataSource(session));
348         }
349         else {
350             evaluatorData = new EvaluatorDataImpl();
351             explorer.removeDataSource(AsyncReadGraph.class);
352             explorer.removeDataSource(ReadGraph.class);
353             factoryHints.removeHint(GraphExplorerHints.KEY_SESSION_CONTEXT);
354         }
355
356         explorer.setProcessor(new ComparableFactoryResolver(evaluatorData));
357         explorer.setProcessor(new ViewpointFactoryResolver(evaluatorData));
358         explorer.setProcessor(new LabelerFactoryResolver(evaluatorData));
359         explorer.setProcessor(new ImagerFactoryResolver(evaluatorData));
360         explorer.setProcessor(new LabelDecoratorFactoryResolver(evaluatorData));
361         explorer.setProcessor(new ImageDecoratorFactoryResolver(evaluatorData));
362         explorer.setPrimitiveProcessor(new TypesQueryProcessor());
363         explorer.setPrimitiveProcessor(new StandardContextTypesQueryProcessor());
364         explorer.setPrimitiveProcessor(new InheritsQueryProcessor());
365         explorer.setPrimitiveProcessor(new RelatedObjectsQueryProcessor());
366
367         if(!hideViewpointSelector) {
368                 explorer.setPrimitiveProcessor(userSelectedViewpointFactoryQueryProcessor);
369                 explorer.setProcessor(new ComparableSelectorQueryProcessor());
370         }
371         if(!hideComparatorSelector) {
372                 explorer.setPrimitiveProcessor(userSelectedComparableFactoryQueryProcessor);
373         }
374         explorer.setPrimitiveProcessor(filterSelectionRequestQueryProcessor);
375
376         initializeExplorerWithEvaluator(explorer, context, evaluatorData);
377     }
378
379     protected void initializeExplorerWithEvaluator(GraphExplorer explorer, ISessionContext context, EvaluatorData data) {
380     }
381
382     protected EvaluatorData createEvaluatorData(Session session) {
383         return Evaluators.load(session, getBrowseContexts(), resourceManager);
384     }
385
386     protected Transfer[] getAcceptedDataTypes() {
387         return new Transfer[] {  LocalObjectTransfer.getTransfer(), FileTransfer.getInstance() };
388     }
389
390     protected void handleDrop(Object data, NodeContext target) {
391         if (target != null) {
392             Object input = target.getConstant(BuiltinKeys.INPUT);
393             //System.out.println("DROPPED " + data + " ON " + target);
394             if (input instanceof IDropTargetNode)
395                 ((IDropTargetNode) input).drop(data);
396         }
397     }
398
399     @Override
400     protected Object createDragSource(GraphExplorer explorer) {
401         ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);
402
403         DragSourceListener listener = new LocalSelectionDragSourceListener(selectionProvider);
404
405         Control control = explorer.getControl();
406         DragSource source = new DragSource(control, DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT);
407         source.setTransfer(new Transfer[] {LocalObjectTransfer.getTransfer()});
408         source.addDragListener(listener);
409         source.setDragSourceEffect(new NoImageDragSourceEffect(control));
410
411         return listener;
412     }
413
414     public EvaluatorData getEvaluatorData() {
415         return evaluatorData;
416     }
417
418 }