]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/WikiDiagramViewer.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / diagramEditor / WikiDiagramViewer.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.modeling.ui.diagramEditor;\r
13 \r
14 import java.awt.Color;\r
15 import java.awt.datatransfer.Transferable;\r
16 import java.awt.datatransfer.UnsupportedFlavorException;\r
17 import java.io.IOException;\r
18 \r
19 import org.eclipse.core.runtime.IProgressMonitor;\r
20 import org.eclipse.core.runtime.NullProgressMonitor;\r
21 import org.eclipse.swt.widgets.Composite;\r
22 import org.eclipse.ui.IEditorInput;\r
23 import org.eclipse.ui.IEditorSite;\r
24 import org.eclipse.ui.PartInitException;\r
25 import org.eclipse.ui.contexts.IContextActivation;\r
26 import org.eclipse.ui.contexts.IContextService;\r
27 import org.eclipse.ui.part.EditorPart;\r
28 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;\r
29 import org.simantics.db.ReadGraph;\r
30 import org.simantics.db.Session;\r
31 import org.simantics.db.common.ResourceArray;\r
32 import org.simantics.db.exception.DatabaseException;\r
33 import org.simantics.db.management.ISessionContext;\r
34 import org.simantics.db.management.ISessionContextProvider;\r
35 import org.simantics.db.request.Read;\r
36 import org.simantics.db.service.SerialisationSupport;\r
37 import org.simantics.diagram.adapter.DefaultConnectionClassFactory;\r
38 import org.simantics.diagram.adapter.FlagClassFactory;\r
39 import org.simantics.diagram.adapter.GraphToDiagramSynchronizer;\r
40 import org.simantics.diagram.handler.SimpleElementTransformHandler;\r
41 import org.simantics.diagram.layer.ILayersViewPage;\r
42 import org.simantics.diagram.query.DiagramRequests;\r
43 import org.simantics.diagram.stubs.DiagramResource;\r
44 import org.simantics.diagram.ui.DiagramModelHints;\r
45 import org.simantics.g2d.canvas.Hints;\r
46 import org.simantics.g2d.canvas.ICanvasContext;\r
47 import org.simantics.g2d.canvas.impl.CanvasContext;\r
48 import org.simantics.g2d.diagram.DiagramHints;\r
49 import org.simantics.g2d.diagram.IDiagram;\r
50 import org.simantics.g2d.diagram.participant.DiagramParticipant;\r
51 import org.simantics.g2d.diagram.participant.ElementInteractor;\r
52 import org.simantics.g2d.diagram.participant.ElementPainter;\r
53 import org.simantics.g2d.diagram.participant.Selection;\r
54 import org.simantics.g2d.diagram.participant.TerminalPainter;\r
55 import org.simantics.g2d.diagram.participant.ZOrderHandler;\r
56 import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;\r
57 import org.simantics.g2d.element.ElementClassProviders;\r
58 import org.simantics.g2d.element.ElementClasses;\r
59 import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
60 import org.simantics.g2d.multileveldiagram.TransitionFunction;\r
61 import org.simantics.g2d.multileveldiagram.ZoomTransitionParticipant;\r
62 import org.simantics.g2d.participant.BackgroundPainter;\r
63 import org.simantics.g2d.participant.CanvasBoundsParticipant;\r
64 import org.simantics.g2d.participant.CanvasGrab;\r
65 import org.simantics.g2d.participant.GridPainter;\r
66 import org.simantics.g2d.participant.KeyToCommand;\r
67 import org.simantics.g2d.participant.KeyUtil;\r
68 import org.simantics.g2d.participant.MouseUtil;\r
69 import org.simantics.g2d.participant.MultitouchPanZoomRotateInteractor;\r
70 import org.simantics.g2d.participant.Notifications;\r
71 import org.simantics.g2d.participant.PageBorderParticipant;\r
72 import org.simantics.g2d.participant.PanZoomRotateHandler;\r
73 import org.simantics.g2d.participant.PointerPainter;\r
74 import org.simantics.g2d.participant.RulerPainter;\r
75 import org.simantics.g2d.participant.SymbolUtil;\r
76 import org.simantics.g2d.participant.TimeParticipant;\r
77 import org.simantics.g2d.participant.TransformUtil;\r
78 import org.simantics.g2d.participant.ZoomToAreaHandler;\r
79 import org.simantics.g2d.utils.CanvasUtils;\r
80 import org.simantics.layer0.utils.triggers.IActivation;\r
81 import org.simantics.modeling.ModelingResources;\r
82 import org.simantics.modeling.mapping.ModelingSynchronizationHints;\r
83 import org.simantics.scenegraph.g2d.events.command.CommandKeyBinding;\r
84 import org.simantics.scenegraph.g2d.events.command.Commands;\r
85 import org.simantics.simulation.experiment.IExperiment;\r
86 import org.simantics.ui.SimanticsUI;\r
87 import org.simantics.ui.dnd.ResourceTransferData;\r
88 import org.simantics.ui.dnd.ResourceTransferUtils;\r
89 import org.simantics.ui.workbench.IResourceEditorInput;\r
90 import org.simantics.ui.workbench.IResourceEditorInput2;\r
91 import org.simantics.ui.workbench.IResourceEditorPart2;\r
92 import org.simantics.ui.workbench.ResourceEditorSupport;\r
93 import org.simantics.utils.datastructures.hints.HintContext;\r
94 import org.simantics.utils.datastructures.hints.IHintContext;\r
95 import org.simantics.utils.page.PageDesc;\r
96 import org.simantics.utils.page.PageOrientation;\r
97 import org.simantics.utils.threads.AWTThread;\r
98 import org.simantics.utils.threads.IThreadWorkQueue;\r
99 \r
100 /**\r
101  * @author J-P Laine\r
102  */\r
103 public class WikiDiagramViewer extends EditorPart implements IResourceEditorPart2 {\r
104 \r
105     protected boolean                  disposed = false;\r
106     protected IDiagram                 sourceDiagram;\r
107     protected ICanvasContext           canvasContext;\r
108     protected ResourceEditorSupport    support;\r
109     protected ISessionContextProvider  sessionContextProvider;\r
110     protected ISessionContext          sessionContext;\r
111     protected GraphToDiagramSynchronizer synchronizer;\r
112     protected IActivation              activation;\r
113     protected ResourceArray            structuralPath = new ResourceArray();\r
114     protected IContextActivation       contextActivation;\r
115     protected IExperiment              experiment;\r
116     protected String                               layer = null;\r
117 \r
118     public WikiDiagramViewer() {\r
119     }\r
120 \r
121     protected void addDropParticipants(ICanvasContext ctx) {\r
122         // FIXME This is a workaround so that this participant can be disabled\r
123         // for SymbolViewer\r
124         ctx.add(new PopulateElementDropParticipant(synchronizer));\r
125         ctx.add(new PopulateElementMonitorDropParticipant(synchronizer, 0.5, 0.5));\r
126     }\r
127 \r
128     protected void addKeyBindingParticipants(CanvasContext ctx) {\r
129         ctx.add( new KeyToCommand( CommandKeyBinding.DEFAULT_BINDINGS ) );\r
130     }\r
131 \r
132     public void setExperiment(IExperiment experiment) {\r
133         sourceDiagram.setHint(DiagramModelHints.KEY_ACTIVE_EXPERIMENT, experiment);\r
134     }\r
135 \r
136     public void init(ResourceArray structuralPath, String layer, IExperiment experiment) {\r
137         this.experiment = experiment;\r
138         this.layer = layer;\r
139         this.structuralPath = structuralPath;\r
140 \r
141         sessionContextProvider = SimanticsUI.getSessionContextProvider();\r
142         sessionContext = sessionContextProvider.getSessionContext();\r
143 \r
144         canvasContext = createViewerCanvas();\r
145 \r
146         try {\r
147             sourceDiagram = loadDiagram(structuralPath, experiment);\r
148         } catch (DatabaseException e) {\r
149             e.printStackTrace();\r
150         }\r
151         onCreated();\r
152     }\r
153 \r
154     public void updateDiagram(ResourceArray structuralPath) {\r
155         canvasContext = createViewerCanvas();\r
156         try {\r
157             IHintContext hints = new HintContext();\r
158             hints.setHint(DiagramModelHints.KEY_ACTIVE_EXPERIMENT, experiment);\r
159             if(layer != null) {\r
160                 System.out.println("using layer '"+layer+"'");\r
161                 hints.setHint(DiagramHints.KEY_FIXED_LAYERS, new String[] { layer });\r
162             }\r
163 \r
164             sourceDiagram = sessionContext.getSession().syncRequest(DiagramRequests.loadDiagram(new NullProgressMonitor(), getResourceInput2().getModel(null), structuralPath.resources[0], null, structuralPath.removeFromBeginning(0), synchronizer, hints));\r
165             canvasContext.getDefaultHintContext().setHint(DiagramHints.KEY_DIAGRAM, sourceDiagram);\r
166         } catch (DatabaseException e) {\r
167             e.printStackTrace();\r
168         }\r
169     }\r
170 \r
171     void scheduleZoomToFit() {\r
172         if (sourceDiagram == null)\r
173             throw new IllegalStateException("source diagram is null");\r
174 \r
175         sourceDiagram.setHint(Hints.KEY_DISABLE_PAINTING, Boolean.TRUE);\r
176         sourceDiagram.setHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT, Boolean.TRUE);\r
177 \r
178         // zoom-to-fit\r
179         sourceDiagram.removeHint(Hints.KEY_DISABLE_PAINTING);\r
180         Boolean zoomToFit = sourceDiagram.removeHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT);\r
181         if (zoomToFit != null && zoomToFit)\r
182             CanvasUtils.sendCommand(canvasContext, Commands.ZOOM_TO_FIT);\r
183         canvasContext.getContentContext().setDirty();\r
184     }\r
185 \r
186     protected IDiagram loadDiagram(ResourceArray structuralPath, IExperiment experiment) throws DatabaseException {\r
187         IHintContext hints = new HintContext();\r
188         if(experiment != null)\r
189             hints.setHint(DiagramModelHints.KEY_ACTIVE_EXPERIMENT, experiment);\r
190         if(layer != null) {\r
191             System.out.println("using layer '"+layer+"'");\r
192             hints.setHint(DiagramHints.KEY_FIXED_LAYERS, new String[] { layer });\r
193         }\r
194         IDiagram d = sessionContext.getSession().syncRequest(DiagramRequests.loadDiagram(new NullProgressMonitor(), getResourceInput2().getModel(null), structuralPath.resources[0], null, structuralPath.removeFromBeginning(0), synchronizer, hints));\r
195         canvasContext.getDefaultHintContext().setHint(DiagramHints.KEY_DIAGRAM, d);\r
196         return d;\r
197     }\r
198 \r
199     protected GraphToDiagramSynchronizer createSynchronizer(final ICanvasContext ctx, final ISessionContext sessionContext) {\r
200         try {\r
201             return sessionContext.getSession().syncRequest(new Read<GraphToDiagramSynchronizer>() {\r
202                 @Override\r
203                 public GraphToDiagramSynchronizer perform(ReadGraph graph) throws DatabaseException {\r
204                     DiagramResource dr = DiagramResource.getInstance(graph);\r
205                     GraphToDiagramSynchronizer sync = new GraphToDiagramSynchronizer(graph, ctx,\r
206                             ElementClassProviders.mappedProvider(\r
207                                     ElementClasses.CONNECTION, DefaultConnectionClassFactory.CLASS.newClassWith(new StaticObjectAdapter(dr.Connection)),\r
208                                     ElementClasses.FLAG, FlagClassFactory.createFlagClass(dr.Flag, dr.Flag_Terminal)\r
209                             )\r
210                     );\r
211                     sync.set(ModelingSynchronizationHints.MODELING_RESOURCE, ModelingResources.getInstance(graph));\r
212                     return sync;\r
213                 }\r
214             });\r
215         } catch (DatabaseException e) {\r
216             throw new UnsupportedOperationException("Failed to initialize data model synchronizer", e);\r
217         }\r
218     }\r
219 \r
220     public ICanvasContext createViewerCanvas()\r
221     {\r
222         IThreadWorkQueue thread = AWTThread.getThreadAccess();\r
223         CanvasContext ctx = new CanvasContext(thread);\r
224         IHintContext h = ctx.getDefaultHintContext();\r
225 \r
226         this.synchronizer = createSynchronizer(ctx, sessionContext);\r
227 \r
228         canvasContext.add( new PanZoomRotateHandler() ); // Must be before TransformUtil\r
229 \r
230         // Support & Util Participants\r
231         ctx.add( new TransformUtil() );\r
232         ctx.add( new MouseUtil() );\r
233         ctx.add( new KeyUtil() );\r
234         ctx.add( new CanvasGrab() );\r
235         ctx.add( new SymbolUtil() );\r
236         ctx.add( new TimeParticipant() );\r
237         ctx.add( new CanvasBoundsParticipant() );\r
238         ctx.add( new Notifications() );\r
239 \r
240 //        ctx.add( new SGFocusParticipant(c) ); // FIXME: Get chassis from somewhere\r
241 \r
242         h.setHint(PointerPainter.KEY_PAINT_POINTER, true);\r
243 \r
244         ctx.add( new MultitouchPanZoomRotateInteractor() );\r
245         ctx.add( new ZoomToAreaHandler() );\r
246         ctx.add( new SimpleElementTransformHandler() );\r
247 \r
248         // Key bindings\r
249         addKeyBindingParticipants(ctx);\r
250 \r
251         // Grid & Ruler & Background\r
252 \r
253         ctx.add( new GridPainter() );\r
254         ctx.add( new RulerPainter() );\r
255         ctx.add( new BackgroundPainter() );\r
256         ctx.add( new PageBorderParticipant() );\r
257 \r
258         h.setHint(Hints.KEY_GRID_COLOR, new Color(0.95f, 0.95f, 0.95f));\r
259         h.setHint(Hints.KEY_BACKGROUND_COLOR, Color.WHITE);\r
260         h.setHint(RulerPainter.KEY_RULER_BACKGROUND_COLOR, new Color(0.9f, 0.9f, 0.9f, 0.75f));\r
261         h.setHint(RulerPainter.KEY_RULER_TEXT_COLOR, Color.BLACK);\r
262 \r
263         ////// Diagram Participants //////\r
264         ctx.add(new PointerInteractor(true, true, true, false, true, false, synchronizer.getElementClassProvider(), null));\r
265         ctx.add(new ElementInteractor());\r
266         ctx.add(new Selection());\r
267         ctx.add(new DiagramParticipant());\r
268         ctx.add(new ElementPainter());\r
269         ctx.add(new TerminalPainter(true, true, false, true));\r
270         //ctx.add(new ElementHeartbeater());\r
271         ctx.add(new ZOrderHandler());\r
272         ctx.add(new ZoomTransitionParticipant(TransitionFunction.SIGMOID));\r
273 \r
274         /////// D'n'D ///////\r
275         addDropParticipants(ctx);\r
276 \r
277         h.setHint(Hints.KEY_TOOL, Hints.POINTERTOOL);\r
278 \r
279         h.setHint(PanZoomRotateHandler.KEY_ZOOM_IN_LIMIT, 1000.0);\r
280         h.setHint(PanZoomRotateHandler.KEY_ZOOM_OUT_LIMIT, 10.0);\r
281 \r
282         // Add visual browsing capabilities for structural models\r
283 //        ctx.add(new HeadlessStructuralBrowsingHandler(this, sessionContext, structuralPath));\r
284 \r
285         // Page settings\r
286         PageDesc pageDesc = PageDesc.DEFAULT.withOrientation(PageOrientation.Landscape);\r
287         // TODO: load page desc from graph\r
288         h.setHint(Hints.KEY_PAGE_DESC, pageDesc);\r
289 \r
290         ctx.assertParticipantDependencies();\r
291 \r
292         return ctx;\r
293     }\r
294 \r
295     private boolean firstFocus = true;\r
296 \r
297     @Override\r
298     public void setFocus() {\r
299         if (firstFocus) {\r
300             // This is a workaround for using the symbol viewer in multi-page\r
301             // editors which causes the first zoom-to-fit scheduling to happen\r
302             // already before the controls have been laid out properly.\r
303             firstFocus = false;\r
304             firstTimeSetFocus();\r
305         }\r
306     }\r
307 \r
308     protected void firstTimeSetFocus() {\r
309         scheduleZoomToFit();\r
310     }\r
311 \r
312     @Override\r
313     public void dispose() {\r
314         System.out.println("RemoteDiagramViewer.dispose()");\r
315         if(getSite() != null) {\r
316             IContextService contextService = (IContextService) getSite().getService(IContextService.class);\r
317             contextService.deactivateContext(contextActivation);\r
318         }\r
319 \r
320         disposed = true;\r
321         if (activation != null) {\r
322             activation.deactivate();\r
323             activation = null;\r
324         }\r
325 \r
326         if(synchronizer != null) {\r
327             synchronizer.dispose();\r
328             synchronizer = null;\r
329         }\r
330 \r
331         if(sourceDiagram != null) {\r
332             sourceDiagram.dispose();\r
333             sourceDiagram = null;\r
334         }\r
335 \r
336         if(support != null) {\r
337             support.dispose();\r
338             support = null;\r
339         }\r
340         super.dispose();\r
341     }\r
342 \r
343     @Override\r
344     public void doSave(IProgressMonitor monitor) {\r
345     }\r
346 \r
347     @Override\r
348     public void doSaveAs() {\r
349     }\r
350 \r
351     @Override\r
352     public void init(IEditorSite site, IEditorInput input)\r
353     throws PartInitException {\r
354         if (!(input instanceof IResourceEditorInput))\r
355             throw new PartInitException("Invalid input: must be IResourceEditorInput");\r
356         setSite(site);\r
357         setInput(input);\r
358         support = new ResourceEditorSupport(this);\r
359 \r
360         // Set initial part name according to the name given by IEditorInput\r
361         setPartName(getEditorInput().getName());\r
362     }\r
363 \r
364     @Override\r
365     public boolean isDirty() {\r
366         return false;\r
367     }\r
368 \r
369     @Override\r
370     public boolean isSaveAsAllowed() {\r
371         return false;\r
372     }\r
373 \r
374     public static ResourceArray[] decodeToResources(Session session, Transferable tr)\r
375     {\r
376         try {\r
377             SerialisationSupport support = session.getService(SerialisationSupport.class);\r
378             ResourceTransferData data = ResourceTransferUtils.readAwtTransferable(support, tr);\r
379             if ("property".equals(data.getPurpose()))\r
380                 return data.toResourceArrayArray();\r
381         } catch (UnsupportedFlavorException e) {\r
382             throw new RuntimeException(e);\r
383         } catch (IOException e) {\r
384             throw new RuntimeException(e);\r
385         } catch (IllegalArgumentException e) {\r
386             throw new RuntimeException(e);\r
387         } catch (DatabaseException e) {\r
388             throw new RuntimeException(e);\r
389         }\r
390         return null;\r
391     }\r
392 \r
393     @SuppressWarnings("rawtypes")\r
394     @Override\r
395     public Object getAdapter(Class adapter) {\r
396         if (adapter == IContentOutlinePage.class)\r
397             return new DiagramOutlinePage(sessionContextProvider, getResourceInput2());\r
398         if (adapter == ILayersViewPage.class)\r
399             return new DiagramLayersPage(sourceDiagram, canvasContext);\r
400         if (adapter == ICanvasContext.class)\r
401             return canvasContext;\r
402         if (adapter == IDiagram.class)\r
403             return sourceDiagram;\r
404         if (adapter == Session.class)\r
405             return sessionContext.getSession();\r
406         return super.getAdapter(adapter);\r
407     }\r
408 \r
409     public ICanvasContext getCanvasContext() {\r
410         return canvasContext;\r
411     }\r
412 \r
413     protected void onCreated() {\r
414     }\r
415 \r
416     @Override\r
417     public void createPartControl(Composite parent) {\r
418         // TODO Auto-generated method stub\r
419 \r
420     }\r
421 \r
422     @Override\r
423     public IResourceEditorInput2 getResourceInput2() {\r
424         // TODO Auto-generated method stub\r
425         return null;\r
426     }\r
427 \r
428     @Override\r
429     public IResourceEditorInput getResourceInput() {\r
430         // TODO Auto-generated method stub\r
431         return null;\r
432     }\r
433 \r
434 }\r