]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/SheetViewer.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / diagramEditor / SheetViewer.java
index b35d537dc3b94a91af8dcd01dcbd1c9268714193..fbe48fbe2ec4aebcde60801b4be7acd5a867f05f 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2007, 2013 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *     Semantum Oy - issue #4384\r
- *******************************************************************************/\r
-package org.simantics.modeling.ui.diagramEditor;\r
-\r
-import java.awt.Color;\r
-import java.lang.reflect.InvocationTargetException;\r
-import java.util.function.Supplier;\r
-\r
-import org.eclipse.core.runtime.IProgressMonitor;\r
-import org.eclipse.core.runtime.SubMonitor;\r
-import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;\r
-import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;\r
-import org.eclipse.jface.action.IStatusLineManager;\r
-import org.eclipse.jface.operation.IRunnableWithProgress;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.ui.IEditorInput;\r
-import org.eclipse.ui.IEditorSite;\r
-import org.eclipse.ui.PartInitException;\r
-import org.eclipse.ui.PlatformUI;\r
-import org.eclipse.ui.contexts.IContextService;\r
-import org.eclipse.ui.part.EditorPart;\r
-import org.eclipse.ui.views.contentoutline.IContentOutlinePage;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.common.ResourceArray;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.management.ISessionContext;\r
-import org.simantics.db.management.ISessionContextProvider;\r
-import org.simantics.db.request.Read;\r
-import org.simantics.diagram.adapter.DefaultConnectionClassFactory;\r
-import org.simantics.diagram.adapter.FlagClassFactory;\r
-import org.simantics.diagram.adapter.GraphToDiagramSynchronizer;\r
-import org.simantics.diagram.handler.ConnectionCommandHandler;\r
-import org.simantics.diagram.handler.CopyPasteHandler;\r
-import org.simantics.diagram.handler.DeleteHandler;\r
-import org.simantics.diagram.handler.ExpandSelectionHandler;\r
-import org.simantics.diagram.handler.SimpleElementTransformHandler;\r
-import org.simantics.diagram.layer.ILayersViewPage;\r
-import org.simantics.diagram.participant.ContextUtil;\r
-import org.simantics.diagram.participant.SGFocusParticipant;\r
-import org.simantics.diagram.query.DiagramRequests;\r
-import org.simantics.diagram.stubs.DiagramResource;\r
-import org.simantics.diagram.synchronization.IModifiableSynchronizationContext;\r
-import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;\r
-import org.simantics.diagram.ui.SWTPopupMenuParticipant;\r
-import org.simantics.g2d.canvas.Hints;\r
-import org.simantics.g2d.canvas.ICanvasContext;\r
-import org.simantics.g2d.canvas.impl.CanvasContext;\r
-import org.simantics.g2d.chassis.SWTChassis;\r
-import org.simantics.g2d.diagram.DiagramClass;\r
-import org.simantics.g2d.diagram.DiagramHints;\r
-import org.simantics.g2d.diagram.IDiagram;\r
-import org.simantics.g2d.diagram.impl.Diagram;\r
-import org.simantics.g2d.diagram.participant.DiagramParticipant;\r
-import org.simantics.g2d.diagram.participant.ElementInteractor;\r
-import org.simantics.g2d.diagram.participant.ElementPainter;\r
-import org.simantics.g2d.diagram.participant.Selection;\r
-import org.simantics.g2d.diagram.participant.TerminalPainter;\r
-import org.simantics.g2d.diagram.participant.ZOrderHandler;\r
-import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;\r
-import org.simantics.g2d.element.ElementClassProviders;\r
-import org.simantics.g2d.element.ElementClasses;\r
-import org.simantics.g2d.element.IElementClassProvider;\r
-import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
-import org.simantics.g2d.participant.CanvasBoundsParticipant;\r
-import org.simantics.g2d.participant.CanvasGrab;\r
-import org.simantics.g2d.participant.KeyUtil;\r
-import org.simantics.g2d.participant.MouseUtil;\r
-import org.simantics.g2d.participant.MultitouchPanZoomRotateInteractor;\r
-import org.simantics.g2d.participant.Notifications;\r
-import org.simantics.g2d.participant.PageBorderParticipant;\r
-import org.simantics.g2d.participant.PanZoomRotateHandler;\r
-import org.simantics.g2d.participant.PointerPainter;\r
-import org.simantics.g2d.participant.RulerPainter;\r
-import org.simantics.g2d.participant.SymbolUtil;\r
-import org.simantics.g2d.participant.TimeParticipant;\r
-import org.simantics.g2d.participant.TransformUtil;\r
-import org.simantics.g2d.participant.ZoomToAreaHandler;\r
-import org.simantics.layer0.utils.triggers.IActivation;\r
-import org.simantics.layer0.utils.triggers.IActivationManager;\r
-import org.simantics.modeling.ModelingResources;\r
-import org.simantics.modeling.mapping.ModelingSynchronizationHints;\r
-import org.simantics.modeling.ui.diagramEditor.handlers.WorkbenchStructuralSelectionProvider;\r
-import org.simantics.modeling.ui.preferences.DiagramPreferenceUtil;\r
-import org.simantics.modeling.ui.preferences.DiagramPreferences;\r
-import org.simantics.scenegraph.INode;\r
-import org.simantics.scenegraph.g2d.snap.GridSnapAdvisor;\r
-import org.simantics.scenegraph.utils.NodeUtil;\r
-import org.simantics.selectionview.StandardPropertyPage;\r
-import org.simantics.ui.SimanticsUI;\r
-import org.simantics.ui.workbench.IPropertyPage;\r
-import org.simantics.ui.workbench.IResourceEditorInput;\r
-import org.simantics.ui.workbench.IResourceEditorInput2;\r
-import org.simantics.ui.workbench.IResourceEditorPart2;\r
-import org.simantics.ui.workbench.ResourceEditorSupport;\r
-import org.simantics.ui.workbench.TitleRequest;\r
-import org.simantics.ui.workbench.TitleUpdater;\r
-import org.simantics.ui.workbench.ToolTipRequest;\r
-import org.simantics.utils.DataContainer;\r
-import org.simantics.utils.datastructures.hints.IHintContext;\r
-import org.simantics.utils.page.PageDesc;\r
-import org.simantics.utils.threads.AWTThread;\r
-import org.simantics.utils.threads.IThreadWorkQueue;\r
-import org.simantics.utils.threads.SWTThread;\r
-import org.simantics.utils.threads.ThreadUtils;\r
-import org.simantics.utils.ui.ErrorLogger;\r
-\r
-/**\r
- * @author Toni Kalajainen\r
- * @author Tuukka Lehtonen\r
- */\r
-public class SheetViewer extends EditorPart implements IResourceEditorPart2 {\r
-\r
-    private static final boolean         PROFILE            = false;\r
-\r
-    protected boolean                    disposed           = false;\r
-    protected IThreadWorkQueue           swt;\r
-    protected IStatusLineManager         statusLineManager;\r
-    protected SWTChassis                 c;\r
-    protected IDiagram                   sourceDiagram;\r
-    protected ICanvasContext             canvasContext;\r
-    protected ResourceEditorSupport      support;\r
-    protected ISessionContextProvider    sessionContextProvider;\r
-    protected ISessionContext            sessionContext;\r
-    protected Resource                   diagramResource;\r
-    protected GraphToDiagramSynchronizer synchronizer;\r
-    protected IActivation                activation;\r
-    protected ContextUtil                contextUtil;\r
-\r
-    protected DiagramPreferences         diagramPreferences;\r
-    protected GridSnapAdvisor            snapAdvisor;\r
-\r
-    public ResourceArray                 structuralPath;\r
-\r
-    IPreferenceChangeListener preferenceListener = new IPreferenceChangeListener() {\r
-        @Override\r
-        public void preferenceChange(PreferenceChangeEvent event) {\r
-            String value = (String) event.getNewValue();\r
-            if (DiagramPreferences.P_SNAP_GRID_SIZE.equals(event.getKey())) {\r
-                double grid = DiagramPreferences.DEFAULT_SNAP_GRID_SIZE;\r
-                if (value != null)\r
-                    grid = Double.parseDouble(value);\r
-                snapAdvisor.setResolution(grid);\r
-            } else if (DiagramPreferences.P_DEFAULT_PAGE_SIZE.equals(event.getKey())) {\r
-                PageDesc pageDesc = PageDesc.deserialize(value, DiagramPreferences.DEFAULT_PAGE_SIZE);\r
-                //System.out.println("new page desc: " + pageDesc);\r
-                canvasContext.getDefaultHintContext().setHint(Hints.KEY_PAGE_DESC, pageDesc);\r
-            } else if (DiagramPreferences.P_DISPLAY_PAGE_SIZE.equals(event.getKey())) {\r
-                Boolean display = value != null ? Boolean.parseBoolean(value) : DiagramPreferences.DEFAULT_DISPLAY_PAGE_SIZE;\r
-                canvasContext.getDefaultHintContext().setHint(Hints.KEY_DISPLAY_PAGE, display);\r
-            } else if (DiagramPreferences.P_DISPLAY_MARGINS.equals(event.getKey())) {\r
-                Boolean display = value != null ? Boolean.parseBoolean(value) : DiagramPreferences.DEFAULT_DISPLAY_MARGINS;\r
-                canvasContext.getDefaultHintContext().setHint(Hints.KEY_DISPLAY_MARGINS, display);\r
-            }\r
-        }\r
-    };\r
-\r
-    protected void addDropParticipants(ICanvasContext ctx) {\r
-        // FIXME This is a workaround so that this participant can be disabled\r
-        // for SymbolViewer\r
-        ctx.add(new PopulateElementDropParticipant(synchronizer));\r
-        ctx.add(new PopulateElementMonitorDropParticipant(synchronizer, 0.5, 0.5));\r
-    }\r
-\r
-    protected void addKeyBindingParticipants(CanvasContext ctx) {\r
-        //ctx.add( new KeyToCommand( CommandKeyBinding.DEFAULT_BINDINGS ) );\r
-        ctx.add(new DeleteHandler(statusLineManager));\r
-        ctx.add(new CopyPasteHandler(statusLineManager));\r
-        ctx.add(new ConnectionCommandHandler());\r
-    }\r
-\r
-    protected void addPopupmenu(ICanvasContext ctx) {\r
-        ctx.add(new SWTPopupMenuParticipant(getSite(), c, getPopupId()));\r
-    }\r
-\r
-    protected void addStructureParticipants(ICanvasContext ctx) {\r
-        structuralPath = getResourceInput().getResourceArray().removeFromBeginning(1);\r
-\r
-        ctx.add(new WorkbenchStructuralSelectionProvider(swt, getSite(), structuralPath));\r
-        // Add visual browsing capabilities for structural models\r
-//        ctx.add(new StructuralBrowsingHandler(getSite(), sessionContext, structuralPath));\r
-//        ctx.add(new LinkBrowsingHandler(getSite(), this, sessionContext));\r
-    }\r
-\r
-    protected String getPopupId() {\r
-        return "#ModelingDiagramPopup";\r
-    }\r
-\r
-    protected void getPreferences() {\r
-        this.diagramPreferences = DiagramPreferenceUtil.getPreferences();\r
-    }\r
-\r
-    protected void initSession() {\r
-        sessionContextProvider = SimanticsUI.getSessionContextProvider();\r
-        sessionContext = sessionContextProvider.getSessionContext();\r
-    }\r
-\r
-    protected void readNames() {\r
-        String name = getEditorInput().getName();\r
-        setPartName(name);\r
-        setTitleToolTip(name);\r
-    }\r
-\r
-    protected void createChassis(Composite parent) {\r
-        c = new SWTChassis(parent, 0);\r
-        c.syncPopulate();\r
-    }\r
-\r
-    protected void setCanvasContext(ICanvasContext context) {\r
-        c.setCanvasContext(canvasContext);\r
-    }\r
-\r
-    @Override\r
-    public void createPartControl(Composite parent) {\r
-        swt = SWTThread.getThreadAccess(parent.getDisplay());\r
-        statusLineManager = getEditorSite().getActionBars().getStatusLineManager();\r
-\r
-        Object task = BEGIN("DV.initSession");\r
-        initSession();\r
-        END(task);\r
-\r
-        diagramResource = getInputResource();\r
-        readNames();\r
-        getPreferences();\r
-\r
-        task = BEGIN("DV.createChassis");\r
-        createChassis(parent);\r
-        END(task);\r
-\r
-        initializeCanvas();\r
-\r
-        // Start tracking changes in diagram preferences.\r
-        diagramPreferences.preferences.addPreferenceChangeListener(preferenceListener);\r
-    }\r
-\r
-    protected void initializeCanvas() {\r
-        Object canvasInit = BEGIN("DV.canvasInitialization");\r
-\r
-        Object task = BEGIN("DV.createViewerCanvas");\r
-//        ThreadUtils.syncExec(AWTThread.getThreadAccess(), new Runnable() {\r
-//            @Override\r
-//            public void run() {\r
-        canvasContext = createViewerCanvas();\r
-//            }\r
-//        });\r
-        END(task);\r
-\r
-        //FullscreenUtils.addFullScreenHandler(canvasContext, s, canvasProvider);\r
-\r
-        task = BEGIN("DV.setCanvasContext");\r
-        setCanvasContext(canvasContext);\r
-        END(task);\r
-\r
-        try {\r
-            task = BEGIN("DV.loadDiagram");\r
-            sourceDiagram = loadDiagram(diagramResource);\r
-            END(task);\r
-\r
-            // Zoom to fit\r
-            task = BEGIN("DV.scheduleZoomToFit");\r
-\r
-//            canvasContext.getDefaultHintContext().setHint(Hints.KEY_CANVAS_TRANSFORM, new AffineTransform());\r
-//            canvasContext.getContentContext().setDirty();\r
-            scheduleZoomToFit();\r
-\r
-            END(task);\r
-\r
-            // Start an activation for the input resource.\r
-            // This will activate mapping if necessary.\r
-            task = BEGIN("DV.performActivation");\r
-            performActivation();\r
-            END(task);\r
-\r
-            task = BEGIN("DV.activate context");\r
-            contextUtil.activate(DiagramViewer.DIAGRAMMING_CONTEXT);\r
-            END(task);\r
-\r
-            task = BEGIN("DV.onCreated");\r
-            onCreated();\r
-            END(task);\r
-\r
-        } catch (DatabaseException e) {\r
-            ErrorLogger.defaultLogError(e);\r
-\r
-            // Without this all diagram participants will crash like there's no tomorrow.\r
-            // Just trying to keep the behavior a bit more sane in case of\r
-            // errors instead of flooding the console with exceptions.\r
-            canvasContext.getDefaultHintContext().setHint(DiagramHints.KEY_DIAGRAM, Diagram.spawnNew(DiagramClass.DEFAULT));\r
-        }\r
-        END(canvasInit);\r
-    }\r
-\r
-    protected void performActivation() {\r
-\r
-        IActivationManager activationManager = sessionContext.getSession().peekService(IActivationManager.class);\r
-        if (activationManager != null) {\r
-            activation = activationManager.activate(diagramResource);\r
-        }\r
-\r
-    }\r
-\r
-    protected void scheduleZoomToFit() {\r
-        if (sourceDiagram == null)\r
-            throw new IllegalStateException("source diagram is null");\r
-\r
-        sourceDiagram.setHint(Hints.KEY_DISABLE_PAINTING, Boolean.TRUE);\r
-        sourceDiagram.setHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT, Boolean.TRUE);\r
-        ThreadUtils.asyncExec(swt, new Runnable() {\r
-            @Override\r
-            public void run() {\r
-                if (disposed)\r
-                    return;\r
-\r
-                // System.out.println("size: " + c.getSize());\r
-                ThreadUtils.asyncExec(canvasContext.getThreadAccess(), new Runnable() {\r
-                    @Override\r
-                    public void run() {\r
-                        if (disposed)\r
-                            return;\r
-                        // System.out.println("fit diagram to view");\r
-                        sourceDiagram.removeHint(Hints.KEY_DISABLE_PAINTING);\r
-                        /*Boolean zoomToFit =*/ sourceDiagram.removeHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT);\r
-                        canvasContext.getDefaultHintContext().removeHint(Hints.KEY_DISABLE_PAINTING);\r
-\r
-//                        if (Boolean.TRUE.equals(zoomToFit))\r
-//                            CanvasUtils.sendCommand(canvasContext, Commands.ZOOM_TO_FIT);\r
-\r
-                        canvasContext.getContentContext().setDirty();\r
-                    }\r
-                });\r
-            }\r
-        });\r
-    }\r
-\r
-\r
-\r
-    protected IDiagram loadDiagram(final Resource r) throws DatabaseException {\r
-        final DataContainer<IDiagram> dc = new DataContainer<IDiagram>();\r
-        //dc.set( loadDiagram(new NullProgressMonitor(), r) );\r
-        try {\r
-            PlatformUI.getWorkbench().getProgressService().busyCursorWhile(new IRunnableWithProgress() {\r
-                @Override\r
-                public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {\r
-                    SubMonitor mon = SubMonitor.convert(monitor, "Loading Diagram", 100);\r
-                    try {\r
-                        dc.set( loadDiagram(mon.newChild(100), r) );\r
-                    } catch (DatabaseException e) {\r
-                        throw new InvocationTargetException(e);\r
-                    } finally {\r
-                        monitor.done();\r
-                    }\r
-                }\r
-            });\r
-        } catch (InvocationTargetException e) {\r
-            Throwable t = e.getTargetException();\r
-            if (t instanceof DatabaseException)\r
-                throw (DatabaseException) t;\r
-            throw new DatabaseException(t);\r
-        } catch (InterruptedException e) {\r
-            throw new DatabaseException(e);\r
-        }\r
-        return dc.get();\r
-    }\r
-\r
-    protected IDiagram loadDiagram(IProgressMonitor monitor, Resource r) throws DatabaseException {\r
-        SubMonitor mon = SubMonitor.convert(monitor, "Loading Diagram", 100);\r
-\r
-        Object task = BEGIN("DV.DiagramLoadQuery");\r
-        IDiagram d = sessionContext.getSession().syncRequest(DiagramRequests.loadDiagram(mon.newChild(100), getResourceInput2().getModel(null), r, null, structuralPath, synchronizer, null));\r
-        END(task);\r
-\r
-        task = BEGIN("DV.setDiagramHint");\r
-        canvasContext.getDefaultHintContext().setHint(DiagramHints.KEY_DIAGRAM, d);\r
-        END(task);\r
-\r
-        task = BEGIN("DV.set other hints");\r
-        // Setup a copy advisor for the synchronizer\r
-        //d.setHint(SynchronizationHints.COPY_ADVISOR, new MappedElementCopyAdvisor(new ComponentCopyAdvisor()));\r
-        d.setHint(DiagramHints.KEY_USE_CONNECTION_FLAGS, Boolean.FALSE);\r
-        d.setHint(DiagramHints.KEY_ALLOW_CONNECTION_BRANCHING, Boolean.FALSE);\r
-        d.setHint(DiagramHints.KEY_ALLOW_ROUTE_POINTS, Boolean.FALSE);\r
-        END(task);\r
-\r
-        return d;\r
-    }\r
-\r
-    protected GraphToDiagramSynchronizer createSynchronizer(final ICanvasContext ctx, final ISessionContext sessionContext) {\r
-        try {\r
-            return sessionContext.getSession().syncRequest(new Read<GraphToDiagramSynchronizer>() {\r
-                @Override\r
-                public GraphToDiagramSynchronizer perform(ReadGraph graph) throws DatabaseException {\r
-                    GraphToDiagramSynchronizer sync = new GraphToDiagramSynchronizer(graph, ctx, createElementClassProvider(graph));\r
-                    initializeSynchronizationContext(graph, sync);\r
-                    return sync;\r
-                }\r
-            });\r
-        } catch (DatabaseException e) {\r
-            throw new UnsupportedOperationException("Failed to initialize data model synchronizer", e);\r
-        }\r
-    }\r
-\r
-    protected void initializeSynchronizationContext(ReadGraph graph, IModifiableSynchronizationContext context) {\r
-        context.set(ModelingSynchronizationHints.MODELING_RESOURCE, ModelingResources.getInstance(graph));\r
-    }\r
-\r
-    protected IElementClassProvider createElementClassProvider(ReadGraph graph) {\r
-        DiagramResource dr = DiagramResource.getInstance(graph);\r
-        return ElementClassProviders.mappedProvider(\r
-                ElementClasses.CONNECTION, DefaultConnectionClassFactory.CLASS.newClassWith(new StaticObjectAdapter(dr.Connection)),\r
-                ElementClasses.FLAG, FlagClassFactory.createFlagClass(dr.Flag, dr.Flag_Terminal)\r
-        );\r
-    }\r
-\r
-    public ICanvasContext createViewerCanvas() {\r
-        IThreadWorkQueue thread = AWTThread.getThreadAccess();\r
-        CanvasContext ctx = new CanvasContext(thread);\r
-        IHintContext h = ctx.getDefaultHintContext();\r
-\r
-        Object task = BEGIN("createSynchronizer");\r
-        this.synchronizer = createSynchronizer(ctx, sessionContext);\r
-        END(task);\r
-\r
-        IContextService contextService = (IContextService) getSite().getService(IContextService.class);\r
-        contextUtil = new ContextUtil(contextService, swt);\r
-\r
-        ctx.add(new PanZoomRotateHandler()); // Must be before TransformUtil\r
-\r
-        // Support & Util Participants\r
-        ctx.add(new TransformUtil());\r
-        ctx.add(new MouseUtil());\r
-        ctx.add(new KeyUtil());\r
-        ctx.add(contextUtil);\r
-        ctx.add(new CanvasGrab());\r
-        ctx.add(new SymbolUtil());\r
-        ctx.add(new TimeParticipant());\r
-        ctx.add(new CanvasBoundsParticipant());\r
-        ctx.add(new Notifications());\r
-\r
-        ctx.add( new SGFocusParticipant(c, DiagramViewer.DIAGRAMMING_CONTEXT) );\r
-\r
-        // Debug participant(s)\r
-        // ctx.add( new PointerPainter() );\r
-        // ctx.add( new HandPainter() );\r
-        h.setHint(PointerPainter.KEY_PAINT_POINTER, true);\r
-\r
-        // Pan & Zoom & Rotate\r
-        ctx.add(new MultitouchPanZoomRotateInteractor());\r
-        // ctx.add( new OrientationRestorer() );\r
-        ctx.add(new ZoomToAreaHandler());\r
-        ctx.add(new SimpleElementTransformHandler(true, true, true));\r
-        ctx.add(new ExpandSelectionHandler(getEditorSite().getActionBars().getStatusLineManager()));\r
-\r
-        // Key bindings\r
-        addKeyBindingParticipants(ctx);\r
-\r
-        // Grid & Ruler & Background\r
-//        ctx.add(new GridPainter());\r
-//        ctx.add(new RulerPainter());\r
-//        ctx.add(new BackgroundPainter());\r
-\r
-\r
-        h.setHint(PanZoomRotateHandler.KEY_ADAPT_VIEWPORT_TO_RESIZED_CONTROL, Boolean.FALSE);\r
-        h.setHint(Hints.KEY_DISPLAY_PAGE, diagramPreferences.get(DiagramPreferences.P_DISPLAY_PAGE_SIZE));\r
-        h.setHint(Hints.KEY_DISPLAY_MARGINS, diagramPreferences.get(DiagramPreferences.P_DISPLAY_MARGINS));\r
-        ctx.add(new PageBorderParticipant());\r
-\r
-        // h.setHint(Hints.KEY_GRID_COLOR, new Color(0.9f, 0.9f, 0.9f));\r
-        // h.setHint(Hints.KEY_BACKGROUND_COLOR, Color.LIGHT_GRAY);\r
-        h.setHint(Hints.KEY_GRID_COLOR, new Color(0.95f, 0.95f, 0.95f));\r
-        h.setHint(Hints.KEY_BACKGROUND_COLOR, Color.WHITE);\r
-        h.setHint(RulerPainter.KEY_RULER_BACKGROUND_COLOR, new Color(0.9f, 0.9f, 0.9f, 0.75f));\r
-        h.setHint(RulerPainter.KEY_RULER_TEXT_COLOR, Color.BLACK);\r
-\r
-        ////// Diagram Participants //////\r
-        ctx.add(new ZOrderHandler());\r
-        ctx.add(new PointerInteractor(true, true, true, false, true, false, synchronizer.getElementClassProvider(), null));\r
-        ctx.add(new ElementInteractor());\r
-        ctx.add(new Selection());\r
-        ctx.add(new DiagramParticipant());\r
-        ctx.add(new ElementPainter());\r
-        ctx.add(new TerminalPainter(true, true, false, true));\r
-        //ctx.add(new ElementHeartbeater());\r
-//        ctx.add(new ZoomTransitionParticipant(TransitionFunction.SIGMOID));\r
-\r
-        /////// D'n'D ///////\r
-        addDropParticipants(ctx);\r
-\r
-        h.setHint(ElementPainter.KEY_SELECTION_FRAME_COLOR, Color.MAGENTA);\r
-        h.setHint(Hints.KEY_TOOL, Hints.POINTERTOOL);\r
-\r
-        h.setHint(PanZoomRotateHandler.KEY_ZOOM_IN_LIMIT, 100000.0);\r
-        h.setHint(PanZoomRotateHandler.KEY_ZOOM_OUT_LIMIT, 10.0);\r
-\r
-        Double snapResolution = diagramPreferences.get(DiagramPreferences.P_SNAP_GRID_SIZE);\r
-        this.snapAdvisor = new GridSnapAdvisor(snapResolution);\r
-        h.setHint(DiagramHints.SNAP_ADVISOR, this.snapAdvisor);\r
-\r
-        // Workbench selection provider\r
-        addStructureParticipants(ctx);\r
-\r
-        // Pop-up menu\r
-        addPopupmenu(ctx);\r
-\r
-        // Load page frame description settings\r
-        loadPageSettings(ctx);\r
-\r
-        // The canvas context should not be painted until it is ready to avoid\r
-        // unnecessary visual glitches.\r
-        h.setHint(Hints.KEY_DISABLE_PAINTING, Boolean.TRUE);\r
-\r
-        ctx.assertParticipantDependencies();\r
-\r
-        return ctx;\r
-    }\r
-\r
-    protected void loadPageSettings(ICanvasContext ctx) {\r
-        PageDesc pageDesc = null;\r
-\r
-        if (diagramResource != null) {\r
-            try {\r
-                pageDesc = sessionContext.getSession().syncRequest(new Read<PageDesc>() {\r
-                    @Override\r
-                    public PageDesc perform(ReadGraph graph) throws DatabaseException {\r
-                        return DiagramGraphUtil.getPageDesc(graph, diagramResource, null);\r
-                    }\r
-                });\r
-            } catch (DatabaseException e) {\r
-                ErrorLogger.defaultLogError(e);\r
-            }\r
-        }\r
-\r
-        if (pageDesc == null) {\r
-            // Take page description from the preferences if nothing else is available.\r
-            PageDesc pd = diagramPreferences.getCompletePageDesc();\r
-            pageDesc = pd;\r
-        }\r
-        ctx.getDefaultHintContext().setHint(Hints.KEY_PAGE_DESC, pageDesc);\r
-    }\r
-\r
-    private boolean firstFocus = true;\r
-\r
-    @Override\r
-    public void setFocus() {\r
-        c.setFocus();\r
-\r
-        if (firstFocus) {\r
-            // This is a workaround for using the symbol viewer in multi-page\r
-            // editors which causes the first zoom-to-fit scheduling to happen\r
-            // already before the controls have been laid out properly.\r
-            firstFocus = false;\r
-            firstTimeSetFocus();\r
-        }\r
-    }\r
-\r
-    protected void firstTimeSetFocus() {\r
-        //scheduleZoomToFit();\r
-    }\r
-\r
-    @Override\r
-    public void dispose() {\r
-        // Remember to remove the added preference change listener\r
-        diagramPreferences.preferences.removePreferenceChangeListener(preferenceListener);\r
-\r
-        // Deactivate all contexts here because after this the context service\r
-        // in question will not be available.\r
-        contextUtil.deactivateAll();\r
-\r
-        disposed = true;\r
-        if (activation != null) {\r
-            activation.deactivate();\r
-            activation = null;\r
-        }\r
-        synchronizer.dispose();\r
-        ThreadUtils.asyncExec(c.getCanvasContext().getThreadAccess(), new Runnable() {\r
-            @Override\r
-            public void run() {\r
-                c.getCanvasContext().dispose();\r
-            }\r
-        });\r
-        sourceDiagram.dispose();\r
-        support.dispose();\r
-        super.dispose();\r
-    }\r
-\r
-    protected Resource getInputResource() {\r
-        return getResourceInput().getResource();\r
-    }\r
-\r
-    @Override\r
-    public IResourceEditorInput2 getResourceInput2() {\r
-        return (IResourceEditorInput2) getEditorInput();\r
-    }\r
-\r
-    @Override\r
-    public IResourceEditorInput getResourceInput() {\r
-        return (IResourceEditorInput) getEditorInput();\r
-    }\r
-\r
-    @Override\r
-    public void doSave(IProgressMonitor monitor) {\r
-    }\r
-\r
-    @Override\r
-    public void doSaveAs() {\r
-    }\r
-\r
-    @Override\r
-    public void init(IEditorSite site, IEditorInput input) throws PartInitException {\r
-        if (!(input instanceof IResourceEditorInput))\r
-            throw new PartInitException("Invalid input: must be IResourceEditorInput");\r
-        setSite(site);\r
-        setInput(input);\r
-        support = new ResourceEditorSupport(this);\r
-\r
-        // Set initial part name according to the name given by IEditorInput\r
-        setPartName(getEditorInput().getName());\r
-\r
-        Session session = SimanticsUI.peekSession();\r
-        if (session != null) {\r
-            Supplier<Boolean> disposedCallback = () -> disposed;\r
-            session.asyncRequest(\r
-                    new TitleRequest(site.getId(), getResourceInput2()),\r
-                    new TitleUpdater(site.getShell().getDisplay(), this::setPartName, disposedCallback));\r
-            session.asyncRequest(\r
-                    new ToolTipRequest(site.getId(), getResourceInput2()),\r
-                    new TitleUpdater(site.getShell().getDisplay(), this::setTitleToolTip, disposedCallback));\r
-        }\r
-\r
-    }\r
-\r
-    @Override\r
-    public boolean isDirty() {\r
-        return false;\r
-    }\r
-\r
-    @Override\r
-    public boolean isSaveAsAllowed() {\r
-        return false;\r
-    }\r
-\r
-    @SuppressWarnings("unchecked")\r
-    @Override\r
-    public <T> T getAdapter(Class<T> adapter) {\r
-        if (adapter == IPropertyPage.class)\r
-            return (T) new StandardPropertyPage(getSite());\r
-        if (adapter == IContentOutlinePage.class)\r
-            return (T) new DiagramOutlinePage(sessionContextProvider, getResourceInput2());\r
-        if (adapter == ILayersViewPage.class)\r
-            return (T) new DiagramLayersPage(sourceDiagram, canvasContext);\r
-        if (adapter == ICanvasContext.class)\r
-            return (T) canvasContext;\r
-        if (adapter == INode.class) {\r
-            if (canvasContext != null) {\r
-                INode node = canvasContext.getCanvasNode();\r
-                if (node != null)\r
-                    return (T) NodeUtil.getRootNode(node);\r
-            }\r
-            return null;\r
-        }\r
-        if (adapter == IDiagram.class)\r
-            return (T) sourceDiagram;\r
-        if (adapter == Session.class)\r
-            return (T) sessionContext.getSession();\r
-        return super.getAdapter(adapter);\r
-    }\r
-\r
-    protected void onCreated() {\r
-    }\r
-\r
-\r
-    private static Object BEGIN(String name) {\r
-        if (PROFILE) {\r
-            //return ThreadLog.BEGIN(name);\r
-        }\r
-        return null;\r
-    }\r
-\r
-    private static void END(Object task) {\r
-        if (PROFILE) {\r
-            //((Task) task).end();\r
-        }\r
-    }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2013 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     VTT Technical Research Centre of Finland - initial API and implementation
+ *     Semantum Oy - issue #4384
+ *******************************************************************************/
+package org.simantics.modeling.ui.diagramEditor;
+
+import java.awt.Color;
+import java.lang.reflect.InvocationTargetException;
+import java.util.function.Supplier;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.IPreferenceChangeListener;
+import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.operation.IRunnableWithProgress;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.contexts.IContextService;
+import org.eclipse.ui.part.EditorPart;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.common.ResourceArray;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.management.ISessionContext;
+import org.simantics.db.management.ISessionContextProvider;
+import org.simantics.db.request.Read;
+import org.simantics.diagram.adapter.DefaultConnectionClassFactory;
+import org.simantics.diagram.adapter.FlagClassFactory;
+import org.simantics.diagram.adapter.GraphToDiagramSynchronizer;
+import org.simantics.diagram.handler.ConnectionCommandHandler;
+import org.simantics.diagram.handler.CopyPasteHandler;
+import org.simantics.diagram.handler.DeleteHandler;
+import org.simantics.diagram.handler.ExpandSelectionHandler;
+import org.simantics.diagram.handler.SimpleElementTransformHandler;
+import org.simantics.diagram.layer.ILayersViewPage;
+import org.simantics.diagram.participant.ContextUtil;
+import org.simantics.diagram.participant.SGFocusParticipant;
+import org.simantics.diagram.query.DiagramRequests;
+import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.diagram.synchronization.IModifiableSynchronizationContext;
+import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;
+import org.simantics.diagram.ui.SWTPopupMenuParticipant;
+import org.simantics.g2d.canvas.Hints;
+import org.simantics.g2d.canvas.ICanvasContext;
+import org.simantics.g2d.canvas.impl.CanvasContext;
+import org.simantics.g2d.chassis.SWTChassis;
+import org.simantics.g2d.diagram.DiagramClass;
+import org.simantics.g2d.diagram.DiagramHints;
+import org.simantics.g2d.diagram.IDiagram;
+import org.simantics.g2d.diagram.impl.Diagram;
+import org.simantics.g2d.diagram.participant.DiagramParticipant;
+import org.simantics.g2d.diagram.participant.ElementInteractor;
+import org.simantics.g2d.diagram.participant.ElementPainter;
+import org.simantics.g2d.diagram.participant.Selection;
+import org.simantics.g2d.diagram.participant.TerminalPainter;
+import org.simantics.g2d.diagram.participant.ZOrderHandler;
+import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;
+import org.simantics.g2d.element.ElementClassProviders;
+import org.simantics.g2d.element.ElementClasses;
+import org.simantics.g2d.element.IElementClassProvider;
+import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;
+import org.simantics.g2d.participant.CanvasBoundsParticipant;
+import org.simantics.g2d.participant.CanvasGrab;
+import org.simantics.g2d.participant.KeyUtil;
+import org.simantics.g2d.participant.MouseUtil;
+import org.simantics.g2d.participant.MultitouchPanZoomRotateInteractor;
+import org.simantics.g2d.participant.Notifications;
+import org.simantics.g2d.participant.PageBorderParticipant;
+import org.simantics.g2d.participant.PanZoomRotateHandler;
+import org.simantics.g2d.participant.PointerPainter;
+import org.simantics.g2d.participant.RulerPainter;
+import org.simantics.g2d.participant.SymbolUtil;
+import org.simantics.g2d.participant.TimeParticipant;
+import org.simantics.g2d.participant.TransformUtil;
+import org.simantics.g2d.participant.ZoomToAreaHandler;
+import org.simantics.layer0.utils.triggers.IActivation;
+import org.simantics.layer0.utils.triggers.IActivationManager;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.modeling.mapping.ModelingSynchronizationHints;
+import org.simantics.modeling.ui.diagramEditor.handlers.WorkbenchStructuralSelectionProvider;
+import org.simantics.modeling.ui.preferences.DiagramPreferenceUtil;
+import org.simantics.modeling.ui.preferences.DiagramPreferences;
+import org.simantics.scenegraph.INode;
+import org.simantics.scenegraph.g2d.snap.GridSnapAdvisor;
+import org.simantics.scenegraph.utils.NodeUtil;
+import org.simantics.selectionview.StandardPropertyPage;
+import org.simantics.ui.SimanticsUI;
+import org.simantics.ui.workbench.IPropertyPage;
+import org.simantics.ui.workbench.IResourceEditorInput;
+import org.simantics.ui.workbench.IResourceEditorInput2;
+import org.simantics.ui.workbench.IResourceEditorPart2;
+import org.simantics.ui.workbench.ResourceEditorSupport;
+import org.simantics.ui.workbench.TitleRequest;
+import org.simantics.ui.workbench.TitleUpdater;
+import org.simantics.ui.workbench.ToolTipRequest;
+import org.simantics.utils.DataContainer;
+import org.simantics.utils.datastructures.hints.IHintContext;
+import org.simantics.utils.page.PageDesc;
+import org.simantics.utils.threads.AWTThread;
+import org.simantics.utils.threads.IThreadWorkQueue;
+import org.simantics.utils.threads.SWTThread;
+import org.simantics.utils.threads.ThreadUtils;
+import org.simantics.utils.ui.ErrorLogger;
+
+/**
+ * @author Toni Kalajainen
+ * @author Tuukka Lehtonen
+ */
+public class SheetViewer extends EditorPart implements IResourceEditorPart2 {
+
+    private static final boolean         PROFILE            = false;
+
+    protected boolean                    disposed           = false;
+    protected IThreadWorkQueue           swt;
+    protected IStatusLineManager         statusLineManager;
+    protected SWTChassis                 c;
+    protected IDiagram                   sourceDiagram;
+    protected ICanvasContext             canvasContext;
+    protected ResourceEditorSupport      support;
+    protected ISessionContextProvider    sessionContextProvider;
+    protected ISessionContext            sessionContext;
+    protected Resource                   diagramResource;
+    protected GraphToDiagramSynchronizer synchronizer;
+    protected IActivation                activation;
+    protected ContextUtil                contextUtil;
+
+    protected DiagramPreferences         diagramPreferences;
+    protected GridSnapAdvisor            snapAdvisor;
+
+    public ResourceArray                 structuralPath;
+
+    IPreferenceChangeListener preferenceListener = new IPreferenceChangeListener() {
+        @Override
+        public void preferenceChange(PreferenceChangeEvent event) {
+            String value = (String) event.getNewValue();
+            if (DiagramPreferences.P_SNAP_GRID_SIZE.equals(event.getKey())) {
+                double grid = DiagramPreferences.DEFAULT_SNAP_GRID_SIZE;
+                if (value != null)
+                    grid = Double.parseDouble(value);
+                snapAdvisor.setResolution(grid);
+            } else if (DiagramPreferences.P_DEFAULT_PAGE_SIZE.equals(event.getKey())) {
+                PageDesc pageDesc = PageDesc.deserialize(value, DiagramPreferences.DEFAULT_PAGE_SIZE);
+                //System.out.println("new page desc: " + pageDesc);
+                canvasContext.getDefaultHintContext().setHint(Hints.KEY_PAGE_DESC, pageDesc);
+            } else if (DiagramPreferences.P_DISPLAY_PAGE_SIZE.equals(event.getKey())) {
+                Boolean display = value != null ? Boolean.parseBoolean(value) : DiagramPreferences.DEFAULT_DISPLAY_PAGE_SIZE;
+                canvasContext.getDefaultHintContext().setHint(Hints.KEY_DISPLAY_PAGE, display);
+            } else if (DiagramPreferences.P_DISPLAY_MARGINS.equals(event.getKey())) {
+                Boolean display = value != null ? Boolean.parseBoolean(value) : DiagramPreferences.DEFAULT_DISPLAY_MARGINS;
+                canvasContext.getDefaultHintContext().setHint(Hints.KEY_DISPLAY_MARGINS, display);
+            }
+        }
+    };
+
+    protected void addDropParticipants(ICanvasContext ctx) {
+        // FIXME This is a workaround so that this participant can be disabled
+        // for SymbolViewer
+        ctx.add(new PopulateElementDropParticipant(synchronizer));
+        ctx.add(new PopulateElementMonitorDropParticipant(synchronizer, 0.5, 0.5));
+    }
+
+    protected void addKeyBindingParticipants(CanvasContext ctx) {
+        //ctx.add( new KeyToCommand( CommandKeyBinding.DEFAULT_BINDINGS ) );
+        ctx.add(new DeleteHandler(statusLineManager));
+        ctx.add(new CopyPasteHandler(statusLineManager));
+        ctx.add(new ConnectionCommandHandler());
+    }
+
+    protected void addPopupmenu(ICanvasContext ctx) {
+        ctx.add(new SWTPopupMenuParticipant(getSite(), c, getPopupId()));
+    }
+
+    protected void addStructureParticipants(ICanvasContext ctx) {
+        structuralPath = getResourceInput().getResourceArray().removeFromBeginning(1);
+
+        ctx.add(new WorkbenchStructuralSelectionProvider(swt, getSite(), structuralPath));
+        // Add visual browsing capabilities for structural models
+//        ctx.add(new StructuralBrowsingHandler(getSite(), sessionContext, structuralPath));
+//        ctx.add(new LinkBrowsingHandler(getSite(), this, sessionContext));
+    }
+
+    protected String getPopupId() {
+        return "#ModelingDiagramPopup";
+    }
+
+    protected void getPreferences() {
+        this.diagramPreferences = DiagramPreferenceUtil.getPreferences();
+    }
+
+    protected void initSession() {
+        sessionContextProvider = SimanticsUI.getSessionContextProvider();
+        sessionContext = sessionContextProvider.getSessionContext();
+    }
+
+    protected void readNames() {
+        String name = getEditorInput().getName();
+        setPartName(name);
+        setTitleToolTip(name);
+    }
+
+    protected void createChassis(Composite parent) {
+        c = new SWTChassis(parent, 0);
+        c.syncPopulate();
+    }
+
+    protected void setCanvasContext(ICanvasContext context) {
+        c.setCanvasContext(canvasContext);
+    }
+
+    @Override
+    public void createPartControl(Composite parent) {
+        swt = SWTThread.getThreadAccess(parent.getDisplay());
+        statusLineManager = getEditorSite().getActionBars().getStatusLineManager();
+
+        Object task = BEGIN("DV.initSession");
+        initSession();
+        END(task);
+
+        diagramResource = getInputResource();
+        readNames();
+        getPreferences();
+
+        task = BEGIN("DV.createChassis");
+        createChassis(parent);
+        END(task);
+
+        initializeCanvas();
+
+        // Start tracking changes in diagram preferences.
+        diagramPreferences.preferences.addPreferenceChangeListener(preferenceListener);
+    }
+
+    protected void initializeCanvas() {
+        Object canvasInit = BEGIN("DV.canvasInitialization");
+
+        Object task = BEGIN("DV.createViewerCanvas");
+//        ThreadUtils.syncExec(AWTThread.getThreadAccess(), new Runnable() {
+//            @Override
+//            public void run() {
+        canvasContext = createViewerCanvas();
+//            }
+//        });
+        END(task);
+
+        //FullscreenUtils.addFullScreenHandler(canvasContext, s, canvasProvider);
+
+        task = BEGIN("DV.setCanvasContext");
+        setCanvasContext(canvasContext);
+        END(task);
+
+        try {
+            task = BEGIN("DV.loadDiagram");
+            sourceDiagram = loadDiagram(diagramResource);
+            END(task);
+
+            // Zoom to fit
+            task = BEGIN("DV.scheduleZoomToFit");
+
+//            canvasContext.getDefaultHintContext().setHint(Hints.KEY_CANVAS_TRANSFORM, new AffineTransform());
+//            canvasContext.getContentContext().setDirty();
+            scheduleZoomToFit();
+
+            END(task);
+
+            // Start an activation for the input resource.
+            // This will activate mapping if necessary.
+            task = BEGIN("DV.performActivation");
+            performActivation();
+            END(task);
+
+            task = BEGIN("DV.activate context");
+            contextUtil.activate(DiagramViewer.DIAGRAMMING_CONTEXT);
+            END(task);
+
+            task = BEGIN("DV.onCreated");
+            onCreated();
+            END(task);
+
+        } catch (DatabaseException e) {
+            ErrorLogger.defaultLogError(e);
+
+            // Without this all diagram participants will crash like there's no tomorrow.
+            // Just trying to keep the behavior a bit more sane in case of
+            // errors instead of flooding the console with exceptions.
+            canvasContext.getDefaultHintContext().setHint(DiagramHints.KEY_DIAGRAM, Diagram.spawnNew(DiagramClass.DEFAULT));
+        }
+        END(canvasInit);
+    }
+
+    protected void performActivation() {
+
+        IActivationManager activationManager = sessionContext.getSession().peekService(IActivationManager.class);
+        if (activationManager != null) {
+            activation = activationManager.activate(diagramResource);
+        }
+
+    }
+
+    protected void scheduleZoomToFit() {
+        if (sourceDiagram == null)
+            throw new IllegalStateException("source diagram is null");
+
+        sourceDiagram.setHint(Hints.KEY_DISABLE_PAINTING, Boolean.TRUE);
+        sourceDiagram.setHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT, Boolean.TRUE);
+        ThreadUtils.asyncExec(swt, new Runnable() {
+            @Override
+            public void run() {
+                if (disposed)
+                    return;
+
+                // System.out.println("size: " + c.getSize());
+                ThreadUtils.asyncExec(canvasContext.getThreadAccess(), new Runnable() {
+                    @Override
+                    public void run() {
+                        if (disposed)
+                            return;
+                        // System.out.println("fit diagram to view");
+                        sourceDiagram.removeHint(Hints.KEY_DISABLE_PAINTING);
+                        /*Boolean zoomToFit =*/ sourceDiagram.removeHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT);
+                        canvasContext.getDefaultHintContext().removeHint(Hints.KEY_DISABLE_PAINTING);
+
+//                        if (Boolean.TRUE.equals(zoomToFit))
+//                            CanvasUtils.sendCommand(canvasContext, Commands.ZOOM_TO_FIT);
+
+                        canvasContext.getContentContext().setDirty();
+                    }
+                });
+            }
+        });
+    }
+
+
+
+    protected IDiagram loadDiagram(final Resource r) throws DatabaseException {
+        final DataContainer<IDiagram> dc = new DataContainer<IDiagram>();
+        //dc.set( loadDiagram(new NullProgressMonitor(), r) );
+        try {
+            PlatformUI.getWorkbench().getProgressService().busyCursorWhile(new IRunnableWithProgress() {
+                @Override
+                public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
+                    SubMonitor mon = SubMonitor.convert(monitor, "Loading Diagram", 100);
+                    try {
+                        dc.set( loadDiagram(mon.newChild(100), r) );
+                    } catch (DatabaseException e) {
+                        throw new InvocationTargetException(e);
+                    } finally {
+                        monitor.done();
+                    }
+                }
+            });
+        } catch (InvocationTargetException e) {
+            Throwable t = e.getTargetException();
+            if (t instanceof DatabaseException)
+                throw (DatabaseException) t;
+            throw new DatabaseException(t);
+        } catch (InterruptedException e) {
+            throw new DatabaseException(e);
+        }
+        return dc.get();
+    }
+
+    protected IDiagram loadDiagram(IProgressMonitor monitor, Resource r) throws DatabaseException {
+        SubMonitor mon = SubMonitor.convert(monitor, "Loading Diagram", 100);
+
+        Object task = BEGIN("DV.DiagramLoadQuery");
+        IDiagram d = sessionContext.getSession().syncRequest(DiagramRequests.loadDiagram(mon.newChild(100), getResourceInput2().getModel(null), r, null, structuralPath, synchronizer, null));
+        END(task);
+
+        task = BEGIN("DV.setDiagramHint");
+        canvasContext.getDefaultHintContext().setHint(DiagramHints.KEY_DIAGRAM, d);
+        END(task);
+
+        task = BEGIN("DV.set other hints");
+        // Setup a copy advisor for the synchronizer
+        //d.setHint(SynchronizationHints.COPY_ADVISOR, new MappedElementCopyAdvisor(new ComponentCopyAdvisor()));
+        d.setHint(DiagramHints.KEY_USE_CONNECTION_FLAGS, Boolean.FALSE);
+        d.setHint(DiagramHints.KEY_ALLOW_CONNECTION_BRANCHING, Boolean.FALSE);
+        d.setHint(DiagramHints.KEY_ALLOW_ROUTE_POINTS, Boolean.FALSE);
+        END(task);
+
+        return d;
+    }
+
+    protected GraphToDiagramSynchronizer createSynchronizer(final ICanvasContext ctx, final ISessionContext sessionContext) {
+        try {
+            return sessionContext.getSession().syncRequest(new Read<GraphToDiagramSynchronizer>() {
+                @Override
+                public GraphToDiagramSynchronizer perform(ReadGraph graph) throws DatabaseException {
+                    GraphToDiagramSynchronizer sync = new GraphToDiagramSynchronizer(graph, ctx, createElementClassProvider(graph));
+                    initializeSynchronizationContext(graph, sync);
+                    return sync;
+                }
+            });
+        } catch (DatabaseException e) {
+            throw new UnsupportedOperationException("Failed to initialize data model synchronizer", e);
+        }
+    }
+
+    protected void initializeSynchronizationContext(ReadGraph graph, IModifiableSynchronizationContext context) {
+        context.set(ModelingSynchronizationHints.MODELING_RESOURCE, ModelingResources.getInstance(graph));
+    }
+
+    protected IElementClassProvider createElementClassProvider(ReadGraph graph) {
+        DiagramResource dr = DiagramResource.getInstance(graph);
+        return ElementClassProviders.mappedProvider(
+                ElementClasses.CONNECTION, DefaultConnectionClassFactory.CLASS.newClassWith(new StaticObjectAdapter(dr.Connection)),
+                ElementClasses.FLAG, FlagClassFactory.createFlagClass(dr.Flag, dr.Flag_Terminal)
+        );
+    }
+
+    public ICanvasContext createViewerCanvas() {
+        IThreadWorkQueue thread = AWTThread.getThreadAccess();
+        CanvasContext ctx = new CanvasContext(thread);
+        IHintContext h = ctx.getDefaultHintContext();
+
+        Object task = BEGIN("createSynchronizer");
+        this.synchronizer = createSynchronizer(ctx, sessionContext);
+        END(task);
+
+        IContextService contextService = (IContextService) getSite().getService(IContextService.class);
+        contextUtil = new ContextUtil(contextService, swt);
+
+        ctx.add(new PanZoomRotateHandler()); // Must be before TransformUtil
+
+        // Support & Util Participants
+        ctx.add(new TransformUtil());
+        ctx.add(new MouseUtil());
+        ctx.add(new KeyUtil());
+        ctx.add(contextUtil);
+        ctx.add(new CanvasGrab());
+        ctx.add(new SymbolUtil());
+        ctx.add(new TimeParticipant());
+        ctx.add(new CanvasBoundsParticipant());
+        ctx.add(new Notifications());
+
+        ctx.add( new SGFocusParticipant(c, DiagramViewer.DIAGRAMMING_CONTEXT) );
+
+        // Debug participant(s)
+        // ctx.add( new PointerPainter() );
+        // ctx.add( new HandPainter() );
+        h.setHint(PointerPainter.KEY_PAINT_POINTER, true);
+
+        // Pan & Zoom & Rotate
+        ctx.add(new MultitouchPanZoomRotateInteractor());
+        // ctx.add( new OrientationRestorer() );
+        ctx.add(new ZoomToAreaHandler());
+        ctx.add(new SimpleElementTransformHandler(true, true, true));
+        ctx.add(new ExpandSelectionHandler(getEditorSite().getActionBars().getStatusLineManager()));
+
+        // Key bindings
+        addKeyBindingParticipants(ctx);
+
+        // Grid & Ruler & Background
+//        ctx.add(new GridPainter());
+//        ctx.add(new RulerPainter());
+//        ctx.add(new BackgroundPainter());
+
+
+        h.setHint(PanZoomRotateHandler.KEY_ADAPT_VIEWPORT_TO_RESIZED_CONTROL, Boolean.FALSE);
+        h.setHint(Hints.KEY_DISPLAY_PAGE, diagramPreferences.get(DiagramPreferences.P_DISPLAY_PAGE_SIZE));
+        h.setHint(Hints.KEY_DISPLAY_MARGINS, diagramPreferences.get(DiagramPreferences.P_DISPLAY_MARGINS));
+        ctx.add(new PageBorderParticipant());
+
+        // h.setHint(Hints.KEY_GRID_COLOR, new Color(0.9f, 0.9f, 0.9f));
+        // h.setHint(Hints.KEY_BACKGROUND_COLOR, Color.LIGHT_GRAY);
+        h.setHint(Hints.KEY_GRID_COLOR, new Color(0.95f, 0.95f, 0.95f));
+        h.setHint(Hints.KEY_BACKGROUND_COLOR, Color.WHITE);
+        h.setHint(RulerPainter.KEY_RULER_BACKGROUND_COLOR, new Color(0.9f, 0.9f, 0.9f, 0.75f));
+        h.setHint(RulerPainter.KEY_RULER_TEXT_COLOR, Color.BLACK);
+
+        ////// Diagram Participants //////
+        ctx.add(new ZOrderHandler());
+        ctx.add(new PointerInteractor(true, true, true, false, true, false, synchronizer.getElementClassProvider(), null));
+        ctx.add(new ElementInteractor());
+        ctx.add(new Selection());
+        ctx.add(new DiagramParticipant());
+        ctx.add(new ElementPainter());
+        ctx.add(new TerminalPainter(true, true, false, true));
+        //ctx.add(new ElementHeartbeater());
+//        ctx.add(new ZoomTransitionParticipant(TransitionFunction.SIGMOID));
+
+        /////// D'n'D ///////
+        addDropParticipants(ctx);
+
+        h.setHint(ElementPainter.KEY_SELECTION_FRAME_COLOR, Color.MAGENTA);
+        h.setHint(Hints.KEY_TOOL, Hints.POINTERTOOL);
+
+        h.setHint(PanZoomRotateHandler.KEY_ZOOM_IN_LIMIT, 100000.0);
+        h.setHint(PanZoomRotateHandler.KEY_ZOOM_OUT_LIMIT, 10.0);
+
+        Double snapResolution = diagramPreferences.get(DiagramPreferences.P_SNAP_GRID_SIZE);
+        this.snapAdvisor = new GridSnapAdvisor(snapResolution);
+        h.setHint(DiagramHints.SNAP_ADVISOR, this.snapAdvisor);
+
+        // Workbench selection provider
+        addStructureParticipants(ctx);
+
+        // Pop-up menu
+        addPopupmenu(ctx);
+
+        // Load page frame description settings
+        loadPageSettings(ctx);
+
+        // The canvas context should not be painted until it is ready to avoid
+        // unnecessary visual glitches.
+        h.setHint(Hints.KEY_DISABLE_PAINTING, Boolean.TRUE);
+
+        ctx.assertParticipantDependencies();
+
+        return ctx;
+    }
+
+    protected void loadPageSettings(ICanvasContext ctx) {
+        PageDesc pageDesc = null;
+
+        if (diagramResource != null) {
+            try {
+                pageDesc = sessionContext.getSession().syncRequest(new Read<PageDesc>() {
+                    @Override
+                    public PageDesc perform(ReadGraph graph) throws DatabaseException {
+                        return DiagramGraphUtil.getPageDesc(graph, diagramResource, null);
+                    }
+                });
+            } catch (DatabaseException e) {
+                ErrorLogger.defaultLogError(e);
+            }
+        }
+
+        if (pageDesc == null) {
+            // Take page description from the preferences if nothing else is available.
+            PageDesc pd = diagramPreferences.getCompletePageDesc();
+            pageDesc = pd;
+        }
+        ctx.getDefaultHintContext().setHint(Hints.KEY_PAGE_DESC, pageDesc);
+    }
+
+    private boolean firstFocus = true;
+
+    @Override
+    public void setFocus() {
+        c.setFocus();
+
+        if (firstFocus) {
+            // This is a workaround for using the symbol viewer in multi-page
+            // editors which causes the first zoom-to-fit scheduling to happen
+            // already before the controls have been laid out properly.
+            firstFocus = false;
+            firstTimeSetFocus();
+        }
+    }
+
+    protected void firstTimeSetFocus() {
+        //scheduleZoomToFit();
+    }
+
+    @Override
+    public void dispose() {
+        // Remember to remove the added preference change listener
+        diagramPreferences.preferences.removePreferenceChangeListener(preferenceListener);
+
+        // Deactivate all contexts here because after this the context service
+        // in question will not be available.
+        contextUtil.deactivateAll();
+
+        disposed = true;
+        if (activation != null) {
+            activation.deactivate();
+            activation = null;
+        }
+        synchronizer.dispose();
+        ThreadUtils.asyncExec(c.getCanvasContext().getThreadAccess(), new Runnable() {
+            @Override
+            public void run() {
+                c.getCanvasContext().dispose();
+            }
+        });
+        sourceDiagram.dispose();
+        support.dispose();
+        super.dispose();
+    }
+
+    protected Resource getInputResource() {
+        return getResourceInput().getResource();
+    }
+
+    @Override
+    public IResourceEditorInput2 getResourceInput2() {
+        return (IResourceEditorInput2) getEditorInput();
+    }
+
+    @Override
+    public IResourceEditorInput getResourceInput() {
+        return (IResourceEditorInput) getEditorInput();
+    }
+
+    @Override
+    public void doSave(IProgressMonitor monitor) {
+    }
+
+    @Override
+    public void doSaveAs() {
+    }
+
+    @Override
+    public void init(IEditorSite site, IEditorInput input) throws PartInitException {
+        if (!(input instanceof IResourceEditorInput))
+            throw new PartInitException("Invalid input: must be IResourceEditorInput");
+        setSite(site);
+        setInput(input);
+        support = new ResourceEditorSupport(this);
+
+        // Set initial part name according to the name given by IEditorInput
+        setPartName(getEditorInput().getName());
+
+        Session session = SimanticsUI.peekSession();
+        if (session != null) {
+            Supplier<Boolean> disposedCallback = () -> disposed;
+            session.asyncRequest(
+                    new TitleRequest(site.getId(), getResourceInput2()),
+                    new TitleUpdater(site.getShell().getDisplay(), this::setPartName, disposedCallback));
+            session.asyncRequest(
+                    new ToolTipRequest(site.getId(), getResourceInput2()),
+                    new TitleUpdater(site.getShell().getDisplay(), this::setTitleToolTip, disposedCallback));
+        }
+
+    }
+
+    @Override
+    public boolean isDirty() {
+        return false;
+    }
+
+    @Override
+    public boolean isSaveAsAllowed() {
+        return false;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T getAdapter(Class<T> adapter) {
+        if (adapter == IPropertyPage.class)
+            return (T) new StandardPropertyPage(getSite());
+        if (adapter == IContentOutlinePage.class)
+            return (T) new DiagramOutlinePage(sessionContextProvider, getResourceInput2());
+        if (adapter == ILayersViewPage.class)
+            return (T) new DiagramLayersPage(sourceDiagram, canvasContext);
+        if (adapter == ICanvasContext.class)
+            return (T) canvasContext;
+        if (adapter == INode.class) {
+            if (canvasContext != null) {
+                INode node = canvasContext.getCanvasNode();
+                if (node != null)
+                    return (T) NodeUtil.getRootNode(node);
+            }
+            return null;
+        }
+        if (adapter == IDiagram.class)
+            return (T) sourceDiagram;
+        if (adapter == Session.class)
+            return (T) sessionContext.getSession();
+        return super.getAdapter(adapter);
+    }
+
+    protected void onCreated() {
+    }
+
+
+    private static Object BEGIN(String name) {
+        if (PROFILE) {
+            //return ThreadLog.BEGIN(name);
+        }
+        return null;
+    }
+
+    private static void END(Object task) {
+        if (PROFILE) {
+            //((Task) task).end();
+        }
+    }
+
+}