]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/SheetViewer.java
Sync git svn branch with SVN repository r33406.
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / diagramEditor / SheetViewer.java
1 /*******************************************************************************\r
2  * Copyright (c) 2007, 2013 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  *     Semantum Oy - issue #4384\r
12  *******************************************************************************/\r
13 package org.simantics.modeling.ui.diagramEditor;\r
14 \r
15 import java.awt.Color;\r
16 import java.lang.reflect.InvocationTargetException;\r
17 import java.util.function.Supplier;\r
18 \r
19 import org.eclipse.core.runtime.IProgressMonitor;\r
20 import org.eclipse.core.runtime.SubMonitor;\r
21 import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;\r
22 import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;\r
23 import org.eclipse.jface.action.IStatusLineManager;\r
24 import org.eclipse.jface.operation.IRunnableWithProgress;\r
25 import org.eclipse.swt.widgets.Composite;\r
26 import org.eclipse.ui.IEditorInput;\r
27 import org.eclipse.ui.IEditorSite;\r
28 import org.eclipse.ui.PartInitException;\r
29 import org.eclipse.ui.PlatformUI;\r
30 import org.eclipse.ui.contexts.IContextService;\r
31 import org.eclipse.ui.part.EditorPart;\r
32 import org.eclipse.ui.views.contentoutline.IContentOutlinePage;\r
33 import org.simantics.db.ReadGraph;\r
34 import org.simantics.db.Resource;\r
35 import org.simantics.db.Session;\r
36 import org.simantics.db.common.ResourceArray;\r
37 import org.simantics.db.exception.DatabaseException;\r
38 import org.simantics.db.management.ISessionContext;\r
39 import org.simantics.db.management.ISessionContextProvider;\r
40 import org.simantics.db.request.Read;\r
41 import org.simantics.diagram.adapter.DefaultConnectionClassFactory;\r
42 import org.simantics.diagram.adapter.FlagClassFactory;\r
43 import org.simantics.diagram.adapter.GraphToDiagramSynchronizer;\r
44 import org.simantics.diagram.handler.ConnectionCommandHandler;\r
45 import org.simantics.diagram.handler.CopyPasteHandler;\r
46 import org.simantics.diagram.handler.DeleteHandler;\r
47 import org.simantics.diagram.handler.ExpandSelectionHandler;\r
48 import org.simantics.diagram.handler.SimpleElementTransformHandler;\r
49 import org.simantics.diagram.layer.ILayersViewPage;\r
50 import org.simantics.diagram.participant.ContextUtil;\r
51 import org.simantics.diagram.participant.SGFocusParticipant;\r
52 import org.simantics.diagram.query.DiagramRequests;\r
53 import org.simantics.diagram.stubs.DiagramResource;\r
54 import org.simantics.diagram.synchronization.IModifiableSynchronizationContext;\r
55 import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;\r
56 import org.simantics.diagram.ui.SWTPopupMenuParticipant;\r
57 import org.simantics.g2d.canvas.Hints;\r
58 import org.simantics.g2d.canvas.ICanvasContext;\r
59 import org.simantics.g2d.canvas.impl.CanvasContext;\r
60 import org.simantics.g2d.chassis.SWTChassis;\r
61 import org.simantics.g2d.diagram.DiagramClass;\r
62 import org.simantics.g2d.diagram.DiagramHints;\r
63 import org.simantics.g2d.diagram.IDiagram;\r
64 import org.simantics.g2d.diagram.impl.Diagram;\r
65 import org.simantics.g2d.diagram.participant.DiagramParticipant;\r
66 import org.simantics.g2d.diagram.participant.ElementInteractor;\r
67 import org.simantics.g2d.diagram.participant.ElementPainter;\r
68 import org.simantics.g2d.diagram.participant.Selection;\r
69 import org.simantics.g2d.diagram.participant.TerminalPainter;\r
70 import org.simantics.g2d.diagram.participant.ZOrderHandler;\r
71 import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;\r
72 import org.simantics.g2d.element.ElementClassProviders;\r
73 import org.simantics.g2d.element.ElementClasses;\r
74 import org.simantics.g2d.element.IElementClassProvider;\r
75 import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
76 import org.simantics.g2d.participant.CanvasBoundsParticipant;\r
77 import org.simantics.g2d.participant.CanvasGrab;\r
78 import org.simantics.g2d.participant.KeyUtil;\r
79 import org.simantics.g2d.participant.MouseUtil;\r
80 import org.simantics.g2d.participant.MultitouchPanZoomRotateInteractor;\r
81 import org.simantics.g2d.participant.Notifications;\r
82 import org.simantics.g2d.participant.PageBorderParticipant;\r
83 import org.simantics.g2d.participant.PanZoomRotateHandler;\r
84 import org.simantics.g2d.participant.PointerPainter;\r
85 import org.simantics.g2d.participant.RulerPainter;\r
86 import org.simantics.g2d.participant.SymbolUtil;\r
87 import org.simantics.g2d.participant.TimeParticipant;\r
88 import org.simantics.g2d.participant.TransformUtil;\r
89 import org.simantics.g2d.participant.ZoomToAreaHandler;\r
90 import org.simantics.layer0.utils.triggers.IActivation;\r
91 import org.simantics.layer0.utils.triggers.IActivationManager;\r
92 import org.simantics.modeling.ModelingResources;\r
93 import org.simantics.modeling.mapping.ModelingSynchronizationHints;\r
94 import org.simantics.modeling.ui.diagramEditor.handlers.WorkbenchStructuralSelectionProvider;\r
95 import org.simantics.modeling.ui.preferences.DiagramPreferenceUtil;\r
96 import org.simantics.modeling.ui.preferences.DiagramPreferences;\r
97 import org.simantics.scenegraph.INode;\r
98 import org.simantics.scenegraph.g2d.snap.GridSnapAdvisor;\r
99 import org.simantics.scenegraph.utils.NodeUtil;\r
100 import org.simantics.selectionview.StandardPropertyPage;\r
101 import org.simantics.ui.SimanticsUI;\r
102 import org.simantics.ui.workbench.IPropertyPage;\r
103 import org.simantics.ui.workbench.IResourceEditorInput;\r
104 import org.simantics.ui.workbench.IResourceEditorInput2;\r
105 import org.simantics.ui.workbench.IResourceEditorPart2;\r
106 import org.simantics.ui.workbench.ResourceEditorSupport;\r
107 import org.simantics.ui.workbench.TitleRequest;\r
108 import org.simantics.ui.workbench.TitleUpdater;\r
109 import org.simantics.ui.workbench.ToolTipRequest;\r
110 import org.simantics.utils.DataContainer;\r
111 import org.simantics.utils.datastructures.hints.IHintContext;\r
112 import org.simantics.utils.page.PageDesc;\r
113 import org.simantics.utils.threads.AWTThread;\r
114 import org.simantics.utils.threads.IThreadWorkQueue;\r
115 import org.simantics.utils.threads.SWTThread;\r
116 import org.simantics.utils.threads.ThreadUtils;\r
117 import org.simantics.utils.ui.ErrorLogger;\r
118 \r
119 /**\r
120  * @author Toni Kalajainen\r
121  * @author Tuukka Lehtonen\r
122  */\r
123 public class SheetViewer extends EditorPart implements IResourceEditorPart2 {\r
124 \r
125     private static final boolean         PROFILE            = false;\r
126 \r
127     protected boolean                    disposed           = false;\r
128     protected IThreadWorkQueue           swt;\r
129     protected IStatusLineManager         statusLineManager;\r
130     protected SWTChassis                 c;\r
131     protected IDiagram                   sourceDiagram;\r
132     protected ICanvasContext             canvasContext;\r
133     protected ResourceEditorSupport      support;\r
134     protected ISessionContextProvider    sessionContextProvider;\r
135     protected ISessionContext            sessionContext;\r
136     protected Resource                   diagramResource;\r
137     protected GraphToDiagramSynchronizer synchronizer;\r
138     protected IActivation                activation;\r
139     protected ContextUtil                contextUtil;\r
140 \r
141     protected DiagramPreferences         diagramPreferences;\r
142     protected GridSnapAdvisor            snapAdvisor;\r
143 \r
144     public ResourceArray                 structuralPath;\r
145 \r
146     IPreferenceChangeListener preferenceListener = new IPreferenceChangeListener() {\r
147         @Override\r
148         public void preferenceChange(PreferenceChangeEvent event) {\r
149             String value = (String) event.getNewValue();\r
150             if (DiagramPreferences.P_SNAP_GRID_SIZE.equals(event.getKey())) {\r
151                 double grid = DiagramPreferences.DEFAULT_SNAP_GRID_SIZE;\r
152                 if (value != null)\r
153                     grid = Double.parseDouble(value);\r
154                 snapAdvisor.setResolution(grid);\r
155             } else if (DiagramPreferences.P_DEFAULT_PAGE_SIZE.equals(event.getKey())) {\r
156                 PageDesc pageDesc = PageDesc.deserialize(value, DiagramPreferences.DEFAULT_PAGE_SIZE);\r
157                 //System.out.println("new page desc: " + pageDesc);\r
158                 canvasContext.getDefaultHintContext().setHint(Hints.KEY_PAGE_DESC, pageDesc);\r
159             } else if (DiagramPreferences.P_DISPLAY_PAGE_SIZE.equals(event.getKey())) {\r
160                 Boolean display = value != null ? Boolean.parseBoolean(value) : DiagramPreferences.DEFAULT_DISPLAY_PAGE_SIZE;\r
161                 canvasContext.getDefaultHintContext().setHint(Hints.KEY_DISPLAY_PAGE, display);\r
162             } else if (DiagramPreferences.P_DISPLAY_MARGINS.equals(event.getKey())) {\r
163                 Boolean display = value != null ? Boolean.parseBoolean(value) : DiagramPreferences.DEFAULT_DISPLAY_MARGINS;\r
164                 canvasContext.getDefaultHintContext().setHint(Hints.KEY_DISPLAY_MARGINS, display);\r
165             }\r
166         }\r
167     };\r
168 \r
169     protected void addDropParticipants(ICanvasContext ctx) {\r
170         // FIXME This is a workaround so that this participant can be disabled\r
171         // for SymbolViewer\r
172         ctx.add(new PopulateElementDropParticipant(synchronizer));\r
173         ctx.add(new PopulateElementMonitorDropParticipant(synchronizer, 0.5, 0.5));\r
174     }\r
175 \r
176     protected void addKeyBindingParticipants(CanvasContext ctx) {\r
177         //ctx.add( new KeyToCommand( CommandKeyBinding.DEFAULT_BINDINGS ) );\r
178         ctx.add(new DeleteHandler(statusLineManager));\r
179         ctx.add(new CopyPasteHandler(statusLineManager));\r
180         ctx.add(new ConnectionCommandHandler());\r
181     }\r
182 \r
183     protected void addPopupmenu(ICanvasContext ctx) {\r
184         ctx.add(new SWTPopupMenuParticipant(getSite(), c, getPopupId()));\r
185     }\r
186 \r
187     protected void addStructureParticipants(ICanvasContext ctx) {\r
188         structuralPath = getResourceInput().getResourceArray().removeFromBeginning(1);\r
189 \r
190         ctx.add(new WorkbenchStructuralSelectionProvider(swt, getSite(), structuralPath));\r
191         // Add visual browsing capabilities for structural models\r
192 //        ctx.add(new StructuralBrowsingHandler(getSite(), sessionContext, structuralPath));\r
193 //        ctx.add(new LinkBrowsingHandler(getSite(), this, sessionContext));\r
194     }\r
195 \r
196     protected String getPopupId() {\r
197         return "#ModelingDiagramPopup";\r
198     }\r
199 \r
200     protected void getPreferences() {\r
201         this.diagramPreferences = DiagramPreferenceUtil.getPreferences();\r
202     }\r
203 \r
204     protected void initSession() {\r
205         sessionContextProvider = SimanticsUI.getSessionContextProvider();\r
206         sessionContext = sessionContextProvider.getSessionContext();\r
207     }\r
208 \r
209     protected void readNames() {\r
210         String name = getEditorInput().getName();\r
211         setPartName(name);\r
212         setTitleToolTip(name);\r
213     }\r
214 \r
215     protected void createChassis(Composite parent) {\r
216         c = new SWTChassis(parent, 0);\r
217         c.syncPopulate();\r
218     }\r
219 \r
220     protected void setCanvasContext(ICanvasContext context) {\r
221         c.setCanvasContext(canvasContext);\r
222     }\r
223 \r
224     @Override\r
225     public void createPartControl(Composite parent) {\r
226         swt = SWTThread.getThreadAccess(parent.getDisplay());\r
227         statusLineManager = getEditorSite().getActionBars().getStatusLineManager();\r
228 \r
229         Object task = BEGIN("DV.initSession");\r
230         initSession();\r
231         END(task);\r
232 \r
233         diagramResource = getInputResource();\r
234         readNames();\r
235         getPreferences();\r
236 \r
237         task = BEGIN("DV.createChassis");\r
238         createChassis(parent);\r
239         END(task);\r
240 \r
241         initializeCanvas();\r
242 \r
243         // Start tracking changes in diagram preferences.\r
244         diagramPreferences.preferences.addPreferenceChangeListener(preferenceListener);\r
245     }\r
246 \r
247     protected void initializeCanvas() {\r
248         Object canvasInit = BEGIN("DV.canvasInitialization");\r
249 \r
250         Object task = BEGIN("DV.createViewerCanvas");\r
251 //        ThreadUtils.syncExec(AWTThread.getThreadAccess(), new Runnable() {\r
252 //            @Override\r
253 //            public void run() {\r
254         canvasContext = createViewerCanvas();\r
255 //            }\r
256 //        });\r
257         END(task);\r
258 \r
259         //FullscreenUtils.addFullScreenHandler(canvasContext, s, canvasProvider);\r
260 \r
261         task = BEGIN("DV.setCanvasContext");\r
262         setCanvasContext(canvasContext);\r
263         END(task);\r
264 \r
265         try {\r
266             task = BEGIN("DV.loadDiagram");\r
267             sourceDiagram = loadDiagram(diagramResource);\r
268             END(task);\r
269 \r
270             // Zoom to fit\r
271             task = BEGIN("DV.scheduleZoomToFit");\r
272 \r
273 //            canvasContext.getDefaultHintContext().setHint(Hints.KEY_CANVAS_TRANSFORM, new AffineTransform());\r
274 //            canvasContext.getContentContext().setDirty();\r
275             scheduleZoomToFit();\r
276 \r
277             END(task);\r
278 \r
279             // Start an activation for the input resource.\r
280             // This will activate mapping if necessary.\r
281             task = BEGIN("DV.performActivation");\r
282             performActivation();\r
283             END(task);\r
284 \r
285             task = BEGIN("DV.activate context");\r
286             contextUtil.activate(DiagramViewer.DIAGRAMMING_CONTEXT);\r
287             END(task);\r
288 \r
289             task = BEGIN("DV.onCreated");\r
290             onCreated();\r
291             END(task);\r
292 \r
293         } catch (DatabaseException e) {\r
294             ErrorLogger.defaultLogError(e);\r
295 \r
296             // Without this all diagram participants will crash like there's no tomorrow.\r
297             // Just trying to keep the behavior a bit more sane in case of\r
298             // errors instead of flooding the console with exceptions.\r
299             canvasContext.getDefaultHintContext().setHint(DiagramHints.KEY_DIAGRAM, Diagram.spawnNew(DiagramClass.DEFAULT));\r
300         }\r
301         END(canvasInit);\r
302     }\r
303 \r
304     protected void performActivation() {\r
305 \r
306         IActivationManager activationManager = sessionContext.getSession().peekService(IActivationManager.class);\r
307         if (activationManager != null) {\r
308             activation = activationManager.activate(diagramResource);\r
309         }\r
310 \r
311     }\r
312 \r
313     protected void scheduleZoomToFit() {\r
314         if (sourceDiagram == null)\r
315             throw new IllegalStateException("source diagram is null");\r
316 \r
317         sourceDiagram.setHint(Hints.KEY_DISABLE_PAINTING, Boolean.TRUE);\r
318         sourceDiagram.setHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT, Boolean.TRUE);\r
319         ThreadUtils.asyncExec(swt, new Runnable() {\r
320             @Override\r
321             public void run() {\r
322                 if (disposed)\r
323                     return;\r
324 \r
325                 // System.out.println("size: " + c.getSize());\r
326                 ThreadUtils.asyncExec(canvasContext.getThreadAccess(), new Runnable() {\r
327                     @Override\r
328                     public void run() {\r
329                         if (disposed)\r
330                             return;\r
331                         // System.out.println("fit diagram to view");\r
332                         sourceDiagram.removeHint(Hints.KEY_DISABLE_PAINTING);\r
333                         /*Boolean zoomToFit =*/ sourceDiagram.removeHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT);\r
334                         canvasContext.getDefaultHintContext().removeHint(Hints.KEY_DISABLE_PAINTING);\r
335 \r
336 //                        if (Boolean.TRUE.equals(zoomToFit))\r
337 //                            CanvasUtils.sendCommand(canvasContext, Commands.ZOOM_TO_FIT);\r
338 \r
339                         canvasContext.getContentContext().setDirty();\r
340                     }\r
341                 });\r
342             }\r
343         });\r
344     }\r
345 \r
346 \r
347 \r
348     protected IDiagram loadDiagram(final Resource r) throws DatabaseException {\r
349         final DataContainer<IDiagram> dc = new DataContainer<IDiagram>();\r
350         //dc.set( loadDiagram(new NullProgressMonitor(), r) );\r
351         try {\r
352             PlatformUI.getWorkbench().getProgressService().busyCursorWhile(new IRunnableWithProgress() {\r
353                 @Override\r
354                 public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {\r
355                     SubMonitor mon = SubMonitor.convert(monitor, "Loading Diagram", 100);\r
356                     try {\r
357                         dc.set( loadDiagram(mon.newChild(100), r) );\r
358                     } catch (DatabaseException e) {\r
359                         throw new InvocationTargetException(e);\r
360                     } finally {\r
361                         monitor.done();\r
362                     }\r
363                 }\r
364             });\r
365         } catch (InvocationTargetException e) {\r
366             Throwable t = e.getTargetException();\r
367             if (t instanceof DatabaseException)\r
368                 throw (DatabaseException) t;\r
369             throw new DatabaseException(t);\r
370         } catch (InterruptedException e) {\r
371             throw new DatabaseException(e);\r
372         }\r
373         return dc.get();\r
374     }\r
375 \r
376     protected IDiagram loadDiagram(IProgressMonitor monitor, Resource r) throws DatabaseException {\r
377         SubMonitor mon = SubMonitor.convert(monitor, "Loading Diagram", 100);\r
378 \r
379         Object task = BEGIN("DV.DiagramLoadQuery");\r
380         IDiagram d = sessionContext.getSession().syncRequest(DiagramRequests.loadDiagram(mon.newChild(100), getResourceInput2().getModel(null), r, null, structuralPath, synchronizer, null));\r
381         END(task);\r
382 \r
383         task = BEGIN("DV.setDiagramHint");\r
384         canvasContext.getDefaultHintContext().setHint(DiagramHints.KEY_DIAGRAM, d);\r
385         END(task);\r
386 \r
387         task = BEGIN("DV.set other hints");\r
388         // Setup a copy advisor for the synchronizer\r
389         //d.setHint(SynchronizationHints.COPY_ADVISOR, new MappedElementCopyAdvisor(new ComponentCopyAdvisor()));\r
390         d.setHint(DiagramHints.KEY_USE_CONNECTION_FLAGS, Boolean.FALSE);\r
391         d.setHint(DiagramHints.KEY_ALLOW_CONNECTION_BRANCHING, Boolean.FALSE);\r
392         d.setHint(DiagramHints.KEY_ALLOW_ROUTE_POINTS, Boolean.FALSE);\r
393         END(task);\r
394 \r
395         return d;\r
396     }\r
397 \r
398     protected GraphToDiagramSynchronizer createSynchronizer(final ICanvasContext ctx, final ISessionContext sessionContext) {\r
399         try {\r
400             return sessionContext.getSession().syncRequest(new Read<GraphToDiagramSynchronizer>() {\r
401                 @Override\r
402                 public GraphToDiagramSynchronizer perform(ReadGraph graph) throws DatabaseException {\r
403                     GraphToDiagramSynchronizer sync = new GraphToDiagramSynchronizer(graph, ctx, createElementClassProvider(graph));\r
404                     initializeSynchronizationContext(graph, sync);\r
405                     return sync;\r
406                 }\r
407             });\r
408         } catch (DatabaseException e) {\r
409             throw new UnsupportedOperationException("Failed to initialize data model synchronizer", e);\r
410         }\r
411     }\r
412 \r
413     protected void initializeSynchronizationContext(ReadGraph graph, IModifiableSynchronizationContext context) {\r
414         context.set(ModelingSynchronizationHints.MODELING_RESOURCE, ModelingResources.getInstance(graph));\r
415     }\r
416 \r
417     protected IElementClassProvider createElementClassProvider(ReadGraph graph) {\r
418         DiagramResource dr = DiagramResource.getInstance(graph);\r
419         return ElementClassProviders.mappedProvider(\r
420                 ElementClasses.CONNECTION, DefaultConnectionClassFactory.CLASS.newClassWith(new StaticObjectAdapter(dr.Connection)),\r
421                 ElementClasses.FLAG, FlagClassFactory.createFlagClass(dr.Flag, dr.Flag_Terminal)\r
422         );\r
423     }\r
424 \r
425     public ICanvasContext createViewerCanvas() {\r
426         IThreadWorkQueue thread = AWTThread.getThreadAccess();\r
427         CanvasContext ctx = new CanvasContext(thread);\r
428         IHintContext h = ctx.getDefaultHintContext();\r
429 \r
430         Object task = BEGIN("createSynchronizer");\r
431         this.synchronizer = createSynchronizer(ctx, sessionContext);\r
432         END(task);\r
433 \r
434         IContextService contextService = (IContextService) getSite().getService(IContextService.class);\r
435         contextUtil = new ContextUtil(contextService, swt);\r
436 \r
437         ctx.add(new PanZoomRotateHandler()); // Must be before TransformUtil\r
438 \r
439         // Support & Util Participants\r
440         ctx.add(new TransformUtil());\r
441         ctx.add(new MouseUtil());\r
442         ctx.add(new KeyUtil());\r
443         ctx.add(contextUtil);\r
444         ctx.add(new CanvasGrab());\r
445         ctx.add(new SymbolUtil());\r
446         ctx.add(new TimeParticipant());\r
447         ctx.add(new CanvasBoundsParticipant());\r
448         ctx.add(new Notifications());\r
449 \r
450         ctx.add( new SGFocusParticipant(c, DiagramViewer.DIAGRAMMING_CONTEXT) );\r
451 \r
452         // Debug participant(s)\r
453         // ctx.add( new PointerPainter() );\r
454         // ctx.add( new HandPainter() );\r
455         h.setHint(PointerPainter.KEY_PAINT_POINTER, true);\r
456 \r
457         // Pan & Zoom & Rotate\r
458         ctx.add(new MultitouchPanZoomRotateInteractor());\r
459         // ctx.add( new OrientationRestorer() );\r
460         ctx.add(new ZoomToAreaHandler());\r
461         ctx.add(new SimpleElementTransformHandler(true, true, true));\r
462         ctx.add(new ExpandSelectionHandler(getEditorSite().getActionBars().getStatusLineManager()));\r
463 \r
464         // Key bindings\r
465         addKeyBindingParticipants(ctx);\r
466 \r
467         // Grid & Ruler & Background\r
468 //        ctx.add(new GridPainter());\r
469 //        ctx.add(new RulerPainter());\r
470 //        ctx.add(new BackgroundPainter());\r
471 \r
472 \r
473         h.setHint(PanZoomRotateHandler.KEY_ADAPT_VIEWPORT_TO_RESIZED_CONTROL, Boolean.FALSE);\r
474         h.setHint(Hints.KEY_DISPLAY_PAGE, diagramPreferences.get(DiagramPreferences.P_DISPLAY_PAGE_SIZE));\r
475         h.setHint(Hints.KEY_DISPLAY_MARGINS, diagramPreferences.get(DiagramPreferences.P_DISPLAY_MARGINS));\r
476         ctx.add(new PageBorderParticipant());\r
477 \r
478         // h.setHint(Hints.KEY_GRID_COLOR, new Color(0.9f, 0.9f, 0.9f));\r
479         // h.setHint(Hints.KEY_BACKGROUND_COLOR, Color.LIGHT_GRAY);\r
480         h.setHint(Hints.KEY_GRID_COLOR, new Color(0.95f, 0.95f, 0.95f));\r
481         h.setHint(Hints.KEY_BACKGROUND_COLOR, Color.WHITE);\r
482         h.setHint(RulerPainter.KEY_RULER_BACKGROUND_COLOR, new Color(0.9f, 0.9f, 0.9f, 0.75f));\r
483         h.setHint(RulerPainter.KEY_RULER_TEXT_COLOR, Color.BLACK);\r
484 \r
485         ////// Diagram Participants //////\r
486         ctx.add(new ZOrderHandler());\r
487         ctx.add(new PointerInteractor(true, true, true, false, true, false, synchronizer.getElementClassProvider(), null));\r
488         ctx.add(new ElementInteractor());\r
489         ctx.add(new Selection());\r
490         ctx.add(new DiagramParticipant());\r
491         ctx.add(new ElementPainter());\r
492         ctx.add(new TerminalPainter(true, true, false, true));\r
493         //ctx.add(new ElementHeartbeater());\r
494 //        ctx.add(new ZoomTransitionParticipant(TransitionFunction.SIGMOID));\r
495 \r
496         /////// D'n'D ///////\r
497         addDropParticipants(ctx);\r
498 \r
499         h.setHint(ElementPainter.KEY_SELECTION_FRAME_COLOR, Color.MAGENTA);\r
500         h.setHint(Hints.KEY_TOOL, Hints.POINTERTOOL);\r
501 \r
502         h.setHint(PanZoomRotateHandler.KEY_ZOOM_IN_LIMIT, 100000.0);\r
503         h.setHint(PanZoomRotateHandler.KEY_ZOOM_OUT_LIMIT, 10.0);\r
504 \r
505         Double snapResolution = diagramPreferences.get(DiagramPreferences.P_SNAP_GRID_SIZE);\r
506         this.snapAdvisor = new GridSnapAdvisor(snapResolution);\r
507         h.setHint(DiagramHints.SNAP_ADVISOR, this.snapAdvisor);\r
508 \r
509         // Workbench selection provider\r
510         addStructureParticipants(ctx);\r
511 \r
512         // Pop-up menu\r
513         addPopupmenu(ctx);\r
514 \r
515         // Load page frame description settings\r
516         loadPageSettings(ctx);\r
517 \r
518         // The canvas context should not be painted until it is ready to avoid\r
519         // unnecessary visual glitches.\r
520         h.setHint(Hints.KEY_DISABLE_PAINTING, Boolean.TRUE);\r
521 \r
522         ctx.assertParticipantDependencies();\r
523 \r
524         return ctx;\r
525     }\r
526 \r
527     protected void loadPageSettings(ICanvasContext ctx) {\r
528         PageDesc pageDesc = null;\r
529 \r
530         if (diagramResource != null) {\r
531             try {\r
532                 pageDesc = sessionContext.getSession().syncRequest(new Read<PageDesc>() {\r
533                     @Override\r
534                     public PageDesc perform(ReadGraph graph) throws DatabaseException {\r
535                         return DiagramGraphUtil.getPageDesc(graph, diagramResource, null);\r
536                     }\r
537                 });\r
538             } catch (DatabaseException e) {\r
539                 ErrorLogger.defaultLogError(e);\r
540             }\r
541         }\r
542 \r
543         if (pageDesc == null) {\r
544             // Take page description from the preferences if nothing else is available.\r
545             PageDesc pd = diagramPreferences.getCompletePageDesc();\r
546             pageDesc = pd;\r
547         }\r
548         ctx.getDefaultHintContext().setHint(Hints.KEY_PAGE_DESC, pageDesc);\r
549     }\r
550 \r
551     private boolean firstFocus = true;\r
552 \r
553     @Override\r
554     public void setFocus() {\r
555         c.setFocus();\r
556 \r
557         if (firstFocus) {\r
558             // This is a workaround for using the symbol viewer in multi-page\r
559             // editors which causes the first zoom-to-fit scheduling to happen\r
560             // already before the controls have been laid out properly.\r
561             firstFocus = false;\r
562             firstTimeSetFocus();\r
563         }\r
564     }\r
565 \r
566     protected void firstTimeSetFocus() {\r
567         //scheduleZoomToFit();\r
568     }\r
569 \r
570     @Override\r
571     public void dispose() {\r
572         // Remember to remove the added preference change listener\r
573         diagramPreferences.preferences.removePreferenceChangeListener(preferenceListener);\r
574 \r
575         // Deactivate all contexts here because after this the context service\r
576         // in question will not be available.\r
577         contextUtil.deactivateAll();\r
578 \r
579         disposed = true;\r
580         if (activation != null) {\r
581             activation.deactivate();\r
582             activation = null;\r
583         }\r
584         synchronizer.dispose();\r
585         ThreadUtils.asyncExec(c.getCanvasContext().getThreadAccess(), new Runnable() {\r
586             @Override\r
587             public void run() {\r
588                 c.getCanvasContext().dispose();\r
589             }\r
590         });\r
591         sourceDiagram.dispose();\r
592         support.dispose();\r
593         super.dispose();\r
594     }\r
595 \r
596     protected Resource getInputResource() {\r
597         return getResourceInput().getResource();\r
598     }\r
599 \r
600     @Override\r
601     public IResourceEditorInput2 getResourceInput2() {\r
602         return (IResourceEditorInput2) getEditorInput();\r
603     }\r
604 \r
605     @Override\r
606     public IResourceEditorInput getResourceInput() {\r
607         return (IResourceEditorInput) getEditorInput();\r
608     }\r
609 \r
610     @Override\r
611     public void doSave(IProgressMonitor monitor) {\r
612     }\r
613 \r
614     @Override\r
615     public void doSaveAs() {\r
616     }\r
617 \r
618     @Override\r
619     public void init(IEditorSite site, IEditorInput input) throws PartInitException {\r
620         if (!(input instanceof IResourceEditorInput))\r
621             throw new PartInitException("Invalid input: must be IResourceEditorInput");\r
622         setSite(site);\r
623         setInput(input);\r
624         support = new ResourceEditorSupport(this);\r
625 \r
626         // Set initial part name according to the name given by IEditorInput\r
627         setPartName(getEditorInput().getName());\r
628 \r
629         Session session = SimanticsUI.peekSession();\r
630         if (session != null) {\r
631             Supplier<Boolean> disposedCallback = () -> disposed;\r
632             session.asyncRequest(\r
633                     new TitleRequest(site.getId(), getResourceInput2()),\r
634                     new TitleUpdater(site.getShell().getDisplay(), this::setPartName, disposedCallback));\r
635             session.asyncRequest(\r
636                     new ToolTipRequest(site.getId(), getResourceInput2()),\r
637                     new TitleUpdater(site.getShell().getDisplay(), this::setTitleToolTip, disposedCallback));\r
638         }\r
639 \r
640     }\r
641 \r
642     @Override\r
643     public boolean isDirty() {\r
644         return false;\r
645     }\r
646 \r
647     @Override\r
648     public boolean isSaveAsAllowed() {\r
649         return false;\r
650     }\r
651 \r
652     @SuppressWarnings("unchecked")\r
653     @Override\r
654     public <T> T getAdapter(Class<T> adapter) {\r
655         if (adapter == IPropertyPage.class)\r
656             return (T) new StandardPropertyPage(getSite());\r
657         if (adapter == IContentOutlinePage.class)\r
658             return (T) new DiagramOutlinePage(sessionContextProvider, getResourceInput2());\r
659         if (adapter == ILayersViewPage.class)\r
660             return (T) new DiagramLayersPage(sourceDiagram, canvasContext);\r
661         if (adapter == ICanvasContext.class)\r
662             return (T) canvasContext;\r
663         if (adapter == INode.class) {\r
664             if (canvasContext != null) {\r
665                 INode node = canvasContext.getCanvasNode();\r
666                 if (node != null)\r
667                     return (T) NodeUtil.getRootNode(node);\r
668             }\r
669             return null;\r
670         }\r
671         if (adapter == IDiagram.class)\r
672             return (T) sourceDiagram;\r
673         if (adapter == Session.class)\r
674             return (T) sessionContext.getSession();\r
675         return super.getAdapter(adapter);\r
676     }\r
677 \r
678     protected void onCreated() {\r
679     }\r
680 \r
681 \r
682     private static Object BEGIN(String name) {\r
683         if (PROFILE) {\r
684             //return ThreadLog.BEGIN(name);\r
685         }\r
686         return null;\r
687     }\r
688 \r
689     private static void END(Object task) {\r
690         if (PROFILE) {\r
691             //((Task) task).end();\r
692         }\r
693     }\r
694 \r
695 }\r