From 6b6b1cdfcd548f6571a1f417d463e9feb8a9abc3 Mon Sep 17 00:00:00 2001 From: miettinen Date: Mon, 20 Jan 2014 08:33:48 +0000 Subject: [PATCH] Loops under structure view in Sysdyn: consider flows bidirectional dependencies, and refactoring (refs #3012). git-svn-id: https://www.simantics.org/svn/simantics/sysdyn/trunk@28672 ac1ea38d-2e2b-0410-8846-a27921b304fc --- .../sysdyn/ui/structure/Dependencies.java | 97 ++-------- .../sysdyn/ui/structure/LoopGraphRequest.java | 11 +- .../simantics/sysdyn/ui/structure/Loops.java | 166 ++---------------- .../sysdyn/ui/structure/StructureTabItem.java | 115 ++++++++++++ .../sysdyn/ui/structure/StructureView.java | 6 +- .../sysdyn/utils/ConfigurationUtils.java | 27 ++- 6 files changed, 174 insertions(+), 248 deletions(-) create mode 100644 org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/StructureTabItem.java diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/Dependencies.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/Dependencies.java index 348d098e..02e052d8 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/Dependencies.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/Dependencies.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2010, 2012 Association for Decentralized Information Management in + * Copyright (c) 2010, 2012, 2014 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 @@ -11,19 +11,9 @@ *******************************************************************************/ 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.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; @@ -34,38 +24,24 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Spinner; 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.ui.ISelectionUtils; -public class Dependencies extends CTabItem { +public class Dependencies extends StructureTabItem { - private GraphvizComponent component; private boolean isInverted = false; private Button bButton, fButton; - private Resource currentSelection; private int levels = 3; - private GraphListener graphListener; - static int MAXLEVELS = 4; - static int MINLEVELS = 1; + private static int MAXLEVELS = 4; + private static int MINLEVELS = 1; - public Dependencies(CTabFolder parent, ISelection selection, int style) { + public Dependencies(CTabFolder parent, 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(dependencies, SWT.NONE); - GridDataFactory.fillDefaults().grab(true, true).applyTo(component); - - Label line = new Label(dependencies, SWT.SEPARATOR | SWT.SHADOW_OUT | SWT.HORIZONTAL); + Label line = new Label(structureComposite, SWT.SEPARATOR | SWT.SHADOW_OUT | SWT.HORIZONTAL); GridDataFactory.fillDefaults().grab(true, false).applyTo(line); - Composite composite = new Composite(dependencies, SWT.NONE); + Composite composite = new Composite(structureComposite, SWT.NONE); RowLayout layout = new RowLayout(); layout.center = true; composite.setLayout(layout); @@ -118,31 +94,11 @@ public class Dependencies extends CTabItem { } }); - drawSelection(selection); - this.setText("Dependencies"); - this.setControl(dependencies); + this.setControl(structureComposite); } - - 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 && !r.equals(currentSelection)) { - currentSelection = r; - readGraph(currentSelection); - } - } - } - } - - private void readGraph(Resource resource) { + protected void readGraph(Resource resource) { if(graphListener != null) graphListener.dispose(); @@ -151,38 +107,7 @@ public class Dependencies extends CTabItem { resource, levels, isInverted), graphListener); } - 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 boolean isDisposed() { - return disposed; - } + protected String getJobLabel() { + return "Loading dependencies graph"; } } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/LoopGraphRequest.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/LoopGraphRequest.java index 4d15341e..f9b7c874 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/LoopGraphRequest.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/LoopGraphRequest.java @@ -44,8 +44,8 @@ public class LoopGraphRequest extends DependencyGraphRequest { * @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 LoopGraphRequest(Resource root, int levels, boolean isInverted) { - super(root, levels, isInverted); + public LoopGraphRequest(Resource root) { + super(root, 999, false); } @Override @@ -61,9 +61,11 @@ public class LoopGraphRequest extends DependencyGraphRequest { } SysdynResource sr = SysdynResource.getInstance(g); if (g.isInstanceOf(root, sr.IndependentVariable) || g.isInstanceOf(root, sr.Input)) { + // Get ALL loops in the diagram in which the root exists. List> loops = ConfigurationUtils.getLoops(g, root); setRoot(g, graph, root); + // Add the edges to the graph. edges = new MapList(); for (List loop : loops) { Resource prev = null; @@ -98,8 +100,8 @@ public class LoopGraphRequest extends DependencyGraphRequest { * @throws DatabaseException */ private void claimEdge(ReadGraph g, IGraph graph, Resource tail, Resource head) throws DatabaseException { - // If edge exists, return - for (Edge e : edges.getValues(tail)) + // If edge exists, increase the size of the arrowhead and return. + for (Edge e : edges.getValues(tail)) { if (((Node)e.getHead()).get("label").equals(getName(g, head))) { // Change the size of the arrowhead (fancily :-) String arrowsize = e.get("arrowsize"); @@ -108,6 +110,7 @@ public class LoopGraphRequest extends DependencyGraphRequest { e.setArrowsize(Math.min(2.2, Math.sqrt(Double.valueOf(arrowsize) + 0.8))); return; } + } for (Edge e : edges.getValues(head)) { // Seek for opposite edges if (((Node)e.getHead()).get("label").equals(getName(g, tail))) { diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/Loops.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/Loops.java index 6afb8edb..798b5043 100644 --- a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/Loops.java +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/Loops.java @@ -11,176 +11,34 @@ *******************************************************************************/ 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.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.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.ui.ISelectionUtils; - -public class Loops extends CTabItem { - - private GraphvizComponent component; - private boolean isInverted = false; - private Button bButton, fButton; - private Resource currentSelection; - private int levels = 3; - private GraphListener graphListener; - static int MAXLEVELS = 4; - static int MINLEVELS = 1; +/** + * Tab for loops. + * @author Tuomas Miettinen + * + */ +public class Loops extends StructureTabItem { public Loops(CTabFolder parent, int style) { super(parent, style); - - Composite loops = new Composite(parent, SWT.NONE); - GridDataFactory.fillDefaults().grab(true, true).applyTo(loops); - GridLayoutFactory.fillDefaults().spacing(0,0).applyTo(loops); - - component = new GraphvizComponent(loops, SWT.NONE); - GridDataFactory.fillDefaults().grab(true, true).applyTo(component); - - Label line = new Label(loops, SWT.SEPARATOR | SWT.SHADOW_OUT | SWT.HORIZONTAL); - GridDataFactory.fillDefaults().grab(true, false).applyTo(line); - - Composite composite = new Composite(loops, SWT.NONE); - RowLayout layout = new RowLayout(); - layout.center = true; - composite.setLayout(layout); - - Label label = new Label(composite, SWT.NONE); - 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.NONE); - 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); - } - - } - }); - this.setText("Loops"); - this.setControl(loops); + this.setControl(structureComposite); } - - 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 && !r.equals(currentSelection)) { - currentSelection = r; - readGraph(currentSelection); - } - } - } - } - - private void readGraph(Resource resource) { + protected void readGraph(Resource resource) { if(graphListener != null) graphListener.dispose(); graphListener = new GraphListener(); SimanticsUI.getSession().asyncRequest(new LoopGraphRequest( - resource, levels, isInverted), graphListener); + resource), graphListener); } - 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 loops 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; - } + protected String getJobLabel() { + return "Loading loops graph"; } + } diff --git a/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/StructureTabItem.java b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/StructureTabItem.java new file mode 100644 index 00000000..ceadd9d4 --- /dev/null +++ b/org.simantics.sysdyn.ui/src/org/simantics/sysdyn/ui/structure/StructureTabItem.java @@ -0,0 +1,115 @@ +/******************************************************************************* + * Copyright (c) 2010, 2012, 2014 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.utils.ui.ISelectionUtils; + +/** + * Super class for certain kinds of structure tabs. + * @author Tuomas Miettinen + * + */ +public abstract class StructureTabItem extends CTabItem { + + protected GraphvizComponent component; + protected GraphListener graphListener; + protected Composite structureComposite; + protected Resource currentSelection; + + public StructureTabItem(CTabFolder parent, int style) { + super(parent, style); + + structureComposite = new Composite(parent, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).applyTo(structureComposite); + GridLayoutFactory.fillDefaults().spacing(0,0).applyTo(structureComposite); + + component = new GraphvizComponent(structureComposite, SWT.NONE); + GridDataFactory.fillDefaults().grab(true, true).applyTo(component); + } + + + 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 && !r.equals(currentSelection)) { + currentSelection = r; + readGraph(currentSelection); + } + } + } + } + + abstract protected void readGraph(Resource resource); + + 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(getJobLabel()) { + + @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; + } + } + + protected String getJobLabel() { + return "Loading dependencies graph"; + } +} 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 index 7d7f53dd..39dc59dd 100644 --- 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 @@ -34,7 +34,7 @@ public class StructureView extends ViewPart { private CTabFolder tabFolder; private ISelectionListener selectionListener; - private Dependencies dependencies; + private StructureTabItem dependencies; private ModuleStructure moduleStructure; private Loops loops; @@ -47,8 +47,8 @@ public class StructureView extends ViewPart { final ISelection currentSeletion = getSite().getWorkbenchWindow().getSelectionService().getSelection(); // Dependencies - dependencies = new Dependencies(tabFolder, currentSeletion, SWT.NONE); - + dependencies = new Dependencies(tabFolder, SWT.NONE); + dependencies.drawSelection(currentSeletion); // Hierarchical model structure moduleStructure = new ModuleStructure(tabFolder, SWT.NONE); diff --git a/org.simantics.sysdyn/src/org/simantics/sysdyn/utils/ConfigurationUtils.java b/org.simantics.sysdyn/src/org/simantics/sysdyn/utils/ConfigurationUtils.java index ef821e85..e10cbe9d 100644 --- a/org.simantics.sysdyn/src/org/simantics/sysdyn/utils/ConfigurationUtils.java +++ b/org.simantics.sysdyn/src/org/simantics/sysdyn/utils/ConfigurationUtils.java @@ -1,3 +1,14 @@ +/******************************************************************************* + * Copyright (c) 2014 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.utils; import java.util.ArrayList; @@ -96,13 +107,27 @@ public class ConfigurationUtils { HashMap elementaryLoopItems = new HashMap(); for (Resource variable : variables) { ArrayList dependingVariables = new ArrayList(); + // Add forward dependencies and flows. Collection dependencies = g.getObjects(variable, sr.Variable_isTailOf); for (Resource dependency : dependencies) { Resource head = g.getPossibleObject(dependency, sr.Variable_HasHead); - if (!g.isInstanceOf(head, sr.Module)) { + if (head != null + && !g.isInstanceOf(head, sr.Module) + && !g.isInstanceOf(head, sr.Cloud)) { dependingVariables.add(head); } } + // Add backward flows. + Collection backwardFlows = g.getObjects(variable, sr.Variable_isHeadOf); + for (Resource flow : backwardFlows) { + if (g.isInstanceOf(flow, sr.Flow)) { + Resource tail = g.getPossibleObject(flow, sr.Variable_HasTail); + if (tail != null && !g.isInstanceOf(tail, sr.Cloud)) { + dependingVariables.add(tail); + } + } + } + // Put the variable in the hash map. elementaryLoopItems.put(variable, new ElementaryLoopItem(k, dependingVariables)); nodes[k++] = variable; } -- 2.47.1