-/*******************************************************************************\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.ContextUtil;
+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";
+ private static final String PREFERENCE_VIRTUAL_GRAPH = "preferences";
+
+ 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());
+ }
+
+ 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(SimanticsUI.getSession(), defaultPropertyBrowseContexts);
+ } catch (DatabaseException e) {
+ ExceptionUtils.logAndShowError("Failed to load modeled browse contexts for property page, see exception for details.", e);
+ return defaultPropertyBrowseContexts;
+ }
+ }
+
+ protected IPropertyPage createPropertyPage(IWorkbenchPartSite site, Set<String> contexts) {
+ return new StandardPropertyPage(site, contexts);
+ }
+
+ protected String getPopupId() {
+ return "#ModelingDiagramPopup";
+ }
+
+ protected void getPreferences() {
+ this.diagramPreferences = DiagramPreferenceUtil.getPreferences();
+ }
+
+ protected void initSession() {
+ sessionContextProvider = SimanticsUI.getSessionContextProvider();
+ sessionContext = sessionContextProvider.getSessionContext();
+ }
+
+ protected void readNames() {
+ String name = getEditorInput().getName();
+ 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");
+ 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");
+ 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");
+ 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");
+
+ Object task = BEGIN("DV.createViewerCanvas");
+ 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");
+ 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, "Activate Mapping", 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");
+
+ 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);
+ }
+ }
+
+ 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");
+ 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);
+ });
+ }
+
+ 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");
+
+ 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");
+
+ 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 = SimanticsUI.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);
+ 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;
+ }
+
+}