Some SCL functions to control graphical debugger 24/1724/1
authorHannu Niemistö <hannu.niemisto@semantum.fi>
Thu, 19 Apr 2018 06:09:34 +0000 (09:09 +0300)
committerHannu Niemistö <hannu.niemisto@semantum.fi>
Thu, 19 Apr 2018 06:09:34 +0000 (09:09 +0300)
Possibility to set statement filter and add resources with a function.

refs #7869

Change-Id: Ifb5cc1fb09d3120ea73302d0b1195bc00ec2949e

bundles/org.simantics.debug.graphical/scl/Simantics/GraphicalDebugger.scl
bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/DebuggerCanvas.java
bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/DebuggerSelection.java [deleted file]
bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/GraphicalDebugger.java
bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/layout/BarnesHut.java [deleted file]
bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/layout/BarnesHut2.java [deleted file]

index 490b481d4e18c98ed98b1c3535c0d9e1a9a96db5..7a23274c4028d377c5a216d7e01a55bb8fca54d4 100644 (file)
@@ -1,2 +1,11 @@
+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
index 00a539990a6c466ae42ac0788a254889cab68508..107125f46e35e9f6b20349f6d18528b8a0efcd33 100644 (file)
@@ -1,9 +1,5 @@
 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;
@@ -53,11 +49,17 @@ import org.simantics.debug.graphical.model.LabelContent;
 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;
@@ -74,10 +76,19 @@ public class DebuggerCanvas extends JPanel {
     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;
@@ -284,6 +295,29 @@ public class DebuggerCanvas extends JPanel {
         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() {            
@@ -462,29 +496,41 @@ public class DebuggerCanvas extends JPanel {
             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();
diff --git a/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/DebuggerSelection.java b/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/DebuggerSelection.java
deleted file mode 100644 (file)
index 6be6ee6..0000000
+++ /dev/null
@@ -1,14 +0,0 @@
-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"});
-    }
-    
-
-}
index 7db2772b551ca0e6d58b646e0b9452e689be8d83..9091a27f98d6367d340b1927e111ee393a93703c 100644 (file)
@@ -11,7 +11,7 @@ import javax.swing.JFrame;
 
 public class GraphicalDebugger {
 
-    public static void newGraphDebugger() {
+    public static DebuggerCanvas newGraphDebugger() {
         final JFrame frame = new JFrame();
         frame.setTitle("Graph debugger");
         Toolkit tk = Toolkit.getDefaultToolkit();
@@ -52,6 +52,8 @@ public class GraphicalDebugger {
             
         });        
         frame.setVisible(true);
+        
+        return canvas;
     }
     
 }
diff --git a/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/layout/BarnesHut.java b/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/layout/BarnesHut.java
deleted file mode 100644 (file)
index ef54c25..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-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);
-    }*/
-    
-}
diff --git a/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/layout/BarnesHut2.java b/bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/layout/BarnesHut2.java
deleted file mode 100644 (file)
index 537655f..0000000
+++ /dev/null
@@ -1,189 +0,0 @@
-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>());
-    }
-}