<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
+/*******************************************************************************\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
\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
/*******************************************************************************\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
* 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
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
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
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
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
\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
}\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
/*******************************************************************************\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
* 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
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
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
}\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
}\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
\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
--- /dev/null
+/*******************************************************************************\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
--- /dev/null
+/*******************************************************************************\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
--- /dev/null
+/*******************************************************************************\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