]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.debug.graphical/src/org/simantics/debug/graphical/DebuggerCanvas.java
Support Json content as drop data in Graphical Debugger
[simantics/platform.git] / bundles / org.simantics.debug.graphical / src / org / simantics / debug / graphical / DebuggerCanvas.java
index 00a539990a6c466ae42ac0788a254889cab68508..310d8a0865e824cfc8b0f6e51dd26af1bf41c78b 100644 (file)
@@ -1,16 +1,12 @@
 package org.simantics.debug.graphical;
 
 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 java.awt.Graphics2D;
 import java.awt.RenderingHints;
 import java.awt.Color;
 import java.awt.GradientPaint;
 import java.awt.Graphics;
 import java.awt.Graphics2D;
 import java.awt.RenderingHints;
+import java.awt.datatransfer.DataFlavor;
 import java.awt.datatransfer.Transferable;
 import java.awt.datatransfer.Transferable;
-import java.awt.datatransfer.UnsupportedFlavorException;
 import java.awt.dnd.DnDConstants;
 import java.awt.dnd.DropTarget;
 import java.awt.dnd.DropTargetAdapter;
 import java.awt.dnd.DnDConstants;
 import java.awt.dnd.DropTarget;
 import java.awt.dnd.DropTargetAdapter;
@@ -25,7 +21,7 @@ import java.awt.event.MouseWheelListener;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
-import java.io.IOException;
+import java.io.Reader;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Random;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Random;
@@ -35,6 +31,7 @@ import javax.swing.SwingUtilities;
 
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.jface.viewers.IStructuredSelection;
 
 import org.eclipse.core.runtime.IAdaptable;
 import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.StructuredSelection;
 import org.simantics.Simantics;
 import org.simantics.db.ChangeSet;
 import org.simantics.db.ChangeSetIdentifier;
 import org.simantics.Simantics;
 import org.simantics.db.ChangeSet;
 import org.simantics.db.ChangeSetIdentifier;
@@ -45,7 +42,9 @@ import org.simantics.db.Statement;
 import org.simantics.db.common.request.ReadRequest;
 import org.simantics.db.common.utils.NameUtils;
 import org.simantics.db.exception.DatabaseException;
 import org.simantics.db.common.request.ReadRequest;
 import org.simantics.db.common.utils.NameUtils;
 import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.request.Read;
 import org.simantics.db.service.ManagementSupport;
 import org.simantics.db.service.ManagementSupport;
+import org.simantics.db.service.SerialisationSupport;
 import org.simantics.debug.graphical.layout.ExtensionLayoutAlgorithm;
 import org.simantics.debug.graphical.layout.LayoutGraph;
 import org.simantics.debug.graphical.model.Edge;
 import org.simantics.debug.graphical.layout.ExtensionLayoutAlgorithm;
 import org.simantics.debug.graphical.layout.LayoutGraph;
 import org.simantics.debug.graphical.model.Edge;
@@ -53,13 +52,26 @@ 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.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 org.simantics.ui.dnd.LocalObjectTransfer;
 import org.simantics.ui.dnd.LocalObjectTransferable;
 import org.simantics.ui.selection.AnyResource;
 import org.simantics.ui.selection.WorkbenchSelectionElement;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 
-public class DebuggerCanvas extends JPanel {
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.NumericNode;
+
+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 Logger LOGGER = LoggerFactory.getLogger(DebuggerCanvas.class);
+    
     private static final long serialVersionUID = -718678297301786379L;
     
     ArrayList<Node> nodes = new ArrayList<Node>();
     private static final long serialVersionUID = -718678297301786379L;
     
     ArrayList<Node> nodes = new ArrayList<Node>();
@@ -74,10 +86,19 @@ public class DebuggerCanvas extends JPanel {
     double canvasZoom = 1.0;
     boolean extensionMode = false;
     Random random = new Random();
     double canvasZoom = 1.0;
     boolean extensionMode = false;
     Random random = new Random();
-
+    public Function statementFilter;
+    
     LabelingPreferences labelingPreferences = 
             new LabelingPreferences();
     
     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;
     @Override
     public void paint(Graphics _g) {
         Graphics2D g = (Graphics2D)_g;
@@ -186,33 +207,55 @@ public class DebuggerCanvas extends JPanel {
             public void drop(DropTargetDropEvent dtde) {
                 try {
                     Transferable transferable = dtde.getTransferable();
             public void drop(DropTargetDropEvent dtde) {
                 try {
                     Transferable transferable = dtde.getTransferable();
-                    
                     if( transferable.isDataFlavorSupported( 
                             LocalObjectTransferable.FLAVOR ) ) {
                         dtde.acceptDrop( DnDConstants.ACTION_MOVE );
                         
                     if( transferable.isDataFlavorSupported( 
                             LocalObjectTransferable.FLAVOR ) ) {
                         dtde.acceptDrop( DnDConstants.ACTION_MOVE );
                         
-                        transferable.getTransferData(LocalObjectTransferable.FLAVOR );
+                        transferable.getTransferData(LocalObjectTransferable.FLAVOR);
                         Object obj = LocalObjectTransfer.getTransfer().getObject();
                         Object obj = LocalObjectTransfer.getTransfer().getObject();
-                        double x = canvasPosX+dtde.getLocation().getX()/canvasZoom;
-                        double y = canvasPosY+dtde.getLocation().getY()/canvasZoom;
-                        handleDrop(x, y, obj);
-                        
-                        dtde.getDropTargetContext().dropComplete( true );
+                        handleDrop(dtde, obj);
                     }
                     else {
                     }
                     else {
+                        DataFlavor textFlavor = DataFlavor.selectBestTextFlavor(transferable.getTransferDataFlavors());
+                        if(textFlavor != null) {
+                            // Try to read the textual content of the drop event as a JSON object containing a field named resourceId
+                            try(Reader reader = textFlavor.getReaderForText(transferable)) {
+                                ObjectMapper mapper = new ObjectMapper();
+                                JsonNode node = mapper.readTree(reader);
+                                Object resourceId = node.get("resourceId");
+                                if(resourceId instanceof NumericNode) {
+                                    dtde.acceptDrop( DnDConstants.ACTION_MOVE );
+                                    
+                                    transferable.getTransferData(LocalObjectTransferable.FLAVOR);
+                                    Object obj = new StructuredSelection(Simantics.getSession().syncRequest(new Read<Resource>() {
+                                        public Resource perform(ReadGraph graph) throws DatabaseException {
+                                            SerialisationSupport ss = graph.getService(SerialisationSupport.class);
+                                            return ss.getResource(((NumericNode)resourceId).longValue());
+                                        }
+                                    }));
+                                    handleDrop(dtde, obj);
+                                    return;
+                                }
+                            }
+                        }
                         dtde.rejectDrop();
                     }
                         dtde.rejectDrop();
                     }
-                } catch( IOException exception ) {
-                    exception.printStackTrace();
-                    dtde.rejectDrop();
-                } catch( UnsupportedFlavorException ufException ) {
-                    ufException.printStackTrace();
+                } catch( Exception exception ) {
+                    LOGGER.warn("Drop failed.", exception);
                     dtde.rejectDrop();
                     dtde.rejectDrop();
-                }
+                } 
             }     
         });
     }    
     
             }     
         });
     }    
     
+    private void handleDrop(DropTargetDropEvent dtde, Object obj) {
+        double x = canvasPosX+dtde.getLocation().getX()/canvasZoom;
+        double y = canvasPosY+dtde.getLocation().getY()/canvasZoom;
+        handleDrop(x, y, obj);
+        
+        dtde.getDropTargetContext().dropComplete( true );
+    }
+    
     public void keyPressed(KeyEvent e) {
         switch(e.getKeyCode()) {
         case KeyEvent.VK_1:
     public void keyPressed(KeyEvent e) {
         switch(e.getKeyCode()) {
         case KeyEvent.VK_1:
@@ -261,6 +304,8 @@ public class DebuggerCanvas extends JPanel {
             if(resource != null)
                 return resource;
         }
             if(resource != null)
                 return resource;
         }
+        if(obj instanceof Resource)
+            return (Resource)obj;
         return null;
     }
     
         return null;
     }
     
@@ -284,6 +329,29 @@ public class DebuggerCanvas extends JPanel {
         nodes.add(a);
         return a;
     }
         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() {            
 
     private void scheduleUpdate() {
         Simantics.getSession().asyncRequest(new ReadRequest() {            
@@ -462,29 +530,41 @@ public class DebuggerCanvas extends JPanel {
             Simantics.getSession().syncRequest(new ReadRequest() {
                 @Override
                 public void run(ReadGraph graph) throws DatabaseException {
             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) {
                                 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();
                     }
                     DebuggerCanvas.this.extensionNodeMap = extensionNodeMap;
                     layoutExtension();