Possibility to set statement filter and add resources with a function.
refs #7869
Change-Id: Ifb5cc1fb09d3120ea73302d0b1195bc00ec2949e
+import "Simantics/DB"
+
+importJava "org.simantics.debug.graphical.DebuggerCanvas" where
+ data GraphDebugger
+
+ setStatementFilter :: GraphDebugger -> (Statement -> <ReadGraph,Proc> Boolean) -> <Proc> ()
+ removeStatementFilter :: GraphDebugger -> <Proc> ()
+ addResource :: GraphDebugger -> Resource -> <Proc> ()
+
importJava "org.simantics.debug.graphical.GraphicalDebugger" where
- newGraphDebugger :: <Proc> ()
\ No newline at end of file
+ newGraphDebugger :: <Proc> GraphDebugger
\ No newline at end of file
package org.simantics.debug.graphical;
-import gnu.trove.list.array.TDoubleArrayList;
-import gnu.trove.map.hash.THashMap;
-import gnu.trove.map.hash.TObjectIntHashMap;
-
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import org.simantics.debug.graphical.model.Node;
import org.simantics.debug.graphical.model.NodeData;
import org.simantics.layer0.Layer0;
+import org.simantics.scl.runtime.SCLContext;
+import org.simantics.scl.runtime.function.Function;
import org.simantics.ui.dnd.LocalObjectTransfer;
import org.simantics.ui.dnd.LocalObjectTransferable;
import org.simantics.ui.selection.AnyResource;
import org.simantics.ui.selection.WorkbenchSelectionElement;
+import gnu.trove.list.array.TDoubleArrayList;
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+
public class DebuggerCanvas extends JPanel {
private static final long serialVersionUID = -718678297301786379L;
double canvasZoom = 1.0;
boolean extensionMode = false;
Random random = new Random();
-
+ public Function statementFilter;
+
LabelingPreferences labelingPreferences =
new LabelingPreferences();
+ public void setStatementFilter(Function statementFilter) {
+ this.statementFilter = statementFilter;
+ }
+
+ public void removeStatementFilter() {
+ this.statementFilter = null;
+ }
+
@Override
public void paint(Graphics _g) {
Graphics2D g = (Graphics2D)_g;
nodes.add(a);
return a;
}
+
+ public void addResource(Resource resource) {
+ double x, y;
+ if(nodes.isEmpty()) {
+ x = 0.0;
+ y = 0.0;
+ }
+ else {
+ double xMin=Double.POSITIVE_INFINITY, yMin=Double.POSITIVE_INFINITY;
+ double xMax=Double.NEGATIVE_INFINITY, yMax=Double.NEGATIVE_INFINITY;
+ for(Node node : nodes) {
+ xMin = Math.min(node.getMinX(), xMin);
+ yMin = Math.min(node.getMinY(), yMin);
+ xMax = Math.max(node.getMaxX(), xMax);
+ yMax = Math.max(node.getMaxY(), yMax);
+ }
+ x = xMin + (xMax - xMin) * random.nextDouble();
+ y = yMin + (yMax - yMin) * random.nextDouble();
+ }
+
+ addResource(x, y, resource);
+ repaint();
+ }
private void scheduleUpdate() {
Simantics.getSession().asyncRequest(new ReadRequest() {
Simantics.getSession().syncRequest(new ReadRequest() {
@Override
public void run(ReadGraph graph) throws DatabaseException {
- THashMap<Resource, Node> oldExtensionNodeMap = DebuggerCanvas.this.extensionNodeMap;
- THashMap<Resource, Node> extensionNodeMap = new THashMap<Resource, Node>();
- for(Node node : nodes) {
- for(Statement stat : node.getData().getStatements()) {
- Resource object = stat.getObject();
- Node node2 = extensionNodeMap.get(object);
- if(node2 == null) {
- node2 = oldExtensionNodeMap.get(object);
+ SCLContext sclContext = SCLContext.getCurrent();
+ Object oldGraph = sclContext.put("graph", graph);
+ try {
+ THashMap<Resource, Node> oldExtensionNodeMap = DebuggerCanvas.this.extensionNodeMap;
+ THashMap<Resource, Node> extensionNodeMap = new THashMap<Resource, Node>();
+ for(Node node : nodes) {
+ for(Statement stat : node.getData().getStatements()) {
+ Resource object = stat.getObject();
+ Node node2 = extensionNodeMap.get(object);
if(node2 == null) {
- node2 = new Node(new NodeData(object));
- double angle = random.nextDouble() * Math.PI * 2.0;
- double dx = Math.cos(angle);
- double dy = Math.sin(angle);
- double len = 150.0;
- node2.setPos(node.getX() + dx*len, node.getY() + dy*len);
+ if(statementFilter != null && Boolean.FALSE.equals(statementFilter.apply(stat)))
+ continue;
+ node2 = oldExtensionNodeMap.get(object);
+ if(node2 == null) {
+ node2 = new Node(new NodeData(object));
+ double angle = random.nextDouble() * Math.PI * 2.0;
+ double dx = Math.cos(angle);
+ double dy = Math.sin(angle);
+ double len = 150.0;
+ node2.setPos(node.getX() + dx*len, node.getY() + dy*len);
+ }
+ node2.getData().updateData(graph, labelingPreferences);
+ node2.setContent(new LabelContent(node2.getData().getLabels()));
+ extensionNodeMap.put(object, node2);
+ extensionNodes.add(node2);
}
- node2.getData().updateData(graph, labelingPreferences);
- node2.setContent(new LabelContent(node2.getData().getLabels()));
- extensionNodeMap.put(object, node2);
- extensionNodes.add(node2);
+ extensionEdges.add(createEdge(graph, stat, node, node2));
}
- extensionEdges.add(createEdge(graph, stat, node, node2));
}
+ } catch (Throwable t) {
+ if (t instanceof DatabaseException)
+ throw (DatabaseException) t;
+ throw new DatabaseException(t);
+ } finally {
+ sclContext.put("graph", oldGraph);
}
DebuggerCanvas.this.extensionNodeMap = extensionNodeMap;
layoutExtension();
+++ /dev/null
-package org.simantics.debug.graphical;
-
-import javax.swing.JList;
-
-public class DebuggerSelection extends JList {
-
- private static final long serialVersionUID = 2502385778204965742L;
-
- public DebuggerSelection() {
- super(new String[] {"a", "b", "c"});
- }
-
-
-}
public class GraphicalDebugger {
- public static void newGraphDebugger() {
+ public static DebuggerCanvas newGraphDebugger() {
final JFrame frame = new JFrame();
frame.setTitle("Graph debugger");
Toolkit tk = Toolkit.getDefaultToolkit();
});
frame.setVisible(true);
+
+ return canvas;
}
}
+++ /dev/null
-package org.simantics.debug.graphical.layout;
-
-public class BarnesHut {
-
- static class Bounds {
- final double minX;
- final double minY;
- final double maxX;
- final double maxY;
-
- public Bounds(double minX, double minY, double maxX, double maxY) {
- this.minX = minX;
- this.minY = minY;
- this.maxX = maxX;
- this.maxY = maxY;
- }
- }
-
- private static Bounds computeOctreeBounds(double[] posX, double[] posY) {
- double minX = posX[0];
- double minY = posY[0];
- double maxX = posX[0];
- double maxY = posY[0];
-
- for(int i=1;i<posX.length;++i) {
- double x = posX[i];
- double y = posY[i];
- if(x < minX)
- minX = x;
- else if(x > maxX)
- maxX = x;
- if(y < minY)
- minY = y;
- else if(y > maxY)
- maxY = y;
- }
-
- double diff = (maxX - minX) - (maxY - minY);
- diff *= 0.5;
- if(diff > 0.0) {
- minY -= diff;
- maxY += diff;
- }
- else {
- minX += diff;
- maxX -= diff;
- }
- return new Bounds(minX, minY, maxX, maxY);
- }
-
- private static class VecRef {
- double x;
- double y;
- }
-
- /*private static void force(VecRef f, double x1, double y1, double x2, double y2) {
- double dx = x2 - x1;
- double dy = y2 - y1;
- double l2 = dx*dx + dy*dy;
- double s = Q / l2;
- f.x -= s * dx;
- f.y -= s * dy;
- }
-
- private static void forceNear(VecRef f, double x1, double y1, OctreeNode node, double[] posX, double[] posY) {
- if(node instanceof OctreeLeaf) {
- for(int id : ((OctreeLeaf)node).ids) {
- force(f, x1, y1, posX[id], posY[id]);
- }
- }
- else {
- OctreeInnerNode inner = (OctreeInnerNode)node;
- forceNear(f, x1, y1, inner.n00, posX, posY);
- forceNear(f, x1, y1, inner.n10, posX, posY);
- forceNear(f, x1, y1, inner.n01, posX, posY);
- forceNear(f, x1, y1, inner.n11, posX, posY);
- }
- }
-
- private static void forceFar(VecRef f, double x1, double y1, OctreeNode node) {
- double dx = node.massCenterX - x1;
- double dy = node.massCenterY - y1;
- double l2 = dx*dx + dy*dy;
- double s = Q * node.mass / l2;
- f.x -= s * dx;
- f.y -= s * dy;
- }
-
- private static void computeForce(OctreeNode octree,
- ArrayList<OctreeNode> farNodes,
- ArrayList<OctreeNode> nearNodes,
- double[] posX, double[] posY,
- double[] forceX, double[] forceY) {
- VecRef f = new VecRef();
- if(octree instanceof OctreeLeaf) {
- int[] ids = ((OctreeLeaf)octree).ids;
- for(int i=0;i<ids.length;++i) {
- int id = ids[i];
-
- double x = posX[id];
- double y = posY[id];
- f.x = 0.0;
- f.y = 0.0;
-
- for(int j=0;j<ids.length;++j)
- if(j != i) {
- int id2 = ids[j];
- force(f, x, y, posX[id2], posY[id2]);
- }
- for(OctreeNode node : nearNodes)
- forceNear(f, x, y, node, posX, posY);
- for(OctreeNode node : farNodes)
- forceFar(f, x, y, node);
-
- forceX[id] += f.x;
- forceY[id] += f.y;
- }
- }
- else {
- OctreeInnerNode inner = (OctreeInnerNode)octree;
- computeForce(inner.n00, farNodes, nearNodes, posX, posY, forceX, forceY);
- computeForce(inner.n10, farNodes, nearNodes, posX, posY, forceX, forceY);
- computeForce(inner.n01, farNodes, nearNodes, posX, posY, forceX, forceY);
- computeForce(inner.n11, farNodes, nearNodes, posX, posY, forceX, forceY);
- }
- }
-
- public static void computeRepulsiveForces(double[] posX, double[] posY, double[] forceX, double[] forceY) {
- Bounds bounds = computeOctreeBounds(posX, posY);
-
- TIntArrayList ids = new TIntArrayList(posX.length);
- for(int i=0;i<posX.length;++i)
- ids.add(i);
- OctreeNode octree = constructOctree(bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, ids, posX, posY);
-
- computeForce(octree, new ArrayList<OctreeNode>(), new ArrayList<OctreeNode>(), posX, posY, forceX, forceY);
- }*/
-
-}
+++ /dev/null
-package org.simantics.debug.graphical.layout;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-
-public class BarnesHut2 {
-
- static final double OPTIMAL_DISTANCE = 150.0;
- static final double C = 0.1;
- static final double K = C / OPTIMAL_DISTANCE;
- static final double G = K;
- static final double Q = C * OPTIMAL_DISTANCE * OPTIMAL_DISTANCE;
-
- public static final int OCTREE_LEAF_SIZE = 25;
-
- public static void applyDirectedForce(Particle a, Particle b) {
- double dx = a.x - b.x;
- double dy = a.y - b.y;
- double l2 = dx*dx + dy*dy;
- double s = Q / l2;
- a.fx += s * dx;
- a.fy += s * dy;
- }
-
- public static void applyDirectedForce(Particle a, OctreeNode b) {
- double dx = a.x - b.massCenterX;
- double dy = a.y - b.massCenterY;
- double l2 = dx*dx + dy*dy;
- double s = Q * b.mass / l2;
- a.fx += s * dx;
- a.fy += s * dy;
- }
-
- private static abstract class OctreeNode {
- double mass;
- double massCenterX;
- double massCenterY;
- }
-
- private static class OctreeInnerNode extends OctreeNode {
- final OctreeNode n00;
- final OctreeNode n10;
- final OctreeNode n01;
- final OctreeNode n11;
-
- public OctreeInnerNode(OctreeNode n00, OctreeNode n10, OctreeNode n01, OctreeNode n11) {
- this.n00 = n00;
- this.n10 = n10;
- this.n01 = n01;
- this.n11 = n11;
-
- double mass00 = n00.mass;
- double mass10 = n10.mass;
- double mass01 = n01.mass;
- double mass11 = n11.mass;
- double totalMass = mass00 + mass10 + mass01 + mass11;
-
- this.mass = totalMass;
- this.massCenterX =
- (n00.massCenterX*mass00 + n10.massCenterX*mass10 +
- n01.massCenterX*mass01 + n11.massCenterX*mass11)
- / totalMass;
- this.massCenterY =
- (n00.massCenterY*mass00 + n10.massCenterY*mass10 +
- n01.massCenterY*mass01 + n11.massCenterY*mass11)
- / totalMass;
- }
- }
-
- private static class OctreeLeaf extends OctreeNode {
- final Particle[] ps;
-
- public OctreeLeaf(Particle[] ps) {
- this.ps = ps;
-
- double massCenterX = 0.0;
- double massCenterY = 0.0;
- for(Particle p : ps) {
- massCenterX += p.x;
- massCenterY += p.y;
- }
-
- this.mass = ps.length;
- this.massCenterX = massCenterX / ps.length;
- this.massCenterY = massCenterY / ps.length;
- }
- }
-
- private static OctreeNode constructOctree(double minX, double minY, double maxX, double maxY,
- ArrayList<Particle> ps) {
- if(ps.size() < OCTREE_LEAF_SIZE)
- return new OctreeLeaf(ps.toArray(new Particle[ps.size()]));
-
- double midX = 0.5 * (minX + maxX);
- double midY = 0.5 * (minY + maxY);
-
- ArrayList<Particle> ps00 = new ArrayList<Particle>();
- ArrayList<Particle> ps10 = new ArrayList<Particle>();
- ArrayList<Particle> ps01 = new ArrayList<Particle>();
- ArrayList<Particle> ps11 = new ArrayList<Particle>();
-
- for(Particle p : ps) {
- double x = p.x;
- double y = p.y;
- if(x < midX) {
- if(y < midY)
- ps00.add(p);
- else
- ps01.add(p);
- }
- else {
- if(y < midY)
- ps10.add(p);
- else
- ps11.add(p);
- }
- }
-
- return new OctreeInnerNode(
- constructOctree(minX, minY, midX, midY, ps00),
- constructOctree(midX, minY, maxX, midY, ps10),
- constructOctree(minX, midY, midX, maxY, ps01),
- constructOctree(midX, midY, maxX, maxY, ps11)
- );
- }
-
- static class Bounds {
- final double minX;
- final double minY;
- final double maxX;
- final double maxY;
-
- public Bounds(double minX, double minY, double maxX, double maxY) {
- this.minX = minX;
- this.minY = minY;
- this.maxX = maxX;
- this.maxY = maxY;
- }
- }
-
- private static Bounds computeOctreeBounds(ArrayList<Particle> ps) {
- Iterator<Particle> it = ps.iterator();
-
- Particle pFirst = it.next();
-
- double minX = pFirst.x;
- double minY = pFirst.y;
- double maxX = pFirst.x;
- double maxY = pFirst.y;
-
- while(it.hasNext()) {
- Particle p = it.next();
- double x = p.x;
- double y = p.y;
- if(x < minX)
- minX = x;
- else if(x > maxX)
- maxX = x;
- if(y < minY)
- minY = y;
- else if(y > maxY)
- maxY = y;
- }
-
- double diff = (maxX - minX) - (maxY - minY);
- diff *= 0.5;
- if(diff > 0.0) {
- minY -= diff;
- maxY += diff;
- }
- else {
- minX += diff;
- maxX -= diff;
- }
- return new Bounds(minX, minY, maxX, maxY);
- }
-
- private static void computeForce(OctreeNode octree,
- ArrayList<OctreeNode> nearNodes, ArrayList<OctreeNode> farNodes) {
- // TODO Auto-generated method stub
-
- }
-
- public static void computeRepulsiveForces(ArrayList<Particle> ps) {
- Bounds bounds = computeOctreeBounds(ps);
- OctreeNode octree = constructOctree(bounds.minX, bounds.minY, bounds.maxX, bounds.maxY, ps);
- computeForce(octree, new ArrayList<OctreeNode>(), new ArrayList<OctreeNode>());
- }
-}