--- /dev/null
+package org.simantics.sysdyn.ui.editor;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+import java.util.Collections;\r
+\r
+import org.eclipse.swt.widgets.Display;\r
+import org.eclipse.ui.IEditorPart;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.ResourceArray;\r
+import org.simantics.db.common.request.ReadRequest;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.variable.Variable;\r
+import org.simantics.db.layer0.variable.Variables;\r
+import org.simantics.diagram.content.ConnectionUtil;\r
+import org.simantics.diagram.flag.FlagUtil;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.g2d.canvas.ICanvasContext;\r
+import org.simantics.g2d.diagram.DiagramHints;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.modeling.ComponentUtils;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.modeling.actions.NavigateToTarget;\r
+import org.simantics.modeling.ui.Activator;\r
+import org.simantics.structural2.StructuralVariables;\r
+import org.simantics.sysdyn.SysdynResource;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.ui.utils.ResourceAdaptionUtils;\r
+import org.simantics.ui.workbench.editor.AbstractResourceEditorAdapter;\r
+import org.simantics.utils.datastructures.Callback;\r
+import org.simantics.utils.threads.SWTThread;\r
+import org.simantics.utils.threads.ThreadUtils;\r
+import org.simantics.utils.ui.AdaptionUtils;\r
+\r
+/**\r
+ * @author Tuukka Lehtonen\r
+ */\r
+public class OpenDiagramFromComponentAdapter extends AbstractResourceEditorAdapter {\r
+\r
+ private static final String EDITOR_ID = "org.simantics.sysdyn.ui.diagramViewer";\r
+\r
+ public OpenDiagramFromComponentAdapter() {\r
+ super("Diagram Editor", Activator.COMPOSITE_ICON);\r
+ }\r
+\r
+ @Override\r
+ public boolean canHandle(ReadGraph graph, Object input) throws DatabaseException {\r
+ Resource r = tryGetResource(graph, input);\r
+ if (r == null)\r
+ return false;\r
+ Variable v = AdaptionUtils.adaptToSingle(input, Variable.class);\r
+ Collection<Runnable> rs = tryFindDiagram(graph, r, v);\r
+ return !rs.isEmpty();\r
+ }\r
+\r
+ private Resource tryGetResource(ReadGraph graph, Object input) throws DatabaseException {\r
+ Resource r = ResourceAdaptionUtils.toSingleResource(input);\r
+ if (r == null) {\r
+ Variable v = AdaptionUtils.adaptToSingle(input, Variable.class);\r
+ r = findResource(graph, v);\r
+ }\r
+ return r;\r
+ }\r
+\r
+ private Resource findResource(ReadGraph graph, Variable v) throws DatabaseException {\r
+ while (v != null) {\r
+ Resource r = v.getPossibleRepresents(graph);\r
+ if (r != null)\r
+ return r;\r
+ v = v.browsePossible(graph, ".");\r
+ }\r
+ return null;\r
+ }\r
+\r
+ @Override\r
+ public void openEditor(final Object input) throws Exception {\r
+ final Display d = Display.getCurrent();\r
+ if (d == null)\r
+ return;\r
+\r
+ SimanticsUI.getSession().syncRequest(new ReadRequest() {\r
+ @Override\r
+ public void run(ReadGraph graph) throws DatabaseException {\r
+ Resource r = tryGetResource(graph, input);\r
+ if (r == null)\r
+ return;\r
+\r
+ Variable v = AdaptionUtils.adaptToSingle(input, Variable.class);\r
+\r
+ final Collection<Runnable> rs = tryFindDiagram(graph, r, v);\r
+ if (rs.isEmpty())\r
+ return;\r
+\r
+ SWTThread.getThreadAccess(d).asyncExec(new Runnable() {\r
+ @Override\r
+ public void run() {\r
+ for (Runnable runnable : rs) {\r
+ runnable.run();\r
+ }\r
+ }\r
+ });\r
+ }\r
+ });\r
+ }\r
+\r
+ private Collection<Runnable> tryFindDiagram(ReadGraph g, Resource module, Variable variable) throws DatabaseException {\r
+ try {\r
+ return findDiagram(g, module, variable);\r
+ } catch (DatabaseException e) {\r
+ return Collections.emptyList();\r
+ }\r
+ }\r
+\r
+ private Collection<Runnable> findDiagram(ReadGraph g, Resource module, Variable variable) throws DatabaseException {\r
+ Layer0 l0 = Layer0.getInstance(g);\r
+ SysdynResource SYSDYN = SysdynResource.getInstance(g);\r
+\r
+ if (g.isInstanceOf(module, SYSDYN.IndependentVariable) || g.isInstanceOf(module, SYSDYN.Input)) {\r
+ Collection<Runnable> result = new ArrayList<Runnable>(1);\r
+\r
+ Resource composite = g.getSingleObject(module, l0.PartOf);\r
+\r
+ final Resource diagram = ComponentUtils.getCompositeDiagram(g, composite);\r
+ final ResourceArray compositePath = StructuralVariables.getCompositeArray(g, composite);\r
+ final ResourceArray variablePath = compositePath.removeFromBeginning(1);\r
+\r
+ Resource model = StructuralVariables.getModel(g, compositePath.head());\r
+ if (model == null)\r
+ return Collections.emptyList();\r
+ String modelURI = g.getURI(model);\r
+\r
+ String rvi = StructuralVariables.getRVI(g, variablePath);\r
+ if (rvi == null)\r
+ return Collections.emptyList();\r
+\r
+ if (variable != null) {\r
+ // Get proper RVI from variable if it exists.\r
+ Variable context = Variables.getPossibleContext(g, variable);\r
+ if (context != null) {\r
+ // We want the composite's RVI, not the component in it.\r
+ Variable parent = variable.getParent(g);\r
+ if (parent != null) {\r
+ String contextURI = context.getURI(g);\r
+ String parentURI = parent.getURI(g);\r
+ rvi = parentURI.replace(contextURI, "");\r
+ }\r
+ }\r
+ }\r
+\r
+ final Collection<Object> selectedObjects = findElementObjects(g, module);\r
+\r
+ result.add(\r
+ NavigateToTarget.editorActivator(EDITOR_ID, diagram, modelURI, rvi, new Callback<IEditorPart>() {\r
+ @Override\r
+ public void run(IEditorPart part) {\r
+ final ICanvasContext openedCanvas = (ICanvasContext) part.getAdapter(ICanvasContext.class);\r
+ assert openedCanvas != null;\r
+ // CanvasContext-wide denial of initial zoom-to-fit on diagram open.\r
+ openedCanvas.getDefaultHintContext().setHint(DiagramHints.KEY_INITIAL_ZOOM_TO_FIT, Boolean.FALSE);\r
+ ThreadUtils.asyncExec(openedCanvas.getThreadAccess(),\r
+ NavigateToTarget.elementSelectorZoomer(openedCanvas, selectedObjects, false));\r
+ }\r
+ }));\r
+ return result;\r
+ }\r
+\r
+ // Nothing to open\r
+ return Collections.emptyList();\r
+ }\r
+\r
+ public static Collection<Object> findElementObjects(ReadGraph g, Resource module) throws DatabaseException {\r
+ DiagramResource DIA = DiagramResource.getInstance(g);\r
+ ModelingResources MOD = ModelingResources.getInstance(g);\r
+ final Collection<Object> selectedObjects = new ArrayList<Object>();\r
+ for (Resource element : g.getObjects(module, MOD.ComponentToElement)) {\r
+ if (g.isInstanceOf(element, DIA.Flag) && FlagUtil.isExternal(g, element)) {\r
+ // Use external flag primarily if one exists in the correspondences\r
+ selectedObjects.clear();\r
+ selectedObjects.add(element);\r
+ break;\r
+ } else if (g.isInstanceOf(element, DIA.RouteGraphConnection)) {\r
+ selectedObjects.add(element);\r
+ } else if (g.isInstanceOf(element, DIA.Connection)) {\r
+ // Okay, we need to find a part of the connection\r
+ ConnectionUtil cu = new ConnectionUtil(g);\r
+ cu.gatherConnectionParts(element, selectedObjects);\r
+ } else {\r
+ selectedObjects.add(element);\r
+ }\r
+ }\r
+ for(Resource element : g.getObjects(module, MOD.HasParentComponent_Inverse)) {\r
+ selectedObjects.add(element);\r
+ }\r
+ return selectedObjects;\r
+ }\r
+\r
+}\r