]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling.ui/src/org/simantics/modeling/ui/diagramEditor/DiagramViewer.java
Option to copy diagram selection to clipboard as SVG graphics
[simantics/platform.git] / bundles / org.simantics.modeling.ui / src / org / simantics / modeling / ui / diagramEditor / DiagramViewer.java
index 8ac45cf021d31bb181dfe772207f418d05c62a60..88d85cfbf6581dc996205ffdf0204d4e8e444e51 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.awt.dnd.DnDConstants;\r
-import java.util.Collections;\r
-import java.util.Set;\r
-import java.util.concurrent.TimeUnit;\r
-import java.util.function.Supplier;\r
-\r
-import org.eclipse.core.runtime.Assert;\r
-import org.eclipse.core.runtime.IAdaptable;\r
-import org.eclipse.core.runtime.IProgressMonitor;\r
-import org.eclipse.core.runtime.SubMonitor;\r
-import org.eclipse.core.runtime.jobs.Job;\r
-import org.eclipse.jface.action.IStatusLineManager;\r
-import org.eclipse.jface.resource.JFaceResources;\r
-import org.eclipse.jface.resource.LocalResourceManager;\r
-import org.eclipse.swt.widgets.Composite;\r
-import org.eclipse.swt.widgets.Display;\r
-import org.eclipse.ui.IEditorInput;\r
-import org.eclipse.ui.IEditorSite;\r
-import org.eclipse.ui.IWorkbenchPartSite;\r
-import org.eclipse.ui.contexts.IContextService;\r
-import org.eclipse.ui.views.contentoutline.IContentOutlinePage;\r
-import org.simantics.Simantics;\r
-import org.simantics.browsing.ui.model.browsecontexts.BrowseContext;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Session;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.common.primitiverequest.PossibleAdapter;\r
-import org.simantics.db.common.procedure.adapter.ListenerDelegate;\r
-import org.simantics.db.common.procedure.adapter.ListenerSupport;\r
-import org.simantics.db.common.request.ParametrizedRead;\r
-import org.simantics.db.common.request.WriteRequest;\r
-import org.simantics.db.common.utils.CommonDBUtils;\r
-import org.simantics.db.common.utils.TagUtil;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.layer0.request.combinations.Combinators;\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.DiagramTypeUtils;\r
-import org.simantics.diagram.adapter.FlagClassFactory;\r
-import org.simantics.diagram.adapter.GraphToDiagramSynchronizer;\r
-import org.simantics.diagram.adapter.IDiagramLoader;\r
-import org.simantics.diagram.connection.ModelledConnectionAdvisor;\r
-import org.simantics.diagram.handler.ConnectionCommandHandler;\r
-import org.simantics.diagram.handler.CopyPasteHandler;\r
-import org.simantics.diagram.handler.CopyPasteStrategy;\r
-import org.simantics.diagram.handler.DefaultCopyPasteStrategy;\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.PointerInteractor2;\r
-import org.simantics.diagram.participant.SGFocusParticipant;\r
-import org.simantics.diagram.query.DiagramRequests;\r
-import org.simantics.diagram.runtime.RuntimeDiagramManager;\r
-import org.simantics.diagram.stubs.DiagramResource;\r
-import org.simantics.diagram.symbolcontribution.SymbolProviderFactory;\r
-import org.simantics.diagram.synchronization.CopyAdvisor;\r
-import org.simantics.diagram.synchronization.IModifiableSynchronizationContext;\r
-import org.simantics.diagram.synchronization.SynchronizationHints;\r
-import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;\r
-import org.simantics.diagram.ui.DiagramModelHints;\r
-import org.simantics.diagram.ui.SWTPopupMenuParticipant;\r
-import org.simantics.diagram.ui.SWTPopupMenuParticipantAwt;\r
-import org.simantics.diagram.ui.WorkbenchSelectionProvider;\r
-import org.simantics.g2d.canvas.Hints;\r
-import org.simantics.g2d.canvas.ICanvasContext;\r
-import org.simantics.g2d.canvas.ICanvasParticipant;\r
-import org.simantics.g2d.canvas.impl.CanvasContext;\r
-import org.simantics.g2d.chassis.AWTChassis;\r
-import org.simantics.g2d.chassis.ICanvasChassis;\r
-import org.simantics.g2d.chassis.IChassisListener;\r
-import org.simantics.g2d.chassis.SWTChassis;\r
-import org.simantics.g2d.connection.IConnectionAdvisor;\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.handler.PickRequest.PickFilter;\r
-import org.simantics.g2d.diagram.impl.Diagram;\r
-import org.simantics.g2d.diagram.participant.DelayedBatchElementPainter;\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.IElement;\r
-import org.simantics.g2d.element.IElementClassProvider;\r
-import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;\r
-import org.simantics.g2d.elementclass.connection.ConnectionClass;\r
-import org.simantics.g2d.page.DiagramDesc;\r
-import org.simantics.g2d.participant.BackgroundPainter;\r
-import org.simantics.g2d.participant.CanvasBoundsParticipant;\r
-import org.simantics.g2d.participant.CanvasGrab;\r
-import org.simantics.g2d.participant.GridPainter;\r
-import org.simantics.g2d.participant.KeyUtil;\r
-import org.simantics.g2d.participant.MouseUtil;\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.RenderingQualityInteractor;\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.WorkbenchStatusLine;\r
-import org.simantics.g2d.participant.ZoomToAreaHandler;\r
-import org.simantics.g2d.tooltip.TerminalTooltipParticipant;\r
-import org.simantics.g2d.utils.CanvasUtils;\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.ComponentCopyAdvisor;\r
-import org.simantics.modeling.mapping.ElementCopyAdvisor;\r
-import org.simantics.modeling.mapping.MappedElementCopyAdvisor;\r
-import org.simantics.modeling.mapping.ModelingSynchronizationHints;\r
-import org.simantics.modeling.ui.diagramEditor.handlers.LinkBrowsingHandler;\r
-import org.simantics.modeling.ui.diagramEditor.handlers.StructuralBrowsingHandler;\r
-import org.simantics.modeling.ui.preferences.DiagramPreferenceUtil;\r
-import org.simantics.modeling.ui.preferences.DiagramPreferences;\r
-import org.simantics.project.ontology.ProjectResource;\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.structural.stubs.StructuralResource2;\r
-import org.simantics.structural2.modelingRules.IModelingRules;\r
-import org.simantics.ui.SimanticsUI;\r
-import org.simantics.ui.jobs.SessionGarbageCollectorJob;\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.TitleRequest;\r
-import org.simantics.ui.workbench.TitleUpdater;\r
-import org.simantics.ui.workbench.ToolTipRequest;\r
-import org.simantics.ui.workbench.editor.input.InputValidationCombinators;\r
-import org.simantics.utils.DataContainer;\r
-import org.simantics.utils.datastructures.Callback;\r
-import org.simantics.utils.datastructures.hints.HintContext;\r
-import org.simantics.utils.datastructures.hints.HintListenerAdapter;\r
-import org.simantics.utils.datastructures.hints.IHintContext;\r
-import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
-import org.simantics.utils.datastructures.hints.IHintListener;\r
-import org.simantics.utils.datastructures.hints.IHintObservable;\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
-import org.simantics.utils.ui.ExceptionUtils;\r
-\r
-import com.kitfox.svg.SVGCache;\r
-\r
-/**\r
- * @author Toni Kalajainen\r
- * @author Tuukka Lehtonen\r
- */\r
-public class DiagramViewer \r
-  //extends EditorPart implements IResourceEditorPart2, \r
-    implements ListenerSupport, IAdaptable {\r
-\r
-    public interface DiagramViewerHost {\r
-        void doSetPartName(String name);\r
-        void doSetTitleToolTip(String name);\r
-    }\r
-\r
-    public static final String                     DIAGRAMMING_CONTEXT      = "org.simantics.modeling.ui.diagramming";\r
-    private static final String                     PREFERENCE_VIRTUAL_GRAPH = "preferences";\r
-\r
-    private static final boolean                    PROFILE                  = false;\r
-\r
-    ParametrizedRead<IResourceEditorInput, Boolean> INPUT_VALIDATOR =\r
-        Combinators.compose(\r
-                InputValidationCombinators.or(\r
-                        // Normal configuration diagrams of a model\r
-                        Combinators.compose(\r
-                                InputValidationCombinators.hasURI(),\r
-                                InputValidationCombinators.partialFunction(ModelingResources.URIs.DiagramToComposite)\r
-                        ),\r
-                        // Configuration diagrams of a component type\r
-                        Combinators.compose(\r
-                                InputValidationCombinators.hasURI(),\r
-                                Combinators.compose(\r
-                                        InputValidationCombinators.partialFunction(StructuralResource2.URIs.Defines),\r
-                                        InputValidationCombinators.partialFunction(ModelingResources.URIs.DiagramToComposite)\r
-                                )\r
-                        )\r
-                ),\r
-                InputValidationCombinators.extractInputResource()\r
-        );\r
-\r
-    protected EditorState                editorState;\r
-\r
-    protected boolean                    disposed           = false;\r
-    protected IThreadWorkQueue           swt;\r
-    protected IStatusLineManager         statusLineManager;\r
-    protected Display                    display;\r
-    protected LocalResourceManager       resourceManager;\r
-    protected SWTChassis                 c;\r
-    protected IDiagram                   sourceDiagram;\r
-    protected DataContainer<IDiagram>    sourceDiagramContainer;\r
-    protected CanvasContext              canvasContext;\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
-    protected SWTPopupMenuParticipant    popupMenuParticipant;\r
-    \r
-    protected DiagramPreferences         diagramPreferences;\r
-    protected DiagramDesc                diagramDesc;\r
-    protected GridSnapAdvisor            snapAdvisor;\r
-\r
-    private RuntimeDiagramManager        runtimeDiagramManager;\r
-\r
-    /**\r
-     * Set externally in\r
-     * {@link #init(DiagramViewerHost, IEditorSite, IEditorInput, DataContainer, WorkbenchSelectionProvider)}\r
-     * .\r
-     */\r
-    protected WorkbenchSelectionProvider selectionProvider;\r
-\r
-    public Resource getRuntime() {\r
-        RuntimeDiagramManager rtdm = runtimeDiagramManager;\r
-        return (rtdm == null) ? null : rtdm.getRuntimeDiagram();\r
-    }\r
-\r
-    public ParametrizedRead<IResourceEditorInput, Boolean> getInputValidator() {\r
-        return INPUT_VALIDATOR;\r
-    }\r
-\r
-    protected void addDropParticipants(ICanvasContext ctx) {\r
-        ctx.getDefaultHintContext().setHint(Hints.KEY_ALLOWED_DRAG_ACTIONS, DnDConstants.ACTION_COPY);\r
-\r
-        ctx.add(new PopulateElementDropParticipant(synchronizer, getSite()));\r
-        ctx.add(new PopulateElementMonitorDropParticipant(synchronizer, 0.5, 0.5));\r
-    }\r
-\r
-    protected CopyPasteStrategy getCopyPasteStrategy() {\r
-               try {\r
-                       CopyPasteStrategy cpStrategy = Simantics.getSession().syncRequest(new PossibleAdapter<CopyPasteStrategy>(getInputResource(), CopyPasteStrategy.class));\r
-                       if(cpStrategy != null) return cpStrategy;\r
-               } catch (DatabaseException e) {\r
-               }\r
-               return getDefaultCopyPasteStrategy();\r
-    }\r
-    \r
-    protected CopyPasteStrategy getDefaultCopyPasteStrategy() {\r
-       return new DefaultCopyPasteStrategy();\r
-    }\r
-\r
-    protected CopyAdvisor getCopyAdvisor() {\r
-               try {\r
-                       CopyAdvisor advisor = Simantics.getSession().syncRequest(new PossibleAdapter<CopyAdvisor>(getInputResource(), CopyAdvisor.class));\r
-                       if(advisor != null) return advisor;\r
-               } catch (DatabaseException e) {\r
-               }\r
-               return new MappedElementCopyAdvisor(new ElementCopyAdvisor(), new ComponentCopyAdvisor());\r
-    }\r
-    \r
-    /**\r
-     * @param ctx\r
-     * TODO: change argument from CanvasContext to ICanvasContext\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(getCopyPasteStrategy(), statusLineManager).setWorkbenchSite(getEditorSite()));\r
-        ctx.add(new ConnectionCommandHandler());\r
-    }\r
-\r
-    protected void addPopupmenu(ICanvasContext ctx) {\r
-        ctx.add(popupMenuParticipant);\r
-    }\r
-\r
-    protected void addWorkbenchSelectionProvider(ICanvasContext ctx) {\r
-        if (selectionProvider != null)\r
-            ctx.add(selectionProvider);\r
-    }\r
-\r
-    protected void addViewManipulationParticipants(CanvasContext ctx) {\r
-        ctx.add(new PanZoomRotateHandler());\r
-        //ctx.add(new MousePanZoomInteractor());\r
-        //ctx.add(new MultitouchPanZoomRotateInteractor());\r
-        // ctx.add( new OrientationRestorer() );\r
-        ctx.add(new ZoomToAreaHandler());\r
-    }\r
-\r
-    protected void addDiagramParticipants(ICanvasContext ctx) {\r
-        ctx.add(new ZOrderHandler());\r
-        ctx.add(getPointerInteractor());\r
-        ctx.add(new ElementInteractor());\r
-        ctx.add(new Selection());\r
-        ctx.add(new DiagramParticipant());\r
-        ctx.add(new ElementPainter());\r
-        //ctx.add(new ElementHeartbeater());\r
-        //ctx.add(new ZoomTransitionParticipant(TransitionFunction.SIGMOID));\r
-        //ctx.add(new TooltipParticipant());\r
-        ctx.add(new TerminalTooltipParticipant());\r
-    }\r
-\r
-    protected void addPainterParticipants(ICanvasContext ctx) {\r
-        ctx.add(new RenderingQualityInteractor());\r
-        ctx.add(new TerminalPainter(true, true, false, true));\r
-        ctx.add(new DelayedBatchElementPainter(PickFilter.FILTER_MONITORS, 500, TimeUnit.MILLISECONDS));\r
-    }\r
-\r
-    protected void addStructureParticipants(ICanvasContext ctx) {\r
-        addWorkbenchSelectionProvider(ctx);\r
-        // Add visual browsing capabilities for structural models\r
-        ctx.add(new StructuralBrowsingHandler(getSite(), sessionContext, getResourceInput2()));\r
-        ctx.add(new LinkBrowsingHandler(getSite(), this, sessionContext));\r
-    }\r
-\r
-    /**\r
-     * Override to add any diagram/canvas participants to the canvas context\r
-     * initialized for the editor.\r
-     * \r
-     * @param ctx\r
-     */\r
-    protected void addOtherParticipants(CanvasContext ctx) {\r
-    }\r
-\r
-    public static Set<String> defaultPropertyBrowseContexts = Collections.singleton(ProjectResource.URIs.ProjectBrowseContext);\r
-\r
-    protected Set<String> getPropertyPageContexts() {\r
-        try {\r
-            return BrowseContext.getBrowseContextClosure(SimanticsUI.getSession(), defaultPropertyBrowseContexts);\r
-        } catch (DatabaseException e) {\r
-            ExceptionUtils.logAndShowError("Failed to load modeled browse contexts for property page, see exception for details.", e);\r
-            return defaultPropertyBrowseContexts;\r
-        }\r
-    }\r
-\r
-    protected IPropertyPage createPropertyPage(IWorkbenchPartSite site, Set<String> contexts) {\r
-        return new StandardPropertyPage(site, contexts);\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
-        host.doSetPartName(name);\r
-        host.doSetTitleToolTip(name);\r
-    }\r
-\r
-    class ChassisListener implements IChassisListener {\r
-        @Override\r
-        public void chassisClosed(ICanvasChassis sender) {\r
-            // Prevent deadlock while disposing which using syncExec would result in.\r
-            final ICanvasContext ctx = canvasContext;\r
-            ThreadUtils.asyncExec(ctx.getThreadAccess(), new Runnable() {\r
-                @Override\r
-                public void run() {\r
-                    if (ctx != null) {\r
-                        saveEditorState(ctx);\r
-                        ctx.getHintStack().removeKeyHintListener(GridPainter.KEY_GRID_ENABLED, canvasHintListener);\r
-                        ctx.getHintStack().removeKeyHintListener(RulerPainter.KEY_RULER_ENABLED, canvasHintListener);\r
-                        final AWTChassis awtChassis = c.getAWTComponent();\r
-                        if (awtChassis != null)\r
-                            awtChassis.setCanvasContext(null);\r
-                        ctx.dispose();\r
-                    }\r
-\r
-                    if (sourceDiagramContainer != null) {\r
-                        sourceDiagramContainer.set(null);\r
-                        sourceDiagramContainer = null;\r
-                    }\r
-\r
-                    if (sourceDiagram != null)\r
-                        sourceDiagram.dispose();\r
-\r
-                    if(synchronizer != null) {\r
-                        synchronizer.dispose();\r
-                        // Let GC work.\r
-                        synchronizer = null;\r
-                    }\r
-\r
-                    if (runtimeDiagramManager != null) {\r
-                        runtimeDiagramManager.dispose();\r
-                        runtimeDiagramManager = null;\r
-                    }\r
-                }\r
-            });\r
-            c.removeChassisListener(ChassisListener.this);\r
-        }\r
-    }\r
-\r
-    protected void createChassis(Composite parent) {\r
-        resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent);\r
-        c = new SWTChassis(parent, 0);\r
-\r
-        Object task = BEGIN("DV.precreateParticipants");\r
-        createCustomParticipants();\r
-        END(task);\r
-\r
-        c.populate(component -> {\r
-            if (!disposed) {\r
-                c.addChassisListener(new ChassisListener());\r
-                initializeCanvas();\r
-            }\r
-        });\r
-    }\r
-\r
-    protected void beforeSetCanvasContext(ICanvasContext canvasContext2) {\r
-    }\r
-\r
-    /**\r
-     * Invoke this only from the AWT thread.\r
-     * @param context\r
-     */\r
-    protected void setCanvasContext(ICanvasContext context) {\r
-        // Cannot directly invoke SWTChassis.setCanvasContext only because it\r
-        // needs to be invoked in the SWT thread and AWTChassis.setCanvasContext in the\r
-        // AWT thread, but directly invoking SWTChassis.setCanvasContext would call both\r
-        // in the SWT thread which would cause synchronous scheduling of AWT\r
-        // runnables which is always a potential source of deadlocks.\r
-        c.getAWTComponent().setCanvasContext(canvasContext);\r
-        swt.asyncExec(new Runnable() {\r
-            @Override\r
-            public void run() {\r
-                if (!c.isDisposed())\r
-                    // For AWT, this is a no-operation.\r
-                    c.setCanvasContext(canvasContext);\r
-            }\r
-        });\r
-    }\r
-\r
-    public void createPartControl(Composite parent) {\r
-        //ProfileObserver.begin = System.nanoTime();\r
-        display = parent.getDisplay(); \r
-        swt = SWTThread.getThreadAccess(display);\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
-        try {\r
-            this.runtimeDiagramManager = RuntimeDiagramManager.track(sessionContext.getSession(), diagramResource, getEditorInput(), this);\r
-\r
-            // Create the canvas context here before finishing createPartControl\r
-            // to give DiagramViewerActionContributor a chance to work.\r
-            // The context can be created in SWT thread without scheduling\r
-            // to the context thread and having potential deadlocks.\r
-            IThreadWorkQueue thread = AWTThread.getThreadAccess();\r
-            this.canvasContext = new CanvasContext(thread);\r
-            this.canvasContext.setLocked(true);\r
-\r
-            task = BEGIN("DV.createChassis");\r
-            createChassis(parent);\r
-            END(task);\r
-        } catch (DatabaseException e) {\r
-            ErrorLogger.defaultLogError(e);\r
-        }\r
-    }\r
-\r
-\r
-       /**\r
-     * A method invoked before chassis construction for creating such\r
-     * {@link ICanvasParticipant}s that need to be constructed in the SWT\r
-     * thread.\r
-     * \r
-     * Use it for creating any such canvas participants during the viewer \r
-     * construction and add them to the {@link ICanvasContext} later on from\r
-     * the AWT thread.\r
-     */\r
-    protected void createCustomParticipants() {\r
-       if (SimanticsUI.isLinuxGTK()) {\r
-               popupMenuParticipant = new SWTPopupMenuParticipantAwt(getSite(), c, display, getPopupId());\r
-       } else {\r
-               popupMenuParticipant = new SWTPopupMenuParticipant(getSite(), c, display, getPopupId());\r
-       }\r
-    }\r
-\r
-    /**\r
-     * Invoke this only from the AWT thread.\r
-     */\r
-    protected void initializeCanvas() {\r
-        Object canvasInit = BEGIN("DV.canvasInitialization");\r
-\r
-        Object task = BEGIN("DV.createViewerCanvas");\r
-        initializeCanvasContext(canvasContext);\r
-        END(task);\r
-\r
-        beforeSetCanvasContext(canvasContext);\r
-        //FullscreenUtils.addFullScreenHandler(canvasContext, s, canvasProvider);\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
-        // Changes in ruler/grid activity shall be written as\r
-        // workspace-persistent diagram-specific preferences.\r
-        canvasContext.getHintStack().addKeyHintListener(GridPainter.KEY_GRID_ENABLED, canvasHintListener);\r
-        canvasContext.getHintStack().addKeyHintListener(RulerPainter.KEY_RULER_ENABLED, canvasHintListener);\r
-\r
-        task = BEGIN("DV.setCanvasContext");\r
-        setCanvasContext(canvasContext);\r
-        END(task);\r
-\r
-        // Finish loading in a worker thread because it may be a time consuming\r
-        // process to load a large diagram and we don't want unnecessary AWT\r
-        // thread contention.\r
-        Job loadJob = new DiagramViewerLoadJob(this);\r
-        loadJob.schedule();\r
-\r
-        END(canvasInit);\r
-    }\r
-\r
-    protected void activateUiContexts(ContextUtil util) {\r
-        util.activate(DIAGRAMMING_CONTEXT);\r
-    }\r
-\r
-    /**\r
-     * @param monitor the progress monitor to use for reporting progress to the\r
-     *        user. It is the caller's responsibility to call done() on the\r
-     *        given monitor. Accepts <code>null</code>, indicating that no\r
-     *        progress should be reported and that the operation cannot be\r
-     *        cancelled.\r
-     */\r
-    protected void performActivation(IProgressMonitor monitor) {\r
-        SubMonitor progress = SubMonitor.convert(monitor, "Activate Mapping", 100);\r
-        IActivationManager activationManager = sessionContext.getSession().peekService(IActivationManager.class);\r
-        if (activationManager != null) {\r
-            activation = activationManager.activate(diagramResource);\r
-        }\r
-        progress.worked(100);\r
-    }\r
-\r
-    protected void onCreated() {\r
-    }\r
-\r
-    /**\r
-     * @param diagram\r
-     */\r
-    protected void scheduleZoomToFit(IDiagram diagram) {\r
-        if (diagram == null)\r
-            throw new IllegalStateException("diagram is null");\r
-\r
-        CanvasUtils.scheduleZoomToFit(swt, () -> disposed, canvasContext, diagram);\r
-    }\r
-\r
-    /**\r
-     * Subclasses may override but should always invoke super.\r
-     * \r
-     * @param diagram\r
-     * @param initialHints\r
-     * @throws DatabaseException\r
-     */\r
-    protected void fillInitialDiagramHints(Resource diagram, IHintContext initialHints) throws DatabaseException {\r
-        IModelingRules modelingRules = sessionContext.getSession().syncRequest(\r
-                DiagramRequests.getModelingRules(diagram, null));\r
-        if (modelingRules != null) {\r
-            initialHints.setHint(DiagramModelHints.KEY_MODELING_RULES, modelingRules);\r
-            initialHints.setHint(DiagramHints.CONNECTION_ADVISOR,\r
-                    getConnectionAdvisor(modelingRules, sessionContext.getSession()));\r
-        }\r
-\r
-        initialHints.setHint(SynchronizationHints.COPY_ADVISOR, getCopyAdvisor());\r
-        initialHints.setHint(DiagramHints.KEY_USE_CONNECTION_FLAGS, Boolean.TRUE);\r
-        initialHints.setHint(DiagramHints.KEY_ALLOW_CONNECTION_BRANCHING, Boolean.TRUE);\r
-        initialHints.setHint(DiagramHints.KEY_ALLOW_ROUTE_POINTS, Boolean.TRUE);\r
-    }\r
-\r
-    /**\r
-     * @param monitor the progress monitor to use for reporting progress to the\r
-     *        user. It is the caller's responsibility to call done() on the\r
-     *        given monitor. Accepts <code>null</code>, indicating that no\r
-     *        progress should be reported and that the operation cannot be\r
-     *        cancelled.\r
-     * @param r\r
-     * @return\r
-     * @throws DatabaseException\r
-     */\r
-    protected IDiagram loadDiagram(IProgressMonitor monitor, final Resource r) throws DatabaseException {\r
-        // Pre-load modeling rules and possibly other hints too since they are\r
-        // needed already while loading the diagram contents.\r
-        IHintContext initialHints = new HintContext();\r
-        fillInitialDiagramHints(r, initialHints);\r
-        IDiagram d = loadDiagram(monitor, r, initialHints);\r
-        return d;\r
-    }\r
-\r
-    /**\r
-     * @param monitor the progress monitor to use for reporting progress to the\r
-     *        user. It is the caller's responsibility to call done() on the\r
-     *        given monitor. Accepts <code>null</code>, indicating that no\r
-     *        progress should be reported and that the operation cannot be\r
-     *        cancelled.\r
-     * @param diagram\r
-     * @param initialHints\r
-     * @return\r
-     * @throws DatabaseException\r
-     */\r
-    protected IDiagram loadDiagram(IProgressMonitor monitor, Resource diagram, IHintContext initialHints) throws DatabaseException {\r
-       RuntimeDiagramManager rtdm = runtimeDiagramManager;\r
-       Resource runtimeDiagram = rtdm != null ? rtdm.getRuntimeDiagram() : null;\r
-       IDiagramLoader loader = synchronizer;\r
-       if (rtdm == null || runtimeDiagram == null || loader == null)\r
-               return null;\r
-        IDiagram d = sessionContext.getSession().syncRequest(\r
-                DiagramRequests.loadDiagram(monitor, getResourceInput2().getModel(null), diagram,\r
-                        runtimeDiagram, null, loader, initialHints));\r
-        return d;\r
-    }\r
-\r
-    protected void beforeSetDiagram(IDiagram diagram) {\r
-    }\r
-\r
-    protected PointerInteractor getPointerInteractor() {\r
-        return new PointerInteractor2(true, true, true, false, true, false, synchronizer.getElementClassProvider());\r
-    }\r
-\r
-    protected IConnectionAdvisor getConnectionAdvisor(IModelingRules modelingRules, Session session) {\r
-        return new ModelledConnectionAdvisor(modelingRules, sessionContext.getSession());\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, ConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(dr.RouteGraphConnection)),\r
-                ElementClasses.FLAG, FlagClassFactory.createFlagClass(dr.Flag, dr.Flag_Terminal)\r
-        );\r
-    }\r
-    \r
-    protected SimpleElementTransformHandler getTransformHandler() {\r
-       return new SimpleElementTransformHandler(true, true, true);\r
-    }\r
-\r
-    public void initializeCanvasContext(CanvasContext ctx) {\r
-        IHintContext h = ctx.getDefaultHintContext();\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
-        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
-        // 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 WorkbenchStatusLine(statusLineManager));\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, 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
-        addViewManipulationParticipants(ctx);\r
-\r
-        ctx.add(getTransformHandler());\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
-        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.9f, 0.9f, 0.9f));\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
-        addDiagramParticipants(ctx);\r
-        addPainterParticipants(ctx);\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
-        h.setHint(GridPainter.KEY_GRID_SIZE, snapResolution);\r
-        h.setHint(GridPainter.KEY_GRID_ENABLED, Boolean.FALSE);\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
-        addOtherParticipants(ctx);\r
-\r
-        ctx.assertParticipantDependencies();\r
-        ctx.setLocked(false);\r
-    }\r
-\r
-    protected void loadPageSettings(ICanvasContext ctx) {\r
-        DiagramDesc diagramDesc = null;\r
-\r
-        // load diagram page configuration\r
-        if (diagramResource != null) {\r
-            try {\r
-                diagramDesc = sessionContext.getSession().syncRequest(DiagramRequests.getDiagramDesc(diagramResource));\r
-            } catch (DatabaseException e) {\r
-                ErrorLogger.defaultLogError(e);\r
-            }\r
-        }\r
-\r
-        if (diagramDesc == null) {\r
-            // Take page description from the preferences if nothing else is available.\r
-            final DiagramDesc desc = diagramDesc = diagramPreferences.getDiagramDesc();\r
-\r
-            // Write page configuration to graph\r
-            sessionContext.getSession().asyncRequest(new WriteRequest() {\r
-                @Override\r
-                public void perform(WriteGraph graph) throws DatabaseException {\r
-                       CommonDBUtils.selectClusterSet(graph, diagramResource);\r
-                    DiagramGraphUtil.setDiagramDesc(graph, diagramResource, desc);\r
-                }\r
-            }, new Callback<DatabaseException>() {\r
-                @Override\r
-                public void run(DatabaseException parameter) {\r
-                    if (parameter != null)\r
-                        ErrorLogger.defaultLogError("Failed to write default diagram page description to database, see exception for details", parameter);\r
-                }\r
-            });\r
-        }\r
-\r
-        setDiagramDesc(ctx, diagramDesc);\r
-\r
-        // Create a listener to react to page setting changes.\r
-        sessionContext.getSession().asyncRequest(DiagramRequests.getDiagramDesc(diagramResource),\r
-                new ListenerDelegate<DiagramDesc>(this) {\r
-            @Override\r
-            public void execute(final DiagramDesc result) {\r
-                if (result != null && canvasContext != null) {\r
-                    ThreadUtils.asyncExec(canvasContext.getThreadAccess(), new Runnable() {\r
-                        @Override\r
-                        public void run() {\r
-                            if (!disposed)\r
-                                setDiagramDesc(canvasContext, result);\r
-                        }\r
-                    });\r
-                }\r
-            }\r
-        });\r
-    }\r
-\r
-    protected void setDiagramDesc(ICanvasContext ctx, DiagramDesc diagramDesc) {\r
-        if (diagramDesc == null)\r
-            throw new NullPointerException("null diagram desc");\r
-\r
-        if (diagramDesc.equals(this.diagramDesc))\r
-            return;\r
-\r
-        this.diagramDesc = diagramDesc;\r
-        IHintContext hints = ctx.getDefaultHintContext();\r
-        hints.setHint(Hints.KEY_PAGE_DESC, diagramDesc.getPageDesc());\r
-        hints.setHint(Hints.KEY_DISPLAY_PAGE, diagramDesc.isPageBordersVisible());\r
-        hints.setHint(Hints.KEY_DISPLAY_MARGINS, diagramDesc.isMarginsVisible());\r
-        hints.setHint(GridPainter.KEY_GRID_ENABLED, diagramDesc.isGridVisible());\r
-        hints.setHint(RulerPainter.KEY_RULER_ENABLED, diagramDesc.isRulerVisible());\r
-        snapAdvisor.setResolution(diagramDesc.getGridSize());\r
-        hints.setHint(GridPainter.KEY_GRID_SIZE, diagramDesc.getGridSize());\r
-    }\r
-\r
-    /**\r
-     * Must be invoked from the AWT thread only.\r
-     * \r
-     * @param state\r
-     * @param ctx\r
-     */\r
-    protected void applyEditorState(final EditorState state, final ICanvasContext ctx) {\r
-        final IDiagram diagram = ctx.getHintStack().getHint(DiagramHints.KEY_DIAGRAM);\r
-\r
-        if (state.viewTransform != null && state.viewTransform.getDeterminant() != 0) {\r
-            for (PanZoomRotateHandler h : ctx.getItemsByClass(PanZoomRotateHandler.class)) {\r
-                h.setTransform(state.viewTransform);\r
-            }\r
-        }\r
-\r
-        if (diagram != null) {\r
-            if (state.viewTransform != null)\r
-                diagram.removeHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT);\r
-\r
-            if (state.toolMode != null)\r
-                ctx.getDefaultHintContext().setHint(Hints.KEY_TOOL, state.toToolMode());\r
-            else\r
-                ctx.getDefaultHintContext().setHint(Hints.KEY_TOOL, Hints.POINTERTOOL);\r
-\r
-            final Set<IElement> selected = DiagramEditorStates.toElements(state.selection, diagram);\r
-            if (!selected.isEmpty()) {\r
-                for (Selection s : ctx.getItemsByClass(Selection.class)) {\r
-                    s.setSelection(0, selected);\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
-    protected EditorState getSavedEditorState(ICanvasContext ctx) {\r
-        return DiagramEditorStates.toEditorState(ctx, true, true, true);\r
-    }\r
-\r
-    protected void saveEditorState(ICanvasContext ctx) {\r
-        DiagramEditorStates.saveEditorState(PREFERENCE_VIRTUAL_GRAPH, diagramResource, getSavedEditorState(ctx) , DiagramViewer.this);\r
-    }\r
-\r
-    private boolean firstFocus = true;\r
-\r
-    public void setFocus() {\r
-       \r
-       if(c != null) {\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
-       \r
-    }\r
-\r
-    protected void firstTimeSetFocus() {\r
-        // [Tuukka@2010-02-11]\r
-        // Removed since this is actually a workaround for multi-page editors.\r
-        //scheduleZoomToFit();\r
-    }\r
-\r
-    public void dispose() {\r
-        // Deactivate all contexts here because after this the context service\r
-        // in question will not be available.\r
-        if (contextUtil != null) {\r
-            contextUtil.deactivateAll();\r
-        }\r
-\r
-        disposed = true;\r
-        if (activation != null) {\r
-            activation.deactivate();\r
-            activation = null;\r
-        }\r
-\r
-        if (resourceManager != null) {\r
-               resourceManager.dispose();\r
-               resourceManager = null;\r
-        }\r
-        //super.dispose();\r
-    }\r
-\r
-    protected Resource getInputResource() {\r
-        return getResourceInput().getResource();\r
-    }\r
-\r
-    public IResourceEditorInput getResourceInput() {\r
-        return (IResourceEditorInput) getEditorInput();\r
-    }\r
-\r
-    public IResourceEditorInput2 getResourceInput2() {\r
-        return (IResourceEditorInput2) getEditorInput();\r
-    }\r
-\r
-    public void init(DiagramViewerHost _host, IEditorSite site, IEditorInput input, DataContainer<IDiagram> diagramContainer, WorkbenchSelectionProvider selectionProvider) {\r
-        if (!(input instanceof IResourceEditorInput))\r
-            throw new RuntimeException("Invalid input: must be IResourceEditorInput");\r
-\r
-        setHost(_host);\r
-        setSite(site);\r
-        setInput(input);\r
-        this.sourceDiagramContainer = diagramContainer;\r
-        this.selectionProvider = selectionProvider;\r
-\r
-        // Set initial part name according to the name given by IEditorInput\r
-        host.doSetPartName(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(), getResourceInput()),\r
-                    new TitleUpdater(site.getShell().getDisplay(), host::doSetPartName, disposedCallback));\r
-            session.asyncRequest(\r
-                    new ToolTipRequest(site.getId(), getResourceInput()),\r
-                    new TitleUpdater(site.getShell().getDisplay(), host::doSetTitleToolTip, disposedCallback));\r
-        }\r
-\r
-        try {\r
-            // Read previous editor state from the database\r
-            editorState = DiagramEditorStates.readEditorState(getInputResource());\r
-        } catch (DatabaseException e) {\r
-            exception(e);\r
-        }\r
-    }\r
-\r
-    @SuppressWarnings("unchecked")\r
-    @Override\r
-    public <T> T getAdapter(Class<T> adapter) {\r
-//        System.out.println("diagramViewer getAdapter " + adapter);\r
-        // Property view support\r
-        if (adapter == IPropertyPage.class)\r
-            return (T) createPropertyPage(getSite(), getPropertyPageContexts());\r
-        // Provide symbols for the editor\r
-        if (adapter == SymbolProviderFactory.class) {\r
-            try {\r
-                return (T) DiagramTypeUtils.readSymbolProviderFactory(sessionContext.getSession(), diagramResource);\r
-            } catch (DatabaseException e) {\r
-                ErrorLogger.defaultLogError(getClass() + " failed to adapt to SymbolProviderFactory, see exception for details.", e);\r
-                return null;\r
-            }\r
-        }\r
-        // Outline view support\r
-        if (adapter == IContentOutlinePage.class)\r
-            return (T) new DiagramOutlinePage(sessionContextProvider, getResourceInput2());\r
-        // Role view support\r
-        if (adapter == ILayersViewPage.class)\r
-            return (T) new DiagramLayersPage(sourceDiagram, canvasContext);\r
-        // Support external steering of the diagram canvas, zooming etc.\r
-        if (adapter == ICanvasContext.class)\r
-            return (T) canvasContext;\r
-        // Support scene graph debugger view\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
-        // Support retrieval of the current diagram.\r
-        if (adapter == IDiagram.class)\r
-            return (T) sourceDiagram;\r
-        // Why is this here ??\r
-        if (adapter == Session.class)\r
-            return (T) sessionContext.getSession();\r
-        if(adapter == RuntimeDiagramManager.class)\r
-            return (T) runtimeDiagramManager;\r
-        if (adapter == Resource.class)\r
-            return (T) getRuntime();\r
-        if (adapter == ICanvasChassis.class)\r
-            return (T) c;\r
-\r
-        return null;\r
-    }\r
-\r
-    //-------------------------------------------------------------------------\r
-    // Profiling aid\r
-\r
-    protected static Object BEGIN(String name) {\r
-        if (PROFILE) {\r
-            //return ThreadLog.BEGIN(name);\r
-        }\r
-        return null;\r
-    }\r
-\r
-    protected static void END(Object task) {\r
-        if (PROFILE) {\r
-            //((Task) task).end();\r
-        }\r
-    }\r
-\r
-    //-------------------------------------------------------------------------\r
-    // implement ListenerSupport\r
-\r
-    @Override\r
-    public void exception(Throwable t) {\r
-        ErrorLogger.defaultLogError(t);\r
-    }\r
-\r
-    @Override\r
-    public boolean isDisposed() {\r
-        return disposed;\r
-    }\r
-\r
-    protected void collectGarbage() {\r
-        SessionGarbageCollectorJob.getInstance().schedule(0);\r
-        AWTThread.getThreadAccess().asyncExec(new Runnable() {\r
-            @Override\r
-            public void run() {\r
-                //System.out.println("BEFORE CLEAR: " + SVGCache.getSVGUniverse().report());\r
-                SVGCache.getSVGUniverse().clearUnreferenced();\r
-                //System.out.println("AFTER CLEAR: " + SVGCache.getSVGUniverse().report());\r
-            }\r
-        });\r
-    }\r
-\r
-    //-------------------------------------------------------------------------\r
-    // Listener for certain canvas context hint changes\r
-\r
-    IHintListener canvasHintListener = new HintListenerAdapter() {\r
-        @Override\r
-        public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {\r
-            if (key == GridPainter.KEY_GRID_ENABLED) {\r
-                boolean v = Boolean.TRUE.equals(newValue);\r
-                if (diagramDesc.isGridVisible() != v)\r
-                    setGlobalPreference(DiagramResource.URIs.DisplayGrid, v);\r
-            } else if (key == RulerPainter.KEY_RULER_ENABLED) {\r
-                boolean v = Boolean.TRUE.equals(newValue);\r
-                if (diagramDesc.isRulerVisible() != v)\r
-                    setGlobalPreference(DiagramResource.URIs.DisplayRuler, v);\r
-            }\r
-        }\r
-    };\r
-\r
-    private <T> void setGlobalPreference(final String preferenceURI, boolean value) {\r
-        TagUtil.execute(Simantics.getSession(), PREFERENCE_VIRTUAL_GRAPH, preferenceURI, value, Simantics.getProjectResource());\r
-    }\r
-\r
-    /*\r
-     * --------------------------------------------------------------------\r
-     * Changes related to removal of EditorPart extension from here on down\r
-     * --------------------------------------------------------------------\r
-     */\r
-\r
-    private IWorkbenchPartSite partSite;\r
-    private DiagramViewerHost host;\r
-    private IEditorInput editorInput = null;\r
-\r
-    /* (non-Javadoc)\r
-     * Method declared on IWorkbenchPart.\r
-     */\r
-    public IWorkbenchPartSite getSite() {\r
-        return partSite;\r
-    }\r
-\r
-    public IEditorSite getEditorSite() {\r
-        return (IEditorSite) getSite();\r
-    }\r
-\r
-    public IEditorInput getEditorInput() {\r
-        return editorInput;\r
-    }\r
-\r
-//    protected void setPartName(String partName) {\r
-////        if (compatibilityTitleListener != null) {\r
-////            removePropertyListener(compatibilityTitleListener);\r
-////            compatibilityTitleListener = null;\r
-////        }\r
-////\r
-////        super.setPartName(partName);\r
-//    }\r
\r
-//    protected void setTitleToolTip(String toolTip) {\r
-////        toolTip = Util.safeString(toolTip);\r
-////        //Do not send changes if they are the same\r
-////        if (Util.equals(this.toolTip, toolTip)) {\r
-////                   return;\r
-////           }\r
-////        this.toolTip = toolTip;\r
-////        firePropertyChange(IWorkbenchPart.PROP_TITLE);\r
-//    }\r
-\r
-    protected void setHost(DiagramViewerHost host) {\r
-        this.host = host;\r
-    }\r
-\r
-    protected void setSite(IWorkbenchPartSite site) {\r
-        this.partSite = site;\r
-    }\r
-\r
-    protected void setInput(IEditorInput input) {\r
-        Assert.isLegal(input != null);\r
-        editorInput = input;\r
-    }\r
-\r
-    public Composite getComposite() {\r
-        return c;\r
-    }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2007, 2019 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, gitlab #399
+ *******************************************************************************/
+package org.simantics.modeling.ui.diagramEditor;
+
+import java.awt.Color;
+import java.awt.dnd.DnDConstants;
+import java.util.Collections;
+import java.util.Set;
+import java.util.concurrent.TimeUnit;
+import java.util.function.Supplier;
+
+import org.eclipse.core.runtime.Assert;
+import org.eclipse.core.runtime.IAdaptable;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.core.runtime.SubMonitor;
+import org.eclipse.core.runtime.jobs.Job;
+import org.eclipse.jface.action.IStatusLineManager;
+import org.eclipse.jface.resource.JFaceResources;
+import org.eclipse.jface.resource.LocalResourceManager;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.IEditorInput;
+import org.eclipse.ui.IEditorSite;
+import org.eclipse.ui.IWorkbenchPartSite;
+import org.eclipse.ui.contexts.IContextService;
+import org.eclipse.ui.views.contentoutline.IContentOutlinePage;
+import org.simantics.Simantics;
+import org.simantics.browsing.ui.model.browsecontexts.BrowseContext;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.primitiverequest.PossibleAdapter;
+import org.simantics.db.common.primitiverequest.PossibleObject;
+import org.simantics.db.common.procedure.adapter.ListenerDelegate;
+import org.simantics.db.common.procedure.adapter.ListenerSupport;
+import org.simantics.db.common.request.ParametrizedRead;
+import org.simantics.db.common.request.TypeURIs;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.common.utils.CommonDBUtils;
+import org.simantics.db.common.utils.TagUtil;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.request.combinations.Combinators;
+import org.simantics.db.management.ISessionContext;
+import org.simantics.db.management.ISessionContextProvider;
+import org.simantics.db.request.Read;
+import org.simantics.diagram.DiagramTypeUtils;
+import org.simantics.diagram.adapter.FlagClassFactory;
+import org.simantics.diagram.adapter.GraphToDiagramSynchronizer;
+import org.simantics.diagram.adapter.IDiagramLoader;
+import org.simantics.diagram.connection.ModelledConnectionAdvisor;
+import org.simantics.diagram.handler.ConnectionCommandHandler;
+import org.simantics.diagram.handler.CopyPasteHandler;
+import org.simantics.diagram.handler.CopyPasteStrategy;
+import org.simantics.diagram.handler.DefaultCopyPasteStrategy;
+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.ConnectionCrossingsParticipant;
+import org.simantics.diagram.participant.ContextUtil;
+import org.simantics.diagram.participant.CopyAsSVGParticipant;
+import org.simantics.diagram.participant.PointerInteractor2;
+import org.simantics.diagram.participant.SGFocusParticipant;
+import org.simantics.diagram.query.DiagramRequests;
+import org.simantics.diagram.runtime.RuntimeDiagramManager;
+import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.diagram.symbolcontribution.SymbolProviderFactory;
+import org.simantics.diagram.synchronization.CopyAdvisor;
+import org.simantics.diagram.synchronization.IModifiableSynchronizationContext;
+import org.simantics.diagram.synchronization.SynchronizationHints;
+import org.simantics.diagram.synchronization.graph.DiagramGraphUtil;
+import org.simantics.diagram.ui.DiagramModelHints;
+import org.simantics.diagram.ui.SWTPopupMenuParticipant;
+import org.simantics.diagram.ui.SWTPopupMenuParticipantAwt;
+import org.simantics.diagram.ui.WorkbenchSelectionProvider;
+import org.simantics.g2d.canvas.Hints;
+import org.simantics.g2d.canvas.ICanvasContext;
+import org.simantics.g2d.canvas.ICanvasParticipant;
+import org.simantics.g2d.canvas.impl.CanvasContext;
+import org.simantics.g2d.chassis.AWTChassis;
+import org.simantics.g2d.chassis.ICanvasChassis;
+import org.simantics.g2d.chassis.IChassisListener;
+import org.simantics.g2d.chassis.SWTChassis;
+import org.simantics.g2d.connection.IConnectionAdvisor;
+import org.simantics.g2d.diagram.DiagramClass;
+import org.simantics.g2d.diagram.DiagramHints;
+import org.simantics.g2d.diagram.IDiagram;
+import org.simantics.g2d.diagram.handler.PickRequest.PickFilter;
+import org.simantics.g2d.diagram.impl.Diagram;
+import org.simantics.g2d.diagram.participant.DelayedBatchElementPainter;
+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.ElementUtils;
+import org.simantics.g2d.element.IElement;
+import org.simantics.g2d.element.IElementClassProvider;
+import org.simantics.g2d.element.handler.impl.StaticObjectAdapter;
+import org.simantics.g2d.elementclass.connection.ConnectionClass;
+import org.simantics.g2d.page.DiagramDesc;
+import org.simantics.g2d.participant.BackgroundPainter;
+import org.simantics.g2d.participant.CanvasBoundsParticipant;
+import org.simantics.g2d.participant.CanvasGrab;
+import org.simantics.g2d.participant.GridPainter;
+import org.simantics.g2d.participant.KeyUtil;
+import org.simantics.g2d.participant.MouseUtil;
+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.RenderingQualityInteractor;
+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.WorkbenchStatusLine;
+import org.simantics.g2d.participant.ZoomToAreaHandler;
+import org.simantics.g2d.tooltip.TerminalTooltipParticipant;
+import org.simantics.g2d.utils.CanvasUtils;
+import org.simantics.layer0.utils.triggers.IActivation;
+import org.simantics.layer0.utils.triggers.IActivationManager;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.modeling.mapping.ComponentCopyAdvisor;
+import org.simantics.modeling.mapping.ElementCopyAdvisor;
+import org.simantics.modeling.mapping.MappedElementCopyAdvisor;
+import org.simantics.modeling.mapping.ModelingSynchronizationHints;
+import org.simantics.modeling.ui.diagramEditor.handlers.LinkBrowsingHandler;
+import org.simantics.modeling.ui.diagramEditor.handlers.StructuralBrowsingHandler;
+import org.simantics.modeling.ui.preferences.DiagramPreferenceUtil;
+import org.simantics.modeling.ui.preferences.DiagramPreferences;
+import org.simantics.project.ontology.ProjectResource;
+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.structural.stubs.StructuralResource2;
+import org.simantics.structural2.modelingRules.IModelingRules;
+import org.simantics.ui.SimanticsUI;
+import org.simantics.ui.jobs.SessionGarbageCollectorJob;
+import org.simantics.ui.workbench.IPropertyPage;
+import org.simantics.ui.workbench.IResourceEditorInput;
+import org.simantics.ui.workbench.IResourceEditorInput2;
+import org.simantics.ui.workbench.TitleRequest;
+import org.simantics.ui.workbench.TitleUpdater;
+import org.simantics.ui.workbench.ToolTipRequest;
+import org.simantics.ui.workbench.editor.input.InputValidationCombinators;
+import org.simantics.utils.DataContainer;
+import org.simantics.utils.datastructures.hints.HintContext;
+import org.simantics.utils.datastructures.hints.HintListenerAdapter;
+import org.simantics.utils.datastructures.hints.IHintContext;
+import org.simantics.utils.datastructures.hints.IHintContext.Key;
+import org.simantics.utils.datastructures.hints.IHintListener;
+import org.simantics.utils.datastructures.hints.IHintObservable;
+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;
+import org.simantics.utils.ui.ExceptionUtils;
+
+import com.kitfox.svg.SVGCache;
+
+/**
+ * @author Toni Kalajainen
+ * @author Tuukka Lehtonen
+ */
+public class DiagramViewer 
+  //extends EditorPart implements IResourceEditorPart2, 
+    implements ListenerSupport, IAdaptable {
+
+    public interface DiagramViewerHost {
+        void doSetPartName(String name);
+        void doSetTitleToolTip(String name);
+    }
+
+    public static final String                      DIAGRAMMING_CONTEXT      = "org.simantics.modeling.ui.diagramming"; //$NON-NLS-1$
+    private static final String                     PREFERENCE_VIRTUAL_GRAPH = "preferences"; //$NON-NLS-1$
+
+    private static final boolean                    PROFILE                  = false;
+
+    ParametrizedRead<IResourceEditorInput, Boolean> INPUT_VALIDATOR =
+        Combinators.compose(
+                InputValidationCombinators.or(
+                        // Normal configuration diagrams of a model
+                        Combinators.compose(
+                                InputValidationCombinators.hasURI(),
+                                InputValidationCombinators.partialFunction(ModelingResources.URIs.DiagramToComposite)
+                        ),
+                        // Configuration diagrams of a component type
+                        Combinators.compose(
+                                InputValidationCombinators.hasURI(),
+                                Combinators.compose(
+                                        InputValidationCombinators.partialFunction(StructuralResource2.URIs.Defines),
+                                        InputValidationCombinators.partialFunction(ModelingResources.URIs.DiagramToComposite)
+                                )
+                        )
+                ),
+                InputValidationCombinators.extractInputResource()
+        );
+
+    protected EditorState                editorState;
+
+    protected boolean                    disposed           = false;
+    protected IThreadWorkQueue           swt;
+    protected IStatusLineManager         statusLineManager;
+    protected Display                    display;
+    protected LocalResourceManager       resourceManager;
+    protected SWTChassis                 c;
+    protected IDiagram                   sourceDiagram;
+    protected DataContainer<IDiagram>    sourceDiagramContainer;
+    protected CanvasContext              canvasContext;
+    protected ISessionContextProvider    sessionContextProvider;
+    protected ISessionContext            sessionContext;
+    protected Resource                   diagramResource;
+    protected GraphToDiagramSynchronizer synchronizer;
+    protected IActivation                activation;
+    protected ContextUtil                contextUtil;
+    protected SWTPopupMenuParticipant    popupMenuParticipant;
+    
+    protected DiagramPreferences         diagramPreferences;
+    protected DiagramDesc                diagramDesc;
+    protected GridSnapAdvisor            snapAdvisor;
+
+    private RuntimeDiagramManager        runtimeDiagramManager;
+    private Resource                     runtimeDiagramResourceCache;
+    private HasDiagramSourceListener     hasDiagramSourceListener;
+
+    /**
+     * Set externally in
+     * {@link #init(DiagramViewerHost, IEditorSite, IEditorInput, DataContainer, WorkbenchSelectionProvider)}
+     * .
+     */
+    protected WorkbenchSelectionProvider selectionProvider;
+
+    protected Resource getRuntimeFromManager() {
+        RuntimeDiagramManager rtdm = runtimeDiagramManager;
+        return (rtdm == null) ? null : rtdm.getRuntimeDiagram();
+    }
+
+    public Resource getRuntime() {
+        if (runtimeDiagramResourceCache != null)
+            return runtimeDiagramResourceCache;
+        runtimeDiagramResourceCache = getRuntimeFromManager();
+        return runtimeDiagramResourceCache;
+    }
+
+    public ParametrizedRead<IResourceEditorInput, Boolean> getInputValidator() {
+        return INPUT_VALIDATOR;
+    }
+
+    protected void addDropParticipants(ICanvasContext ctx) {
+        ctx.getDefaultHintContext().setHint(Hints.KEY_ALLOWED_DRAG_ACTIONS, DnDConstants.ACTION_COPY);
+
+        ctx.add(new PopulateElementDropParticipant(synchronizer, getSite()));
+        ctx.add(new PopulateElementMonitorDropParticipant(synchronizer, 0.5, 0.5));
+    }
+
+    protected CopyPasteStrategy getCopyPasteStrategy() {
+               try {
+                       CopyPasteStrategy cpStrategy = Simantics.getSession().syncRequest(new PossibleAdapter<CopyPasteStrategy>(getInputResource(), CopyPasteStrategy.class));
+                       if(cpStrategy != null) return cpStrategy;
+               } catch (DatabaseException e) {
+               }
+               return getDefaultCopyPasteStrategy();
+    }
+    
+    protected CopyPasteStrategy getDefaultCopyPasteStrategy() {
+       return new DefaultCopyPasteStrategy();
+    }
+
+    protected CopyAdvisor getCopyAdvisor() {
+               try {
+                       CopyAdvisor advisor = Simantics.getSession().syncRequest(new PossibleAdapter<CopyAdvisor>(getInputResource(), CopyAdvisor.class));
+                       if(advisor != null) return advisor;
+               } catch (DatabaseException e) {
+               }
+               return new MappedElementCopyAdvisor(new ElementCopyAdvisor(), new ComponentCopyAdvisor());
+    }
+    
+    /**
+     * @param ctx
+     * TODO: change argument from CanvasContext to ICanvasContext
+     */
+    protected void addKeyBindingParticipants(CanvasContext ctx) {
+        //ctx.add( new KeyToCommand( CommandKeyBinding.DEFAULT_BINDINGS ) );
+        ctx.add(new DeleteHandler(statusLineManager));
+        ctx.add(new CopyPasteHandler(getCopyPasteStrategy(), statusLineManager).setWorkbenchSite(getEditorSite()));
+        ctx.add(new ConnectionCommandHandler());
+    }
+
+    protected void addPopupmenu(ICanvasContext ctx) {
+        ctx.add(popupMenuParticipant);
+    }
+
+    protected void addWorkbenchSelectionProvider(ICanvasContext ctx) {
+        if (selectionProvider != null)
+            ctx.add(selectionProvider);
+    }
+
+    protected void addViewManipulationParticipants(CanvasContext ctx) {
+        ctx.add(new PanZoomRotateHandler());
+        //ctx.add(new MousePanZoomInteractor());
+        //ctx.add(new MultitouchPanZoomRotateInteractor());
+        // ctx.add( new OrientationRestorer() );
+        ctx.add(new ZoomToAreaHandler());
+    }
+
+    protected void addDiagramParticipants(ICanvasContext ctx) {
+        ctx.add(new ZOrderHandler());
+        ctx.add(getPointerInteractor());
+        ctx.add(new ElementInteractor());
+        ctx.add(new Selection());
+        ctx.add(new DiagramParticipant());
+        ctx.add(new ElementPainter());
+        //ctx.add(new ElementHeartbeater());
+        //ctx.add(new ZoomTransitionParticipant(TransitionFunction.SIGMOID));
+        //ctx.add(new TooltipParticipant());
+        ctx.add(new TerminalTooltipParticipant());
+        ctx.add(new ConnectionCrossingsParticipant(getInputResource()));
+        ctx.add(new CopyAsSVGParticipant());
+    }
+
+    protected void addPainterParticipants(ICanvasContext ctx) {
+        ctx.add(new RenderingQualityInteractor());
+        ctx.add(new TerminalPainter(true, true, false, true));
+        ctx.add(new DelayedBatchElementPainter(PickFilter.FILTER_MONITORS, 500, TimeUnit.MILLISECONDS));
+    }
+
+    protected void addStructureParticipants(ICanvasContext ctx) {
+        addWorkbenchSelectionProvider(ctx);
+        // Add visual browsing capabilities for structural models
+        ctx.add(new StructuralBrowsingHandler(getSite(), sessionContext, getResourceInput2()));
+        ctx.add(new LinkBrowsingHandler(getSite(), this, sessionContext));
+    }
+
+    /**
+     * Override to add any diagram/canvas participants to the canvas context
+     * initialized for the editor.
+     * 
+     * @param ctx
+     */
+    protected void addOtherParticipants(CanvasContext ctx) {
+    }
+
+    public static Set<String> defaultPropertyBrowseContexts = Collections.singleton(ProjectResource.URIs.ProjectBrowseContext);
+
+    protected Set<String> getPropertyPageContexts() {
+        try {
+            return BrowseContext.getBrowseContextClosure(Simantics.getSession(), defaultPropertyBrowseContexts);
+        } catch (DatabaseException e) {
+            ExceptionUtils.logAndShowError(Messages.DiagramViewer_FailedtoLoadModeled, e);
+            return defaultPropertyBrowseContexts;
+        }
+    }
+
+    protected IPropertyPage createPropertyPage(IWorkbenchPartSite site, Set<String> contexts) {
+        return new StandardPropertyPage(site, contexts);
+    }
+
+    protected String getPopupId() {
+        return "#ModelingDiagramPopup"; //$NON-NLS-1$
+    }
+
+    protected void getPreferences() {
+        this.diagramPreferences = DiagramPreferenceUtil.getPreferences();
+    }
+
+    protected void initSession() {
+        sessionContextProvider = Simantics.getSessionContextProvider();
+        sessionContext = sessionContextProvider.getSessionContext();
+    }
+
+    protected void readNames() {
+        String name = getEditorInput().getName();
+        host.doSetPartName(name);
+        host.doSetTitleToolTip(name);
+    }
+
+    class ChassisListener implements IChassisListener {
+        @Override
+        public void chassisClosed(ICanvasChassis sender) {
+            // Prevent deadlock while disposing which using syncExec would result in.
+            final ICanvasContext ctx = canvasContext;
+            ThreadUtils.asyncExec(ctx.getThreadAccess(), new Runnable() {
+                @Override
+                public void run() {
+                    if (ctx != null) {
+                        saveEditorState(ctx);
+                        ctx.getHintStack().removeKeyHintListener(GridPainter.KEY_GRID_ENABLED, canvasHintListener);
+                        ctx.getHintStack().removeKeyHintListener(RulerPainter.KEY_RULER_ENABLED, canvasHintListener);
+                        final AWTChassis awtChassis = c.getAWTComponent();
+                        if (awtChassis != null)
+                            awtChassis.setCanvasContext(null);
+                        ctx.dispose();
+                    }
+
+                    if (sourceDiagramContainer != null) {
+                        sourceDiagramContainer.set(null);
+                        sourceDiagramContainer = null;
+                    }
+
+                    if (sourceDiagram != null)
+                        sourceDiagram.dispose();
+
+                    if(synchronizer != null) {
+                        synchronizer.dispose();
+                        // Let GC work.
+                        synchronizer = null;
+                    }
+
+                    if (runtimeDiagramManager != null) {
+                        runtimeDiagramManager.dispose();
+                        runtimeDiagramManager = null;
+                    }
+                }
+            });
+            c.removeChassisListener(ChassisListener.this);
+        }
+    }
+
+    protected void createChassis(Composite parent) {
+        resourceManager = new LocalResourceManager(JFaceResources.getResources(), parent);
+        c = new SWTChassis(parent, 0);
+
+        Object task = BEGIN("DV.precreateParticipants"); //$NON-NLS-1$
+        createCustomParticipants();
+        END(task);
+
+        c.populate(component -> {
+            if (!disposed) {
+                c.addChassisListener(new ChassisListener());
+                initializeCanvas();
+            }
+        });
+    }
+
+    protected void beforeSetCanvasContext(ICanvasContext canvasContext2) {
+    }
+
+    /**
+     * Invoke this only from the AWT thread.
+     * @param context
+     */
+    protected void setCanvasContext(ICanvasContext context) {
+        // Cannot directly invoke SWTChassis.setCanvasContext only because it
+        // needs to be invoked in the SWT thread and AWTChassis.setCanvasContext in the
+        // AWT thread, but directly invoking SWTChassis.setCanvasContext would call both
+        // in the SWT thread which would cause synchronous scheduling of AWT
+        // runnables which is always a potential source of deadlocks.
+        c.getAWTComponent().setCanvasContext(canvasContext);
+        swt.asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                if (!c.isDisposed())
+                    // For AWT, this is a no-operation.
+                    c.setCanvasContext(canvasContext);
+            }
+        });
+    }
+
+    public void createPartControl(Composite parent) {
+        //ProfileObserver.begin = System.nanoTime();
+        display = parent.getDisplay(); 
+        swt = SWTThread.getThreadAccess(display);
+        statusLineManager = getEditorSite().getActionBars().getStatusLineManager();
+
+        Object task = BEGIN("DV.initSession"); //$NON-NLS-1$
+        initSession();
+        END(task);
+
+        diagramResource = getInputResource();
+        readNames();
+        getPreferences();
+
+        try {
+            this.runtimeDiagramManager = RuntimeDiagramManager.track(sessionContext.getSession(), diagramResource, getEditorInput(), this);
+
+            // Create the canvas context here before finishing createPartControl
+            // to give DiagramViewerActionContributor a chance to work.
+            // The context can be created in SWT thread without scheduling
+            // to the context thread and having potential deadlocks.
+            IThreadWorkQueue thread = AWTThread.getThreadAccess();
+            this.canvasContext = new CanvasContext(thread);
+            this.canvasContext.setLocked(true);
+
+            task = BEGIN("DV.createChassis"); //$NON-NLS-1$
+            createChassis(parent);
+            END(task);
+        } catch (DatabaseException e) {
+            ErrorLogger.defaultLogError(e);
+        }
+    }
+
+
+       /**
+     * A method invoked before chassis construction for creating such
+     * {@link ICanvasParticipant}s that need to be constructed in the SWT
+     * thread.
+     * 
+     * Use it for creating any such canvas participants during the viewer 
+     * construction and add them to the {@link ICanvasContext} later on from
+     * the AWT thread.
+     */
+    protected void createCustomParticipants() {
+       if (SimanticsUI.isLinuxGTK()) {
+               popupMenuParticipant = new SWTPopupMenuParticipantAwt(getSite(), c, display, getPopupId());
+       } else {
+               popupMenuParticipant = new SWTPopupMenuParticipant(getSite(), c, display, getPopupId());
+       }
+    }
+
+    /**
+     * Invoke this only from the AWT thread.
+     */
+    protected void initializeCanvas() {
+        Object canvasInit = BEGIN("DV.canvasInitialization"); //$NON-NLS-1$
+
+        Object task = BEGIN("DV.createViewerCanvas"); //$NON-NLS-1$
+        initializeCanvasContext(canvasContext);
+        END(task);
+
+        beforeSetCanvasContext(canvasContext);
+        //FullscreenUtils.addFullScreenHandler(canvasContext, s, canvasProvider);
+
+        // 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));
+
+        // Changes in ruler/grid activity shall be written as
+        // workspace-persistent diagram-specific preferences.
+        canvasContext.getHintStack().addKeyHintListener(GridPainter.KEY_GRID_ENABLED, canvasHintListener);
+        canvasContext.getHintStack().addKeyHintListener(RulerPainter.KEY_RULER_ENABLED, canvasHintListener);
+
+        task = BEGIN("DV.setCanvasContext"); //$NON-NLS-1$
+        setCanvasContext(canvasContext);
+        END(task);
+
+        // Finish loading in a worker thread because it may be a time consuming
+        // process to load a large diagram and we don't want unnecessary AWT
+        // thread contention.
+        Job loadJob = new DiagramViewerLoadJob(this);
+        loadJob.schedule();
+
+        END(canvasInit);
+    }
+
+    protected void activateUiContexts(ContextUtil util) {
+        util.activate(DIAGRAMMING_CONTEXT);
+    }
+
+    /**
+     * @param monitor the progress monitor to use for reporting progress to the
+     *        user. It is the caller's responsibility to call done() on the
+     *        given monitor. Accepts <code>null</code>, indicating that no
+     *        progress should be reported and that the operation cannot be
+     *        cancelled.
+     */
+    protected void performActivation(IProgressMonitor monitor) {
+        SubMonitor progress = SubMonitor.convert(monitor, Messages.DiagramViewer_MonitorActivateMapping, 100);
+        IActivationManager activationManager = sessionContext.getSession().peekService(IActivationManager.class);
+        if (activationManager != null) {
+            activation = activationManager.activate(diagramResource);
+        }
+        progress.worked(100);
+    }
+
+    protected void onCreated() {
+    }
+
+    /**
+     * @param diagram
+     */
+    protected void scheduleZoomToFit(IDiagram diagram) {
+        if (diagram == null)
+            throw new IllegalStateException("diagram is null"); //$NON-NLS-1$
+
+        CanvasUtils.scheduleZoomToFit(swt, () -> disposed, canvasContext, diagram);
+    }
+
+    /**
+     * Subclasses may override but should always invoke super.
+     * 
+     * @param diagram
+     * @param initialHints
+     * @throws DatabaseException
+     */
+    protected void fillInitialDiagramHints(Resource diagram, IHintContext initialHints) throws DatabaseException {
+        IModelingRules modelingRules = sessionContext.getSession().syncRequest(
+                DiagramRequests.getModelingRules(diagram, null));
+        if (modelingRules != null) {
+            initialHints.setHint(DiagramModelHints.KEY_MODELING_RULES, modelingRules);
+            initialHints.setHint(DiagramHints.CONNECTION_ADVISOR,
+                    getConnectionAdvisor(modelingRules, sessionContext.getSession()));
+        }
+
+        initialHints.setHint(SynchronizationHints.COPY_ADVISOR, getCopyAdvisor());
+        initialHints.setHint(DiagramHints.KEY_USE_CONNECTION_FLAGS, Boolean.TRUE);
+        initialHints.setHint(DiagramHints.KEY_ALLOW_CONNECTION_BRANCHING, Boolean.TRUE);
+        initialHints.setHint(DiagramHints.KEY_ALLOW_ROUTE_POINTS, Boolean.TRUE);
+    }
+
+    /**
+     * @param monitor the progress monitor to use for reporting progress to the
+     *        user. It is the caller's responsibility to call done() on the
+     *        given monitor. Accepts <code>null</code>, indicating that no
+     *        progress should be reported and that the operation cannot be
+     *        cancelled.
+     * @param r
+     * @return
+     * @throws DatabaseException
+     */
+    protected IDiagram loadDiagram(IProgressMonitor monitor, final Resource r) throws DatabaseException {
+        // Pre-load modeling rules and possibly other hints too since they are
+        // needed already while loading the diagram contents.
+        IHintContext initialHints = new HintContext();
+        fillInitialDiagramHints(r, initialHints);
+        IDiagram d = loadDiagram(monitor, r, initialHints);
+        return d;
+    }
+
+    /**
+     * @param monitor the progress monitor to use for reporting progress to the
+     *        user. It is the caller's responsibility to call done() on the
+     *        given monitor. Accepts <code>null</code>, indicating that no
+     *        progress should be reported and that the operation cannot be
+     *        cancelled.
+     * @param diagram
+     * @param initialHints
+     * @return
+     * @throws DatabaseException
+     */
+    protected IDiagram loadDiagram(IProgressMonitor monitor, Resource diagram, IHintContext initialHints) throws DatabaseException {
+        RuntimeDiagramManager rtdm = runtimeDiagramManager;
+        Resource runtimeDiagram = rtdm != null ? rtdm.getRuntimeDiagram() : null;
+        IDiagramLoader loader = synchronizer;
+        if (rtdm == null || runtimeDiagram == null || loader == null)
+            return null;
+        IDiagram d = sessionContext.getSession().syncRequest((Read<IDiagram>) graph -> {
+            IDiagram result = DiagramRequests.loadDiagram(monitor, getResourceInput2().getModel(null), diagram,
+                    runtimeDiagram, null, loader, initialHints).perform(graph);
+
+            // #399: Enable certain PropertyTester implementation without database transactions
+            ModelingResources MOD = ModelingResources.getInstance(graph);
+            Resource composite = graph.getPossibleObject(diagram, MOD.DiagramToComposite);
+            result.setHint(
+                    DiagramModelHints.KEY_DIAGRAM_RESOURCE_TYPE_URIS,
+                    graph.syncRequest(new TypeURIs(diagram)));
+            result.setHint(
+                    DiagramModelHints.KEY_MAPPED_COMPOSITE_RESOURCE_TYPE_URIS,
+                    composite != null ? graph.syncRequest(new TypeURIs(composite)) : Collections.emptySet());
+
+            Resource diagramSource = graph.syncRequest(
+                    new PossibleObject(diagram, MOD.HasDiagramSource),
+                    hasDiagramSourceListener = new HasDiagramSourceListener(sourceDiagramContainer));
+            ElementUtils.setOrRemoveHint(
+                    result, 
+                    DiagramModelHints.KEY_HAS_DIAGRAM_SOURCE,
+                    diagramSource);
+
+            return result;
+        });
+        return d;
+    }
+
+    protected void beforeSetDiagram(IDiagram diagram) {
+    }
+
+    protected PointerInteractor getPointerInteractor() {
+        return new PointerInteractor2(true, true, true, false, true, false, synchronizer.getElementClassProvider());
+    }
+
+    protected IConnectionAdvisor getConnectionAdvisor(IModelingRules modelingRules, Session session) {
+        return new ModelledConnectionAdvisor(modelingRules, sessionContext.getSession());
+    }
+
+    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); //$NON-NLS-1$
+        }
+    }
+
+    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, ConnectionClass.CLASS.newClassWith(new StaticObjectAdapter(dr.RouteGraphConnection)),
+                ElementClasses.FLAG, FlagClassFactory.createFlagClass(dr.Flag, dr.Flag_Terminal)
+        );
+    }
+    
+    protected SimpleElementTransformHandler getTransformHandler() {
+       return new SimpleElementTransformHandler(true, true, true);
+    }
+
+    public void initializeCanvasContext(CanvasContext ctx) {
+        IHintContext h = ctx.getDefaultHintContext();
+
+        // The canvas context should not be painted until it is ready to avoid
+        // unnecessary visual glitches.
+        h.setHint(Hints.KEY_DISABLE_PAINTING, Boolean.TRUE);
+
+        Object task = BEGIN("createSynchronizer"); //$NON-NLS-1$
+        this.synchronizer = createSynchronizer(ctx, sessionContext);
+        END(task);
+
+        IContextService contextService = (IContextService) getSite().getService(IContextService.class);
+        contextUtil = new ContextUtil(contextService, swt);
+
+        // Support & Util Participants
+        ctx.add(new TransformUtil());
+        ctx.add(new MouseUtil());
+        ctx.add(new KeyUtil());
+        ctx.add(contextUtil);
+        ctx.add(new WorkbenchStatusLine(statusLineManager));
+        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, DIAGRAMMING_CONTEXT));
+
+        // Debug participant(s)
+        // ctx.add( new PointerPainter() );
+        // ctx.add( new HandPainter() );
+        h.setHint(PointerPainter.KEY_PAINT_POINTER, true);
+
+        // Pan & Zoom & Rotate
+        addViewManipulationParticipants(ctx);
+
+        ctx.add(getTransformHandler());
+        ctx.add(new ExpandSelectionHandler(getEditorSite().getActionBars().getStatusLineManager()));
+
+        // Key bindings
+        addKeyBindingParticipants(ctx);
+
+        // Grid & Ruler & Background
+        addGridRulerBackgroundParticipants(ctx);
+
+        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.9f, 0.9f, 0.9f));
+        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 //////
+        addDiagramParticipants(ctx);
+        addPainterParticipants(ctx);
+
+        /////// 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);
+        h.setHint(GridPainter.KEY_GRID_SIZE, snapResolution);
+        h.setHint(GridPainter.KEY_GRID_ENABLED, Boolean.FALSE);
+
+        // Workbench selection provider
+        addStructureParticipants(ctx);
+
+        // Pop-up menu
+        addPopupmenu(ctx);
+
+        // Load page frame description settings
+        loadPageSettings(ctx);
+
+        addOtherParticipants(ctx);
+
+        ctx.assertParticipantDependencies();
+        ctx.setLocked(false);
+    }
+
+    protected void addGridRulerBackgroundParticipants(CanvasContext ctx) {
+        ctx.add(new GridPainter());
+        ctx.add(new RulerPainter());
+        ctx.add(new BackgroundPainter());
+    }
+
+    protected void loadPageSettings(ICanvasContext ctx) {
+        DiagramDesc diagramDesc = null;
+
+        // load diagram page configuration
+        if (diagramResource != null) {
+            try {
+                diagramDesc = sessionContext.getSession().syncRequest(DiagramRequests.getDiagramDesc(diagramResource));
+            } catch (DatabaseException e) {
+                ErrorLogger.defaultLogError(e);
+            }
+        }
+
+        if (diagramDesc == null) {
+            // Take page description from the preferences if nothing else is available.
+            final DiagramDesc desc = diagramDesc = diagramPreferences.getDiagramDesc();
+
+            // Write page configuration to graph
+            sessionContext.getSession().asyncRequest(new WriteRequest() {
+                @Override
+                public void perform(WriteGraph graph) throws DatabaseException {
+                    if (graph.isImmutable(diagramResource))
+                        return;
+                    CommonDBUtils.selectClusterSet(graph, diagramResource);
+                    DiagramGraphUtil.setDiagramDesc(graph, diagramResource, desc);
+                }
+            }, parameter -> {
+                if (parameter != null)
+                    ErrorLogger.defaultLogError("Failed to write default diagram page description to database, see exception for details", parameter); //$NON-NLS-1$
+            });
+        }
+
+        setDiagramDesc(ctx, diagramDesc);
+
+        // Create a listener to react to page setting changes.
+        sessionContext.getSession().asyncRequest(DiagramRequests.getDiagramDesc(diagramResource),
+                new ListenerDelegate<DiagramDesc>(this) {
+            @Override
+            public void execute(final DiagramDesc result) {
+                if (result != null && canvasContext != null) {
+                    ThreadUtils.asyncExec(canvasContext.getThreadAccess(), new Runnable() {
+                        @Override
+                        public void run() {
+                            if (!disposed)
+                                setDiagramDesc(canvasContext, result);
+                        }
+                    });
+                }
+            }
+        });
+    }
+
+    protected void setDiagramDesc(ICanvasContext ctx, DiagramDesc diagramDesc) {
+        if (diagramDesc == null)
+            throw new NullPointerException("null diagram desc"); //$NON-NLS-1$
+
+        if (diagramDesc.equals(this.diagramDesc))
+            return;
+
+        this.diagramDesc = diagramDesc;
+        IHintContext hints = ctx.getDefaultHintContext();
+        hints.setHint(Hints.KEY_PAGE_DESC, diagramDesc.getPageDesc());
+        hints.setHint(Hints.KEY_DISPLAY_PAGE, diagramDesc.isPageBordersVisible());
+        hints.setHint(Hints.KEY_DISPLAY_MARGINS, diagramDesc.isMarginsVisible());
+        hints.setHint(GridPainter.KEY_GRID_ENABLED, diagramDesc.isGridVisible());
+        hints.setHint(RulerPainter.KEY_RULER_ENABLED, diagramDesc.isRulerVisible());
+        snapAdvisor.setResolution(diagramDesc.getGridSize());
+        hints.setHint(GridPainter.KEY_GRID_SIZE, diagramDesc.getGridSize());
+    }
+
+    /**
+     * Must be invoked from the AWT thread only.
+     * 
+     * @param state
+     * @param ctx
+     */
+    protected void applyEditorState(final EditorState state, final ICanvasContext ctx) {
+        final IDiagram diagram = ctx.getHintStack().getHint(DiagramHints.KEY_DIAGRAM);
+
+        if (state.viewTransform != null && state.viewTransform.getDeterminant() != 0) {
+            for (PanZoomRotateHandler h : ctx.getItemsByClass(PanZoomRotateHandler.class)) {
+                h.setTransform(state.viewTransform);
+            }
+        }
+
+        if (diagram != null) {
+            if (state.viewTransform != null)
+                diagram.removeHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT);
+
+            if (state.toolMode != null)
+                ctx.getDefaultHintContext().setHint(Hints.KEY_TOOL, state.toToolMode());
+            else
+                ctx.getDefaultHintContext().setHint(Hints.KEY_TOOL, Hints.POINTERTOOL);
+
+            final Set<IElement> selected = DiagramEditorStates.toElements(state.selection, diagram);
+            if (!selected.isEmpty()) {
+                for (Selection s : ctx.getItemsByClass(Selection.class)) {
+                    s.setSelection(0, selected);
+                }
+            }
+        }
+    }
+
+    protected EditorState getSavedEditorState(ICanvasContext ctx) {
+        return DiagramEditorStates.toEditorState(ctx, true, true, true);
+    }
+
+    protected void saveEditorState(ICanvasContext ctx) {
+        DiagramEditorStates.saveEditorState(PREFERENCE_VIRTUAL_GRAPH, diagramResource, getSavedEditorState(ctx) , DiagramViewer.this);
+    }
+
+    private boolean firstFocus = true;
+
+    public void setFocus() {
+       
+       if(c != null) {
+               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() {
+        // [Tuukka@2010-02-11]
+        // Removed since this is actually a workaround for multi-page editors.
+        //scheduleZoomToFit();
+    }
+
+    public void dispose() {
+        // Deactivate all contexts here because after this the context service
+        // in question will not be available.
+        if (contextUtil != null) {
+            contextUtil.deactivateAll();
+        }
+
+        disposed = true;
+
+        if (hasDiagramSourceListener != null) {
+            hasDiagramSourceListener.dispose();
+            hasDiagramSourceListener = null;
+        }
+
+        if (activation != null) {
+            activation.deactivate();
+            activation = null;
+        }
+
+        if (resourceManager != null) {
+               resourceManager.dispose();
+               resourceManager = null;
+        }
+        //super.dispose();
+    }
+
+    protected Resource getInputResource() {
+        return getResourceInput().getResource();
+    }
+
+    public IResourceEditorInput getResourceInput() {
+        return (IResourceEditorInput) getEditorInput();
+    }
+
+    public IResourceEditorInput2 getResourceInput2() {
+        return (IResourceEditorInput2) getEditorInput();
+    }
+
+    public void init(DiagramViewerHost _host, IEditorSite site, IEditorInput input, DataContainer<IDiagram> diagramContainer, WorkbenchSelectionProvider selectionProvider) {
+        if (!(input instanceof IResourceEditorInput))
+            throw new RuntimeException("Invalid input: must be IResourceEditorInput"); //$NON-NLS-1$
+
+        setHost(_host);
+        setSite(site);
+        setInput(input);
+        this.sourceDiagramContainer = diagramContainer;
+        this.selectionProvider = selectionProvider;
+
+        // Set initial part name according to the name given by IEditorInput
+        host.doSetPartName(getEditorInput().getName());
+
+        Session session = Simantics.peekSession();
+        if (session != null) {
+            Supplier<Boolean> disposedCallback = () -> disposed;
+            session.asyncRequest(
+                    new TitleRequest(site.getId(), getResourceInput()),
+                    new TitleUpdater(site.getShell().getDisplay(), host::doSetPartName, disposedCallback));
+            session.asyncRequest(
+                    new ToolTipRequest(site.getId(), getResourceInput()),
+                    new TitleUpdater(site.getShell().getDisplay(), host::doSetTitleToolTip, disposedCallback));
+        }
+
+        try {
+            // Read previous editor state from the database
+            editorState = DiagramEditorStates.readEditorState(getInputResource());
+        } catch (DatabaseException e) {
+            exception(e);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T getAdapter(Class<T> adapter) {
+//        System.out.println("diagramViewer getAdapter " + adapter);
+        // Property view support
+        if (adapter == IPropertyPage.class)
+            return (T) createPropertyPage(getSite(), getPropertyPageContexts());
+        // Provide symbols for the editor
+        if (adapter == SymbolProviderFactory.class) {
+            try {
+                return (T) DiagramTypeUtils.readSymbolProviderFactory(sessionContext.getSession(), diagramResource);
+            } catch (DatabaseException e) {
+                ErrorLogger.defaultLogError(getClass() + " failed to adapt to SymbolProviderFactory, see exception for details.", e); //$NON-NLS-1$
+                return null;
+            }
+        }
+        // Outline view support
+        if (adapter == IContentOutlinePage.class)
+            return (T) new DiagramOutlinePage(sessionContextProvider, getResourceInput2());
+        // Role view support
+        if (adapter == ILayersViewPage.class)
+            return (T) new DiagramLayersPage(sourceDiagram, canvasContext);
+        // Support external steering of the diagram canvas, zooming etc.
+        if (adapter == ICanvasContext.class)
+            return (T) canvasContext;
+        // Support scene graph debugger view
+        if (adapter == INode.class) {
+            if (canvasContext != null) {
+                INode node = canvasContext.getCanvasNode();
+                if (node != null)
+                    return (T) NodeUtil.getRootNode(node);
+            }
+            return null;
+        }
+        // Support retrieval of the current diagram.
+        if (adapter == IDiagram.class)
+            return (T) sourceDiagram;
+        // Why is this here ??
+        if (adapter == Session.class)
+            return (T) sessionContext.getSession();
+        if(adapter == RuntimeDiagramManager.class)
+            return (T) runtimeDiagramManager;
+        if (adapter == Resource.class)
+            return (T) getRuntime();
+        if (adapter == ICanvasChassis.class)
+            return (T) c;
+
+        return null;
+    }
+
+    //-------------------------------------------------------------------------
+    // Profiling aid
+
+    protected static Object BEGIN(String name) {
+        if (PROFILE) {
+            //return ThreadLog.BEGIN(name);
+        }
+        return null;
+    }
+
+    protected static void END(Object task) {
+        if (PROFILE) {
+            //((Task) task).end();
+        }
+    }
+
+    //-------------------------------------------------------------------------
+    // implement ListenerSupport
+
+    @Override
+    public void exception(Throwable t) {
+        ErrorLogger.defaultLogError(t);
+    }
+
+    @Override
+    public boolean isDisposed() {
+        return disposed;
+    }
+
+    protected void collectGarbage() {
+        SessionGarbageCollectorJob.getInstance().schedule(0);
+        AWTThread.getThreadAccess().asyncExec(new Runnable() {
+            @Override
+            public void run() {
+                //System.out.println("BEFORE CLEAR: " + SVGCache.getSVGUniverse().report());
+                SVGCache.getSVGUniverse().clearUnreferenced();
+                //System.out.println("AFTER CLEAR: " + SVGCache.getSVGUniverse().report());
+            }
+        });
+    }
+
+    //-------------------------------------------------------------------------
+    // Listener for certain canvas context hint changes
+
+    IHintListener canvasHintListener = new HintListenerAdapter() {
+        @Override
+        public void hintChanged(IHintObservable sender, Key key, Object oldValue, Object newValue) {
+            if (key == GridPainter.KEY_GRID_ENABLED) {
+                boolean v = Boolean.TRUE.equals(newValue);
+                if (diagramDesc.isGridVisible() != v)
+                    setGlobalPreference(DiagramResource.URIs.DisplayGrid, v);
+            } else if (key == RulerPainter.KEY_RULER_ENABLED) {
+                boolean v = Boolean.TRUE.equals(newValue);
+                if (diagramDesc.isRulerVisible() != v)
+                    setGlobalPreference(DiagramResource.URIs.DisplayRuler, v);
+            }
+        }
+    };
+
+    private <T> void setGlobalPreference(final String preferenceURI, boolean value) {
+        TagUtil.execute(Simantics.getSession(), PREFERENCE_VIRTUAL_GRAPH, preferenceURI, value, Simantics.getProjectResource());
+    }
+
+    /*
+     * --------------------------------------------------------------------
+     * Changes related to removal of EditorPart extension from here on down
+     * --------------------------------------------------------------------
+     */
+
+    private IWorkbenchPartSite partSite;
+    private DiagramViewerHost host;
+    private IEditorInput editorInput = null;
+
+    /* (non-Javadoc)
+     * Method declared on IWorkbenchPart.
+     */
+    public IWorkbenchPartSite getSite() {
+        return partSite;
+    }
+
+    public IEditorSite getEditorSite() {
+        return (IEditorSite) getSite();
+    }
+
+    public IEditorInput getEditorInput() {
+        return editorInput;
+    }
+
+//    protected void setPartName(String partName) {
+////        if (compatibilityTitleListener != null) {
+////            removePropertyListener(compatibilityTitleListener);
+////            compatibilityTitleListener = null;
+////        }
+////
+////        super.setPartName(partName);
+//    }
+//    protected void setTitleToolTip(String toolTip) {
+////        toolTip = Util.safeString(toolTip);
+////        //Do not send changes if they are the same
+////        if (Util.equals(this.toolTip, toolTip)) {
+////                   return;
+////           }
+////        this.toolTip = toolTip;
+////        firePropertyChange(IWorkbenchPart.PROP_TITLE);
+//    }
+
+    protected void setHost(DiagramViewerHost host) {
+        this.host = host;
+    }
+
+    protected void setSite(IWorkbenchPartSite site) {
+        this.partSite = site;
+    }
+
+    protected void setInput(IEditorInput input) {
+        Assert.isLegal(input != null);
+        editorInput = input;
+    }
+
+    public Composite getComposite() {
+        return c;
+    }
+
+}