]> gerrit.simantics Code Review - simantics/platform.git/blob
477d6815e36901a52d832f30fb367d75ed870fc0
[simantics/platform.git] /
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         parent.setLayout(LayoutUtils.createNoBorderGridLayout(3, false));\r
265 \r
266         if (!hideComparatorSelector) {\r
267             ComparatorSelector comparatorSelector = new ComparatorSelector(explorer, userSelectedComparableFactoryQueryProcessor, parent, SWT.READ_ONLY);\r
268             comparatorSelector.moveAbove(explorerControl);\r
269         }\r
270 \r
271         if (!hideViewpointSelector) {\r
272             ViewpointSelector viewpointSelector = new ViewpointSelector(explorer, userSelectedViewpointFactoryQueryProcessor, parent, SWT.READ_ONLY);\r
273             viewpointSelector.moveAbove(explorerControl);\r
274         }\r
275 \r
276         if (!hideFilter) {\r
277             filterArea = new FilterArea(explorer, filterSelectionRequestQueryProcessor, parent, SWT.READ_ONLY);\r
278             filterArea.moveAbove(explorerControl);\r
279         }\r
280 \r
281         GridDataFactory.fillDefaults().grab(true, true).span(3,1).applyTo(explorerControl);\r
282     }\r
283 \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
289 \r
290             @Override\r
291             public void dragEnter(DropTargetEvent event) {\r
292                 event.detail = DND.DROP_COPY;\r
293             }\r
294 \r
295             @Override\r
296             public void drop(DropTargetEvent event) {\r
297                 TreeItem item = tree.getItem(tree.toControl(event.x, event.y));\r
298                 if (item != null)\r
299                     handleDrop(event.data, (NodeContext) item.getData());\r
300                 else\r
301                     handleDrop(event.data, null);\r
302             }\r
303         });\r
304     }\r
305 \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
312         }\r
313     }\r
314 \r
315     @SuppressWarnings("rawtypes")\r
316     @Override\r
317     public Object getAdapter(Class adapter) {\r
318         if (adapter == IFilterAreaProvider.class)\r
319             return filterArea;\r
320         return super.getAdapter(adapter);\r
321     }\r
322 \r
323     @Override\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
330         super.dispose();\r
331     }\r
332 \r
333     @Override\r
334     protected final void initializeExplorer(GraphExplorer explorer, ISessionContext context) {\r
335         if (explorer.isDisposed())\r
336             return;\r
337 \r
338         super.initializeExplorer(explorer, context);\r
339 \r
340         Session session = context != null ? context.getSession() : null;\r
341 \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
347         }\r
348         else {\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
353         }\r
354 \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
365 \r
366         if(!hideViewpointSelector) {\r
367                 explorer.setPrimitiveProcessor(userSelectedViewpointFactoryQueryProcessor);\r
368                 explorer.setProcessor(new ComparableSelectorQueryProcessor());\r
369         }\r
370         if(!hideComparatorSelector) {\r
371                 explorer.setPrimitiveProcessor(userSelectedComparableFactoryQueryProcessor);\r
372         }\r
373         explorer.setPrimitiveProcessor(filterSelectionRequestQueryProcessor);\r
374 \r
375         initializeExplorerWithEvaluator(explorer, context, evaluatorData);\r
376     }\r
377 \r
378     protected void initializeExplorerWithEvaluator(GraphExplorer explorer, ISessionContext context, EvaluatorData data) {\r
379     }\r
380 \r
381     protected EvaluatorData createEvaluatorData(Session session) {\r
382         return Evaluators.load(session, getBrowseContexts(), resourceManager);\r
383     }\r
384 \r
385     protected Transfer[] getAcceptedDataTypes() {\r
386         return new Transfer[] {  LocalObjectTransfer.getTransfer(), FileTransfer.getInstance() };\r
387     }\r
388 \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
395         }\r
396     }\r
397 \r
398     @Override\r
399     protected Object createDragSource(GraphExplorer explorer) {\r
400         ISelectionProvider selectionProvider = (ISelectionProvider) explorer.getAdapter(ISelectionProvider.class);\r
401 \r
402         DragSourceListener listener = new LocalSelectionDragSourceListener(selectionProvider);\r
403 \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
409 \r
410         return listener;\r
411     }\r
412 \r
413     public EvaluatorData getEvaluatorData() {\r
414         return evaluatorData;\r
415     }\r
416 \r
417 }\r