]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.browsing.ui.platform/src/org/simantics/browsing/ui/platform/GraphExplorerView.java
Sync git svn branch with SVN repository r33144.
[simantics/platform.git] / bundles / org.simantics.browsing.ui.platform / src / org / simantics / browsing / ui / platform / GraphExplorerView.java
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
8  *\r
9  * Contributors:\r
10  *     VTT Technical Research Centre of Finland - initial API and implementation\r
11  *******************************************************************************/\r
12 package org.simantics.browsing.ui.platform;\r
13 \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
19 \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
83 \r
84 /**\r
85  * Override:\r
86  * <ul>\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
100  * </ul>\r
101  * \r
102  * @author Tuukka Lehtonen\r
103  * @deprecated in favor of org.simantics.views.swt.ModelledView\r
104  * \r
105  **/\r
106 public class GraphExplorerView extends GraphExplorerViewBase {\r
107 \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
114 \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
121 \r
122     protected boolean                                     hideComparatorSelector = false;\r
123     protected boolean                                     hideViewpointSelector = false;\r
124     protected boolean                                     hideFilter = false;\r
125 \r
126     @Override\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
133 \r
134             String[] parameters = ((String) data).split(";");\r
135 \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
140 \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
145                     continue;\r
146                 }\r
147                 String key = keyValue[0];\r
148                 String value = keyValue.length > 1 ? keyValue[1] : "";\r
149 \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
157                         continue;\r
158                     }\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
171                 }\r
172             }\r
173 \r
174             this.browseContexts = browseContexts;\r
175             this.uiContexts = uiContexts;\r
176             this.propertyBrowseContexts = propertyBrowseContexts;\r
177         }\r
178     }\r
179 \r
180     public GraphExplorer getExplorer() {\r
181         return explorer;\r
182     }\r
183     \r
184     public <T> T getBrowseContext() {\r
185         return evaluatorData.getBrowseContext();\r
186     }\r
187     \r
188     \r
189     /**\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
193      * \r
194      * @return\r
195      */\r
196     protected Set<String> getBrowseContexts() {\r
197         return browseContexts;\r
198     }\r
199 \r
200     /* (non-Javadoc)\r
201      * @see org.simantics.browsing.ui.swt.GraphExplorerViewBase#getContextMenuId()\r
202      */\r
203     @Override\r
204     protected String getContextMenuId() {\r
205         return contextMenuId;\r
206     }\r
207 \r
208     /**\r
209      * @return the set of <code>org.eclipse.ui.context</code> contexts to\r
210      *         activate for this view site\r
211      */\r
212     protected Set<String> getUiContexts() {\r
213         return uiContexts;\r
214     }\r
215 \r
216     @Override\r
217     protected IPropertyPage getPropertyPage() {\r
218         if (propertyPageContributor != null && propertyPageClassName != null) {\r
219             try {\r
220                 Bundle b = Platform.getBundle(propertyPageContributor);\r
221                 if (b == null) {\r
222                     ErrorLogger.defaultLogError("property page '" + propertyPageClassName + "' contributor bundle '"\r
223                             + propertyPageContributor + "' was not found in the platform.", null);\r
224                     return null;\r
225                 }\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
230                     return null;\r
231                 }\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
239             }\r
240         } else if (!propertyBrowseContexts.isEmpty()) {\r
241             return new StandardPropertyPage(getSite(), new HashSet<String>(propertyBrowseContexts));\r
242         }\r
243         return null;\r
244     }\r
245 \r
246     @Override\r
247     protected void createControls(Composite parent) {\r
248         super.createControls(parent);\r
249 \r
250         Control control = explorer.getControl();\r
251 \r
252         userSelectedComparableFactoryQueryProcessor = new UserSelectedComparableFactoryQueryProcessor();\r
253         userSelectedViewpointFactoryQueryProcessor = new UserSelectedViewpointFactoryQueryProcessor();\r
254         filterSelectionRequestQueryProcessor = new FilterSelectionRequestQueryProcessor();\r
255 \r
256         createAuxiliaryControls(parent, control);\r
257 \r
258         setupDropTarget(control);\r
259         setWorkbenchListeners();\r
260         activateUiContexts();\r
261     }\r
262 \r
263     protected void createAuxiliaryControls(Composite parent, Control explorerControl) {\r
264         if (explorerControl instanceof Tree)\r
265                 parent.setLayout(LayoutUtils.createNoBorderGridLayout(3, false));\r
266 \r
267         if (!hideComparatorSelector) {\r
268             ComparatorSelector comparatorSelector = new ComparatorSelector(explorer, userSelectedComparableFactoryQueryProcessor, parent, SWT.READ_ONLY);\r
269             comparatorSelector.moveAbove(explorerControl);\r
270         }\r
271 \r
272         if (!hideViewpointSelector) {\r
273             ViewpointSelector viewpointSelector = new ViewpointSelector(explorer, userSelectedViewpointFactoryQueryProcessor, parent, SWT.READ_ONLY);\r
274             viewpointSelector.moveAbove(explorerControl);\r
275         }\r
276 \r
277         if (!hideFilter) {\r
278             filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, parent, SWT.READ_ONLY);\r
279             filterArea.moveAbove(explorerControl);\r
280         }\r
281 \r
282         GridDataFactory.fillDefaults().grab(true, true).span(3,1).applyTo(explorerControl);\r
283     }\r
284 \r
285     protected void setupDropTarget(Control control) {\r
286         DropTarget target = new DropTarget(control, DND.DROP_COPY | DND.DROP_LINK);\r
287         target.setTransfer(getAcceptedDataTypes());\r
288         target.addDropListener(new DropTargetAdapter() {\r
289             Tree tree = (Tree) explorer.getControl();\r
290 \r
291             @Override\r
292             public void dragEnter(DropTargetEvent event) {\r
293                 event.detail = DND.DROP_COPY;\r
294             }\r
295 \r
296             @Override\r
297             public void drop(DropTargetEvent event) {\r
298                 TreeItem item = tree.getItem(tree.toControl(event.x, event.y));\r
299                 if (item != null)\r
300                     handleDrop(event.data, (NodeContext) item.getData());\r
301                 else\r
302                     handleDrop(event.data, null);\r
303             }\r
304         });\r
305     }\r
306 \r
307     protected void activateUiContexts() {\r
308         Collection<String> contexts = getUiContexts();\r
309         if (!contexts.isEmpty()) {\r
310             IContextService cs = (IContextService) getSite().getService(IContextService.class);\r
311             for (String context : contexts)\r
312                 cs.activateContext(context);\r
313         }\r
314     }\r
315 \r
316     @SuppressWarnings("rawtypes")\r
317     @Override\r
318     public Object getAdapter(Class adapter) {\r
319         if (adapter == IFilterAreaProvider.class)\r
320             return filterArea;\r
321         return super.getAdapter(adapter);\r
322     }\r
323 \r
324     @Override\r
325     public void dispose() {\r
326         //System.out.println(this + ".GraphExplorerViewBase2.dispose()");\r
327         removeWorkbenchListeners();\r
328         userSelectedComparableFactoryQueryProcessor = null;\r
329         userSelectedViewpointFactoryQueryProcessor = null;\r
330         filterSelectionRequestQueryProcessor = null;\r
331         super.dispose();\r
332     }\r
333 \r
334     @Override\r
335     protected final void initializeExplorer(GraphExplorer explorer, ISessionContext context) {\r
336         if (explorer.isDisposed())\r
337             return;\r
338 \r
339         super.initializeExplorer(explorer, context);\r
340 \r
341         Session session = context != null ? context.getSession() : null;\r
342 \r
343         if (session != null) {\r
344             evaluatorData = createEvaluatorData(session);\r
345             factoryHints.setHint(GraphExplorerHints.KEY_SESSION_CONTEXT, context);\r
346             explorer.setDataSource(new AsyncReadGraphDataSource(session));\r
347             explorer.setDataSource(new ReadGraphDataSource(session));\r
348         }\r
349         else {\r
350             evaluatorData = new EvaluatorDataImpl();\r
351             explorer.removeDataSource(AsyncReadGraph.class);\r
352             explorer.removeDataSource(ReadGraph.class);\r
353             factoryHints.removeHint(GraphExplorerHints.KEY_SESSION_CONTEXT);\r
354         }\r
355 \r
356         explorer.setProcessor(new ComparableFactoryResolver(evaluatorData));\r
357         explorer.setProcessor(new ViewpointFactoryResolver(evaluatorData));\r
358         explorer.setProcessor(new LabelerFactoryResolver(evaluatorData));\r
359         explorer.setProcessor(new ImagerFactoryResolver(evaluatorData));\r
360         explorer.setProcessor(new LabelDecoratorFactoryResolver(evaluatorData));\r
361         explorer.setProcessor(new ImageDecoratorFactoryResolver(evaluatorData));\r
362         explorer.setPrimitiveProcessor(new TypesQueryProcessor());\r
363         explorer.setPrimitiveProcessor(new StandardContextTypesQueryProcessor());\r
364         explorer.setPrimitiveProcessor(new InheritsQueryProcessor());\r
365         explorer.setPrimitiveProcessor(new RelatedObjectsQueryProcessor());\r
366 \r
367         if(!hideViewpointSelector) {\r
368                 explorer.setPrimitiveProcessor(userSelectedViewpointFactoryQueryProcessor);\r
369                 explorer.setProcessor(new ComparableSelectorQueryProcessor());\r
370         }\r
371         if(!hideComparatorSelector) {\r
372                 explorer.setPrimitiveProcessor(userSelectedComparableFactoryQueryProcessor);\r
373         }\r
374         explorer.setPrimitiveProcessor(filterSelectionRequestQueryProcessor);\r
375 \r
376         initializeExplorerWithEvaluator(explorer, context, evaluatorData);\r
377     }\r
378 \r
379     protected void initializeExplorerWithEvaluator(GraphExplorer explorer, ISessionContext context, EvaluatorData data) {\r
380     }\r
381 \r
382     protected EvaluatorData createEvaluatorData(Session session) {\r
383         return Evaluators.load(session, getBrowseContexts(), resourceManager);\r
384     }\r
385 \r
386     protected Transfer[] getAcceptedDataTypes() {\r
387         return new Transfer[] {  LocalObjectTransfer.getTransfer(), FileTransfer.getInstance() };\r
388     }\r
389 \r
390     protected void handleDrop(Object data, NodeContext target) {\r
391         if (target != null) {\r
392             Object input = target.getConstant(BuiltinKeys.INPUT);\r
393             //System.out.println("DROPPED " + data + " ON " + target);\r
394             if (input instanceof IDropTargetNode)\r
395                 ((IDropTargetNode) input).drop(data);\r
396         }\r
397     }\r
398 \r
399     @Override\r
400     protected Object createDragSource(GraphExplorer explorer) {\r
401         ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);\r
402 \r
403         DragSourceListener listener = new LocalSelectionDragSourceListener(selectionProvider);\r
404 \r
405         Control control = explorer.getControl();\r
406         DragSource source = new DragSource(control, DND.DROP_LINK | DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_DEFAULT);\r
407         source.setTransfer(new Transfer[] {LocalObjectTransfer.getTransfer()});\r
408         source.addDragListener(listener);\r
409         source.setDragSourceEffect(new NoImageDragSourceEffect(control));\r
410 \r
411         return listener;\r
412     }\r
413 \r
414     public EvaluatorData getEvaluatorData() {\r
415         return evaluatorData;\r
416     }\r
417 \r
418 }\r