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