From 449e351cc611899e5022068f6e2cb5f7aabd6eb0 Mon Sep 17 00:00:00 2001 From: lempinen Date: Wed, 19 May 2010 13:33:32 +0000 Subject: [PATCH] Dependency -view for showing backward and forward dependencies of variables. git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@15778 ac1ea38d-2e2b-0410-8846-a27921b304fc --- org.simantics.sysdyn.ui/META-INF/MANIFEST.MF | 4 +- org.simantics.sysdyn.ui/plugin.xml | 8 + .../dependencies/CreateDependencyGraph.java | 102 ++++++++++ .../ui/dependencies/DependencyView.java | 177 ++++++++++++++++++ .../ui/project/SysdynPerspectiveFactory.java | 1 + 5 files changed, 291 insertions(+), 1 deletion(-) create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/dependencies/CreateDependencyGraph.java create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/dependencies/DependencyView.java diff --git a/org.simantics.sysdyn.ui/META-INF/MANIFEST.MF b/org.simantics.sysdyn.ui/META-INF/MANIFEST.MF index 1f8985dd..df09a233 100644 --- a/org.simantics.sysdyn.ui/META-INF/MANIFEST.MF +++ b/org.simantics.sysdyn.ui/META-INF/MANIFEST.MF @@ -24,6 +24,8 @@ Require-Bundle: org.simantics.h2d;bundle-version="1.0.0", org.simantics.browsing.ui.graph;bundle-version="0.9.0", org.simantics.browsing.ui.swt;bundle-version="0.9.0", org.simantics.modeling.ui;bundle-version="1.0.0", - org.eclipse.ui.cheatsheets + org.eclipse.ui.cheatsheets, + org.simantics.graphviz.ui;bundle-version="1.0.0", + org.simantics.graphviz;bundle-version="1.0.0" Bundle-Activator: org.simantics.sysdyn.ui.Activator Bundle-ActivationPolicy: lazy diff --git a/org.simantics.sysdyn.ui/plugin.xml b/org.simantics.sysdyn.ui/plugin.xml index 5fd3e91f..bdc19f69 100644 --- a/org.simantics.sysdyn.ui/plugin.xml +++ b/org.simantics.sysdyn.ui/plugin.xml @@ -75,6 +75,14 @@ name="Configuration View" restorable="true"> + + 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/dependencies/CreateDependencyGraph.java new file mode 100644 index 00000000..2d6f5e00 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/dependencies/CreateDependencyGraph.java @@ -0,0 +1,102 @@ +package org.simantics.sysdyn.ui.dependencies; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; + +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +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.IGraph; +import org.simantics.graphviz.Node; +import org.simantics.sysdyn.SysdynResource; + +public class CreateDependencyGraph implements Read { + + Resource root; + HashMap nodes; + boolean isInverted; + int levels; + + public CreateDependencyGraph(Resource root, int levels, boolean isInverted) { + this.root = root; + this.nodes = new HashMap(); + this.isInverted = isInverted; + this.levels = levels; + } + + @Override + public Graph perform(ReadGraph g) throws DatabaseException { + Graph graph = new Graph(); + graph.setRankdir("LR"); + if (g.isInstanceOf(root, SysdynResource.getInstance(g).IndependentVariable)) { + Collection resources = new ArrayList(); + resources.add(root); + for (int i = 0; i < levels && !resources.isEmpty(); i++) { + Collection newResources = new ArrayList(); + for(Resource r : resources) { + newResources.addAll(getDependencies(g, graph, r)); + } + resources = new ArrayList(newResources); + } + } + return graph; + } + + private Collection getDependencies(ReadGraph g, IGraph graph, Resource r) throws DatabaseException{ + SysdynResource sr = SysdynResource.getInstance(g); + Resource headRelation = sr.IsHeadOf; + Resource tailRelation = sr.HasTail; + if(isInverted) { + headRelation = sr.IsTailOf; + tailRelation = sr.HasHead; + } + + Node n; + if (!nodes.containsKey(r)) { + n = new Node(graph, getName(g, r)); + setShape(g, r, n); + n.set("style", "filled"); + n.setFillColor("#d3d3d3"); + nodes.put(r, n); + } + + Collection dependencies = g.getObjects(r, headRelation); + Collection dependants = new ArrayList(); + for(Resource d : dependencies) { + Resource dependant = g.getSingleObject(d, tailRelation); + if(!g.isInstanceOf(dependant, sr.IndependentVariable)) { + break; + } + if( !nodes.containsKey(dependant)) { + n= new Node(graph, getName(g, dependant)); + setShape(g, dependant, n); + nodes.put(dependant, n); + dependants.add(dependant); + } else { + n = nodes.get(dependant); + } + if(isInverted) + new Edge(graph, nodes.get(r), n); + else + new Edge(graph, n, nodes.get(r)); + } + return dependants; + } + + private void setShape(ReadGraph g, Resource r, Node n) throws DatabaseException { + SysdynResource sr = SysdynResource.getInstance(g); + if(g.isInstanceOf(r, sr.Stock)) + n.setShape("rectangle"); + else + n.setShape("ellipse"); + } + + private String getName(ReadGraph g, Resource r) throws DatabaseException { + return (String)g.getRelatedValue(r, g.getBuiltins().HasName); + } + +} 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/dependencies/DependencyView.java new file mode 100644 index 00000000..7383d030 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/dependencies/DependencyView.java @@ -0,0 +1,177 @@ +package org.simantics.sysdyn.ui.dependencies; + +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.events.ModifyEvent; +import org.eclipse.swt.events.ModifyListener; +import org.eclipse.swt.events.SelectionAdapter; +import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.layout.RowLayout; +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; +import org.simantics.graphviz.ui.GraphvizComponent; +import org.simantics.ui.SimanticsUI; + +public class DependencyView extends ViewPart { + + private GraphvizComponent component; + private boolean disposed, isInverted = false; + private Button bButton, fButton; + private Resource currentSelection; + private int levels = 3; + private ISelectionListener selectionListener; + + static int MAXLEVELS = 4; + static int MINLEVELS = 1; + + @Override + public void createPartControl(Composite parent) { + disposed = false; + GridLayoutFactory.fillDefaults().margins(3, 3).applyTo(parent); + + component = new GraphvizComponent(parent, SWT.BORDER); + GridDataFactory.fillDefaults().grab(true, true).applyTo(component); + + Composite composite = new Composite(parent, SWT.NULL); + RowLayout layout = new RowLayout(); + layout.center = true; + composite.setLayout(layout); + + Label label = new Label(composite, SWT.NULL); + label.setText("Direction: "); + + bButton = new Button(composite, SWT.RADIO); + bButton.setText("Backward"); + bButton.setSelection(true); + bButton.addSelectionListener(new SelectionAdapter() { + public void widgetSelected(SelectionEvent event) { + if(bButton.getSelection()) + isInverted = false; + else + isInverted = true; + if(currentSelection != null) { + readGraph(currentSelection); + } + } + }); + + fButton = new Button(composite, SWT.RADIO); + fButton.setText("Forward"); + + label = new Label(composite, SWT.NULL); + label.setText("Steps: "); + + Spinner spinner = new Spinner(composite, SWT.BORDER); + spinner.setMaximum(MAXLEVELS); + spinner.setMinimum(MINLEVELS); + spinner.setTextLimit(1); + spinner.setSelection(levels); + + spinner.addModifyListener(new ModifyListener() { + + @Override + public void modifyText(ModifyEvent e) { + Spinner s = (Spinner)e.widget; + int lvls = Integer.parseInt(s.getText()); + if(lvls > MAXLEVELS) + levels = MAXLEVELS; + else if (lvls < MINLEVELS) + levels = MINLEVELS; + levels = lvls; + if(currentSelection != null) { + readGraph(currentSelection); + } + + } + }); + + drawSelection(getSite().getWorkbenchWindow().getSelectionService().getSelection()); + + selectionListener = new ISelectionListener() { + + @Override + public void selectionChanged(IWorkbenchPart part, ISelection selection) { + drawSelection(selection); + } + }; + getSite().getWorkbenchWindow().getSelectionService().addPostSelectionListener(selectionListener); + } + + private void drawSelection(ISelection selection) { + if(selection == null || selection.isEmpty()) + return; + if(selection instanceof IStructuredSelection) { + Object[] els = ((IStructuredSelection) selection).toArray(); + if(els.length == 1) { + if(els[0] instanceof Resource && !els[0].equals(currentSelection)) { + currentSelection = (Resource)els[0]; + readGraph(currentSelection); + } + } + } + } + + 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; + } + }); + } + + + @Override + public void setFocus() { + if (component != null && !component.isDisposed()) + component.requestFocus(); + } + + + @Override + public void dispose() { + super.dispose(); + getSite().getWorkbenchWindow().getSelectionService().removePostSelectionListener(selectionListener); + disposed = true; + } + +} diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynPerspectiveFactory.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynPerspectiveFactory.java index 2777b630..1d86dbe6 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynPerspectiveFactory.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/project/SysdynPerspectiveFactory.java @@ -39,6 +39,7 @@ public class SysdynPerspectiveFactory implements IPerspectiveFactory { bottom1.addView(IConsoleConstants.ID_CONSOLE_VIEW); bottom1.addView("org.simantics.sysdyn.ui.configurationView"); bottom2.addView("org.simantics.sysdyn.ui.trend.view"); + bottom2.addView("org.simantics.sysdyn.ui.dependencies.view"); IFolderLayout left = layout.createFolder("left", IPageLayout.LEFT, 0.25f, editorArea); left.addView("org.simantics.sysdyn.ui.browser"); -- 2.47.1