]> gerrit.simantics Code Review - simantics/sysdyn.git/commitdiff
Hierarchy view displaying the full hierarchy of the model that can be reached with...
authorlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Fri, 24 Feb 2012 13:57:00 +0000 (13:57 +0000)
committerlempinen <lempinen@ac1ea38d-2e2b-0410-8846-a27921b304fc>
Fri, 24 Feb 2012 13:57:00 +0000 (13:57 +0000)
git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@24292 ac1ea38d-2e2b-0410-8846-a27921b304fc

org.simantics.sysdyn.ui/plugin.xml
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/editor/participant/SysdynConnectionBuilder.java
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/Dependencies.java [moved from org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/dependencies/DependencyView.java with 58% similarity]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/DependencyGraphRequest.java [moved from org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/dependencies/CreateDependencyGraph.java with 76% similarity]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/ModuleStructure.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/ModuleStructureGraphRequest.java [new file with mode: 0644]
org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/StructureView.java [new file with mode: 0644]

index 7a9e43c2d7f86e0c6dddc46a1e8519df0afd399e..144ef94112a3e1058a43c9ae65594c60fd0845e9 100644 (file)
       <view\r
             allowMultiple="false"\r
             category="org.simantics.sysdyn.ui.category"\r
-            class="org.simantics.sysdyn.ui.dependencies.DependencyView"\r
+            class="org.simantics.sysdyn.ui.structure.StructureView"\r
             icon="platform:/plugin/com.famfamfam.silk/icons/arrow_switch.png"\r
-            id="org.simantics.sysdyn.ui.dependencies.view"\r
-            name="Dependencies"\r
+            id="org.simantics.sysdyn.ui.structure.view"\r
+            name="Structure"\r
             restorable="true">\r
       </view>\r
       <view\r
                relative="org.simantics.browsing.ui.graph.propertyView">\r
          </view>\r
          <view\r
-               id="org.simantics.sysdyn.ui.dependencies.view"\r
+               id="org.simantics.sysdyn.ui.structure.view"\r
                minimized="false"\r
                relationship="stack"\r
                relative="org.simantics.sysdyn.ui.trend.view">\r
index 5d48050f700346664fb6f49f4499a020249730e5..da8581db6cbc749e640d9bff72c4de0605eb7195 100644 (file)
@@ -1,3 +1,14 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2012 Association for Decentralized Information Management in\r
+ * 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
+ *******************************************************************************/\r
 package org.simantics.sysdyn.ui.editor.participant;\r
 \r
 import java.awt.geom.AffineTransform;\r
@@ -176,6 +187,7 @@ public class SysdynConnectionBuilder extends ConnectionBuilder{
 \r
         Resource valve = graph.newResource();\r
         graph.claim(valve, L0.InstanceOf, null, valveClassResource);\r
+        graph.claim(valve, L0.PartOf, diagramResource);\r
         valveElement.setHint(ElementHints.KEY_OBJECT, valve);\r
 \r
         OrderedSetUtils.add(graph, diagramResource, valve);\r
similarity index 58%
rename from org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/dependencies/DependencyView.java
rename to org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/Dependencies.java
index d783c03caa82ecd3270a7f224fc61846fdc8c136..348d098e28b6f5ebe434dfc572d4a5da6eb198bd 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\r
- * Copyright (c) 2010 Association for Decentralized Information Management in\r
+ * Copyright (c) 2010, 2012 Association for Decentralized Information Management in\r
  * 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
@@ -9,7 +9,7 @@
  * Contributors:\r
  *     VTT Technical Research Centre of Finland - initial API and implementation\r
  *******************************************************************************/\r
-package org.simantics.sysdyn.ui.dependencies;\r
+package org.simantics.sysdyn.ui.structure;\r
 \r
 import java.util.Set;\r
 \r
@@ -22,6 +22,8 @@ import org.eclipse.jface.layout.GridLayoutFactory;
 import org.eclipse.jface.viewers.ISelection;\r
 import org.eclipse.jface.viewers.IStructuredSelection;\r
 import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.CTabFolder;\r
+import org.eclipse.swt.custom.CTabItem;\r
 import org.eclipse.swt.events.ModifyEvent;\r
 import org.eclipse.swt.events.ModifyListener;\r
 import org.eclipse.swt.events.SelectionAdapter;\r
@@ -31,9 +33,6 @@ import org.eclipse.swt.widgets.Button;
 import org.eclipse.swt.widgets.Composite;\r
 import org.eclipse.swt.widgets.Label;\r
 import org.eclipse.swt.widgets.Spinner;\r
-import org.eclipse.ui.ISelectionListener;\r
-import org.eclipse.ui.IWorkbenchPart;\r
-import org.eclipse.ui.part.ViewPart;\r
 import org.simantics.db.Resource;\r
 import org.simantics.db.procedure.Listener;\r
 import org.simantics.graphviz.Graph;\r
@@ -41,37 +40,37 @@ import org.simantics.graphviz.ui.GraphvizComponent;
 import org.simantics.ui.SimanticsUI;\r
 import org.simantics.utils.ui.ISelectionUtils;\r
 \r
-public class DependencyView extends ViewPart {\r
-\r
+public class Dependencies extends CTabItem {\r
+    \r
     private GraphvizComponent component;\r
-    private boolean disposed, isInverted = false;\r
+    private boolean isInverted = false;\r
     private Button bButton, fButton;\r
     private Resource currentSelection;\r
     private int levels = 3;\r
-    private ISelectionListener selectionListener;\r
-    private Composite baseComposite;\r
+    private GraphListener graphListener;\r
 \r
     static int MAXLEVELS = 4;\r
     static int MINLEVELS = 1;\r
 \r
-    @Override\r
-    public void createPartControl(Composite parent) {\r
-        disposed = false;\r
-        GridLayoutFactory.fillDefaults().margins(3, 3).applyTo(parent);\r
-        baseComposite = new Composite(parent, \r
-                SWT.NO_BACKGROUND | SWT.EMBEDDED);\r
-        GridLayoutFactory.fillDefaults().applyTo(baseComposite);\r
-        GridDataFactory.fillDefaults().grab(true, true).applyTo(baseComposite);\r
+    public Dependencies(CTabFolder parent, ISelection selection, int style) {\r
+        super(parent, style);\r
+        \r
+        Composite dependencies = new Composite(parent, SWT.NONE);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(dependencies);\r
+        GridLayoutFactory.fillDefaults().spacing(0,0).applyTo(dependencies);\r
 \r
-        component = new GraphvizComponent(baseComposite, SWT.BORDER);\r
+        component = new GraphvizComponent(dependencies, SWT.NONE);\r
         GridDataFactory.fillDefaults().grab(true, true).applyTo(component);\r
-\r
-        Composite composite = new Composite(parent, SWT.NULL);\r
+        \r
+        Label line = new Label(dependencies, SWT.SEPARATOR | SWT.SHADOW_OUT | SWT.HORIZONTAL);\r
+        GridDataFactory.fillDefaults().grab(true, false).applyTo(line);\r
+        \r
+        Composite composite = new Composite(dependencies, SWT.NONE);\r
         RowLayout layout = new RowLayout();\r
         layout.center = true;\r
         composite.setLayout(layout);\r
 \r
-        Label label = new Label(composite, SWT.NULL);\r
+        Label label = new Label(composite, SWT.NONE);\r
         label.setText("Direction: ");\r
 \r
         bButton = new Button(composite, SWT.RADIO);\r
@@ -92,7 +91,7 @@ public class DependencyView extends ViewPart {
         fButton = new Button(composite, SWT.RADIO);\r
         fButton.setText("Forward");\r
 \r
-        label = new Label(composite, SWT.NULL);\r
+        label = new Label(composite, SWT.NONE);\r
         label.setText("Steps: ");\r
 \r
         Spinner spinner = new Spinner(composite, SWT.BORDER);\r
@@ -118,20 +117,15 @@ public class DependencyView extends ViewPart {
 \r
             }\r
         });\r
-\r
-        drawSelection(getSite().getWorkbenchWindow().getSelectionService().getSelection());\r
-\r
-        selectionListener = new ISelectionListener() {\r
-\r
-            @Override\r
-            public void selectionChanged(IWorkbenchPart part, ISelection selection) {\r
-                drawSelection(selection);\r
-            }\r
-        };    \r
-        getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(selectionListener);\r
+        \r
+        drawSelection(selection);\r
+        \r
+        this.setText("Dependencies");\r
+        this.setControl(dependencies);\r
     }\r
 \r
-    private void drawSelection(ISelection selection) {\r
+\r
+    public void drawSelection(ISelection selection) {\r
         if(selection == null || selection.isEmpty())\r
             return;\r
         if(selection instanceof IStructuredSelection) {                    \r
@@ -149,54 +143,46 @@ public class DependencyView extends ViewPart {
     }\r
 \r
     private void readGraph(Resource resource) {\r
-        SimanticsUI.getSession().asyncRequest(new CreateDependencyGraph(\r
-                resource, levels, isInverted),\r
-                new Listener<Graph>() {\r
-\r
-            @Override\r
-            public void exception(Throwable e) {\r
-                e.printStackTrace();\r
-            }\r
-\r
-            @Override\r
-            public void execute(final Graph graph) {\r
-                Job job = new Job("Layout composite graph") {\r
-\r
-                    @Override\r
-                    protected IStatus run(IProgressMonitor monitor) {\r
-                        if(!isDisposed()) {\r
-                            component.setGraph(graph, "dot");\r
-                            component.fit();                            \r
-                        }\r
-                        return Status.OK_STATUS;\r
-                    }\r
-                };\r
-                job.schedule();\r
-            }\r
-\r
-            @Override\r
-            public boolean isDisposed() {\r
-                return disposed;\r
-            }\r
-        });\r
+        if(graphListener != null)\r
+            graphListener.dispose();\r
+        \r
+        graphListener = new GraphListener();\r
+        SimanticsUI.getSession().asyncRequest(new DependencyGraphRequest(\r
+                resource, levels, isInverted), graphListener);\r
     }\r
 \r
-\r
-    @Override\r
-    public void setFocus() {\r
-        if(baseComposite != null && !baseComposite.isDisposed()) {\r
-            baseComposite.setFocus();\r
-            component.setFocus();\r
+    private class GraphListener implements Listener<Graph> {\r
+        \r
+        private boolean disposed = false;\r
+        \r
+        public void dispose() {\r
+            disposed = true;\r
+        }\r
+        \r
+        @Override\r
+        public void exception(Throwable e) {\r
+            e.printStackTrace();\r
         }\r
-    }\r
-\r
 \r
+        @Override\r
+        public void execute(final Graph graph) {\r
+            Job job = new Job("Loading dependencies graph") {\r
 \r
+                @Override\r
+                protected IStatus run(IProgressMonitor monitor) {\r
+                    if(!isDisposed()) {\r
+                        component.setGraph(graph, "dot");\r
+                        component.fit();                            \r
+                    }\r
+                    return Status.OK_STATUS;\r
+                }\r
+            };\r
+            job.schedule();\r
+        }\r
 \r
-    @Override\r
-    public void dispose() {\r
-        super.dispose();\r
-        getSite().getWorkbenchWindow().getSelectionService().removePostSelectionListener(selectionListener);\r
-        disposed = true;\r
+        @Override\r
+        public boolean isDisposed() {\r
+            return disposed;\r
+        }\r
     }\r
 }\r
similarity index 76%
rename from org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/dependencies/CreateDependencyGraph.java
rename to org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/DependencyGraphRequest.java
index 586117b08303d519131e0e558be305d06fa0ce53..5864b912afb6b007730e1012cea40d8ccbda8041 100644 (file)
@@ -1,5 +1,5 @@
 /*******************************************************************************\r
- * Copyright (c) 2010 Association for Decentralized Information Management in\r
+ * Copyright (c) 2010, 2012 Association for Decentralized Information Management in\r
  * 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
@@ -9,7 +9,7 @@
  * Contributors:\r
  *     VTT Technical Research Centre of Finland - initial API and implementation\r
  *******************************************************************************/\r
-package org.simantics.sysdyn.ui.dependencies;\r
+package org.simantics.sysdyn.ui.structure;\r
 \r
 import java.util.ArrayList;\r
 import java.util.Collection;\r
@@ -29,14 +29,28 @@ import org.simantics.layer0.Layer0;
 import org.simantics.modeling.ModelingResources;\r
 import org.simantics.sysdyn.SysdynResource;\r
 \r
-public class CreateDependencyGraph implements Read<Graph> {\r
+/**\r
+ * Builds a graph of the dependencies of a selected variable\r
+ * \r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class DependencyGraphRequest implements Read<Graph> {\r
 \r
        Resource root;\r
        HashMap<Resource, Node> nodes;\r
        boolean isInverted;\r
        int levels;\r
 \r
-       public CreateDependencyGraph(Resource root, int levels, boolean isInverted) {\r
+       /**\r
+        * Builds a graph of the dependencies of a selected variable\r
+        * \r
+        * @param root Variable from which to find dependencies\r
+        * @param levels How many steps of dependencies are calculated from the variable\r
+        * @param isInverted true => variables that affect root; false => variables that are affected by root \r
+        */\r
+       public DependencyGraphRequest(Resource root, int levels, boolean isInverted) {\r
                this.root = root;\r
                this.isInverted = isInverted;    \r
                this.levels = levels;\r
@@ -69,6 +83,13 @@ public class CreateDependencyGraph implements Read<Graph> {
                return graph;\r
        }\r
 \r
+       /**\r
+        * Create a root node and set appearance settings for it\r
+        * @param g ReadGraph\r
+        * @param graph Graphviz graph\r
+        * @param root Root resource\r
+        * @throws DatabaseException\r
+        */\r
        private void setRoot(ReadGraph g, IGraph graph, Resource root) throws DatabaseException {\r
                Node n;\r
                n = new Node(graph, getName(g, root));\r
@@ -79,6 +100,17 @@ public class CreateDependencyGraph implements Read<Graph> {
        }\r
 \r
 \r
+       /**\r
+        * Call for calculating  \r
+        * @param g\r
+        * @param graph\r
+        * @param r\r
+        * @param toDependency\r
+        * @param fromDependency\r
+        * @param connectionType\r
+        * @return\r
+        * @throws DatabaseException\r
+        */\r
        private Collection<Resource> getDependants(ReadGraph g, IGraph graph, Resource r, Resource toDependency, Resource fromDependency, Resource connectionType) throws DatabaseException {\r
                SysdynResource sr = SysdynResource.getInstance(g);\r
 \r
@@ -108,6 +140,7 @@ public class CreateDependencyGraph implements Read<Graph> {
                }\r
                return dependants;\r
        }\r
+       \r
        private Collection<Resource> setDependencies(ReadGraph g, IGraph graph, Resource r) throws DatabaseException{\r
                SysdynResource sr = SysdynResource.getInstance(g);\r
 \r
@@ -128,7 +161,14 @@ public class CreateDependencyGraph implements Read<Graph> {
 \r
                return dependants;\r
        }\r
-\r
+       \r
+       /**\r
+        * Set shape for a node. Rectangle for stocks, ellipse for auxiliaries and rounded rectangle for modules. \r
+        * @param g ReadGraph\r
+        * @param r Resource\r
+        * @param n Node\r
+        * @throws DatabaseException\r
+        */\r
        private void setShape(ReadGraph g, Resource r, Node n) throws DatabaseException {\r
                SysdynResource sr = SysdynResource.getInstance(g);\r
                if(g.isInstanceOf(r, sr.Stock))\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/ModuleStructure.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/ModuleStructure.java
new file mode 100644 (file)
index 0000000..3354f7f
--- /dev/null
@@ -0,0 +1,134 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2012 Association for Decentralized Information Management in\r
+ * 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
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.structure;\r
+\r
+import java.util.Set;\r
+\r
+import org.eclipse.core.runtime.IProgressMonitor;\r
+import org.eclipse.core.runtime.IStatus;\r
+import org.eclipse.core.runtime.Status;\r
+import org.eclipse.core.runtime.jobs.Job;\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.jface.viewers.IStructuredSelection;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.CTabFolder;\r
+import org.eclipse.swt.custom.CTabItem;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.procedure.Listener;\r
+import org.simantics.graphviz.Graph;\r
+import org.simantics.graphviz.ui.GraphvizComponent;\r
+import org.simantics.ui.SimanticsUI;\r
+import org.simantics.utils.RunnableWithObject;\r
+import org.simantics.utils.ui.ISelectionUtils;\r
+\r
+/**\r
+ * Tab for displaying hierarchical model structure\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ModuleStructure extends CTabItem {\r
+\r
+    private GraphvizComponent component;\r
+    private GraphListener graphListener;\r
+\r
+    \r
+    public ModuleStructure(CTabFolder parent, int style) {\r
+        super(parent, style);\r
+        \r
+        Composite moduleStructure = new Composite(parent, SWT.NONE);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(moduleStructure);\r
+        GridLayoutFactory.fillDefaults().applyTo(moduleStructure);\r
+\r
+        component = new GraphvizComponent(moduleStructure, SWT.NONE);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(component);\r
+        \r
+        this.setText("Model Hierarchy");\r
+        this.setControl(moduleStructure);\r
+\r
+    }\r
+\r
+    /**\r
+     * Draw a graph about the model of the selected resource\r
+     * @param selection\r
+     */\r
+    public void drawSelection(ISelection selection) {\r
+        if(selection == null || selection.isEmpty())\r
+            return;\r
+\r
+        if(selection instanceof IStructuredSelection) {                    \r
+            Object[] els = ((IStructuredSelection) selection).toArray();\r
+            if(els.length == 1) {\r
+                Set<Resource> ress = ISelectionUtils.filterSetSelection(selection, Resource.class);\r
+                if(ress.isEmpty()) return;\r
+                Resource r = (ress.toArray(Resource.NONE))[0];\r
+                if(r != null) {\r
+                    // Read graph for the resource\r
+                    if(graphListener != null)\r
+                        graphListener.dispose(); // Dispose possible previous listener\r
+                    \r
+                    graphListener = new GraphListener();\r
+                    SimanticsUI.getSession().asyncRequest(new ModuleStructureGraphRequest(r), graphListener);\r
+                }\r
+            }\r
+        }           \r
+    }\r
+    \r
+    /**\r
+     * Listener for updating hierarchical model graph\r
+     * @author Teemu Lempinen\r
+     *\r
+     */\r
+    private class GraphListener implements Listener<Graph> {\r
+        private boolean disposed = false;\r
+        \r
+        public void dispose() {\r
+            disposed = true;\r
+        }\r
+        \r
+        @Override\r
+        public void exception(Throwable e) {\r
+            e.printStackTrace();\r
+        }\r
+\r
+        @Override\r
+        public void execute(final Graph graph) {\r
+            Job job = new Job("Loading model structure graph") {\r
+\r
+                @Override\r
+                protected IStatus run(IProgressMonitor monitor) {\r
+                    if(!isDisposed()) {\r
+                        component.getDisplay().asyncExec(new RunnableWithObject(graph) {\r
+                            \r
+                            @Override\r
+                            public void run() {\r
+                                component.setGraph((Graph)getObject(), "dot");\r
+                                component.fit();    \r
+                            }\r
+                        });\r
+                     \r
+                    }\r
+                    return Status.OK_STATUS;\r
+                }\r
+            };\r
+            job.schedule();\r
+        }\r
+\r
+        @Override\r
+        public boolean isDisposed() {\r
+            return disposed;\r
+        }\r
+    }\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/ModuleStructureGraphRequest.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/ModuleStructureGraphRequest.java
new file mode 100644 (file)
index 0000000..4724a0d
--- /dev/null
@@ -0,0 +1,131 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2012 Association for Decentralized Information Management in\r
+ * 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
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.structure;\r
+\r
+import java.util.HashMap;\r
+import java.util.HashSet;\r
+\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.common.request.PossibleObjectWithType;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.graphviz.Edge;\r
+import org.simantics.graphviz.Graph;\r
+import org.simantics.graphviz.Node;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.sysdyn.SysdynResource;\r
+\r
+/**\r
+ * Builds a graph about the modular structure of the model where a selected object is located.\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class ModuleStructureGraphRequest implements Read<Graph> {\r
+\r
+    private Resource resource;\r
+\r
+    /**\r
+     * Request a hierarchical graph about the model of resource\r
+     * @param resource\r
+     */\r
+    public ModuleStructureGraphRequest(Resource resource) {\r
+        this.resource = resource;\r
+    }\r
+\r
+    @Override\r
+    public Graph perform(ReadGraph graph) throws DatabaseException {\r
+        SysdynResource sr = SysdynResource.getInstance(graph);\r
+        Layer0 l0 = Layer0.getInstance(graph);\r
+\r
+        Graph g = new Graph();\r
+        g.setRankdir("TB");\r
+\r
+        // Find model resource, the root of this\r
+        Resource model = resource;\r
+        while(model != null && !graph.isInstanceOf(model, sr.SysdynModel)) {\r
+            model = graph.getPossibleObject(model, l0.PartOf);\r
+        }\r
+\r
+        // Model root was not found, return empty graph\r
+        if(model == null)\r
+            return g;\r
+\r
+        // Set root node\r
+        Node rootNode = new Node(g, NameUtils.getSafeLabel(graph, model));\r
+        rootNode.setShape("rectangle");\r
+        HashSet<Resource> visited = new HashSet<Resource>();\r
+        visited.add(model);\r
+        findChildModules(g, rootNode, graph, model, visited);\r
+\r
+\r
+        return g;\r
+    }\r
+\r
+    /**\r
+     * Recursive call for finding child modules \r
+     * @param g GraphViz graph\r
+     * @param parent Parent module or model\r
+     * @param graph ReadGraph\r
+     * @param resource Module type or model\r
+     * @param visited All visited modules. Needed to check for loops in the structure. Loops are not allowed.\r
+     * @throws DatabaseException\r
+     */\r
+    private void findChildModules(Graph g, Node parent, ReadGraph graph, Resource resource, HashSet<Resource> visited) throws DatabaseException {\r
+        SysdynResource sr = SysdynResource.getInstance(graph);\r
+        Layer0 l0 = Layer0.getInstance(graph);\r
+\r
+        HashMap<Resource, Integer> modules = new HashMap<Resource, Integer>();\r
+\r
+        // Find all module children\r
+        Resource configuration = graph.syncRequest(new PossibleObjectWithType(resource, l0.ConsistsOf, sr.Configuration));\r
+        for(Resource m : graph.getObjects(configuration, l0.ConsistsOf)) {\r
+            Resource type = graph.getPossibleObject(m, l0.InstanceOf);\r
+            if(graph.isInheritedFrom(type, sr.Module)) {\r
+                if(!modules.containsKey(type))\r
+                    modules.put(type, 0);\r
+                modules.put(type, modules.get(type) + 1);\r
+            }\r
+        }\r
+\r
+        // Display module children in graph\r
+        for(Resource type : modules.keySet()) {\r
+\r
+            Node node = new Node(g, NameUtils.getSafeName(graph, type));\r
+            node.setShape("rectangle");\r
+            Edge edge = new Edge(g, parent, node);\r
+            edge.set("labeldistance", "1.5");\r
+            edge.set("labelfontsize", "7");\r
+            edge.setFontColor("#4f4f4f");\r
+            if(modules.get(type) > 1)\r
+                edge.setHeadLabel(modules.get(type).toString());\r
+            \r
+            if(visited.contains(type)) {\r
+                // Found a loop. Stop recursive call and display error.\r
+                edge.setFontColor("#FF0000");\r
+                edge.setColor("#FF000");\r
+                edge.setLabel("Error: loop");\r
+                node.setColor("#FF0000");\r
+                node.setFontColor("#FF0000");\r
+                continue;\r
+            } else {\r
+                visited.add(type);\r
+                findChildModules(g, node, graph, type, visited);\r
+            }\r
+            \r
+        }\r
+\r
+    }\r
+\r
+}\r
diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/StructureView.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/StructureView.java
new file mode 100644 (file)
index 0000000..ab3983b
--- /dev/null
@@ -0,0 +1,110 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007, 2012 Association for Decentralized Information Management in\r
+ * 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
+ *******************************************************************************/\r
+package org.simantics.sysdyn.ui.structure;\r
+\r
+import org.eclipse.jface.layout.GridDataFactory;\r
+import org.eclipse.jface.layout.GridLayoutFactory;\r
+import org.eclipse.jface.viewers.ISelection;\r
+import org.eclipse.swt.SWT;\r
+import org.eclipse.swt.custom.CTabFolder;\r
+import org.eclipse.swt.events.SelectionEvent;\r
+import org.eclipse.swt.events.SelectionListener;\r
+import org.eclipse.swt.widgets.Composite;\r
+import org.eclipse.ui.ISelectionListener;\r
+import org.eclipse.ui.IWorkbenchPart;\r
+import org.eclipse.ui.part.ViewPart;\r
+\r
+/**\r
+ * View for displaying different types of structural visualizations\r
+ * \r
+ * @author Teemu Lempinen\r
+ *\r
+ */\r
+public class StructureView extends ViewPart {\r
+\r
+    private CTabFolder tabFolder;\r
+    private ISelectionListener selectionListener;\r
+    private Dependencies dependencies;\r
+    private ModuleStructure moduleStructure;\r
+    \r
+    \r
+    @Override\r
+    public void createPartControl(Composite parent) {\r
+        tabFolder = new CTabFolder(parent, SWT.BORDER);\r
+        GridDataFactory.fillDefaults().grab(true, true).applyTo(tabFolder);\r
+        GridLayoutFactory.fillDefaults().applyTo(tabFolder);\r
+\r
+        final ISelection currentSeletion = getSite().getWorkbenchWindow().getSelectionService().getSelection();\r
+        \r
+        // Dependencies\r
+        dependencies = new Dependencies(tabFolder, currentSeletion, SWT.NONE);\r
+\r
+        \r
+        // Hierarchical model structure\r
+        moduleStructure = new ModuleStructure(tabFolder, SWT.NONE);\r
+\r
+\r
+        selectionListener = new ISelectionListener() {\r
+\r
+            @Override\r
+            public void selectionChanged(IWorkbenchPart part, ISelection selection) {\r
+                drawSelection(selection);\r
+            }\r
+        };    \r
+        getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(selectionListener);\r
+        \r
+        \r
+        // Listener for refreshing module structure visualization on first loading\r
+        tabFolder.addSelectionListener(new SelectionListener() {\r
+            \r
+            private boolean openedOnce = false;\r
+            \r
+            @Override\r
+            public void widgetSelected(SelectionEvent e) {\r
+                if(!openedOnce && e.item.equals(moduleStructure)) {\r
+                    openedOnce = true;\r
+                    moduleStructure.drawSelection(currentSeletion);\r
+                }\r
+            }\r
+            \r
+            @Override\r
+            public void widgetDefaultSelected(SelectionEvent e) {\r
+            }\r
+        });\r
+    }\r
+    \r
+    /**\r
+     * Draw structural visualizations for selected object(s)\r
+     * \r
+     * @param selection Current selection\r
+     */\r
+    private void drawSelection(ISelection selection) {\r
+        dependencies.drawSelection(selection);\r
+        moduleStructure.drawSelection(selection);\r
+    }\r
+    \r
+\r
+    @Override\r
+    public void setFocus() {\r
+        if(tabFolder != null && !tabFolder.isDisposed()) {\r
+            tabFolder.setFocus();\r
+        }\r
+    }\r
+\r
+\r
+    @Override\r
+    public void dispose() {\r
+        super.dispose();\r
+        getSite().getWorkbenchWindow().getSelectionService().removePostSelectionListener(selectionListener);\r
+    }\r
+\r
+}\r