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.datatransfer.DataFlavor;
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.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 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.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.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.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.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>();
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;
public void drop(DropTargetDropEvent dtde) {
try {
Transferable transferable = dtde.getTransferable();
-
if( transferable.isDataFlavorSupported(
LocalObjectTransferable.FLAVOR ) ) {
dtde.acceptDrop( DnDConstants.ACTION_MOVE );
- transferable.getTransferData(LocalObjectTransferable.FLAVOR );
+ transferable.getTransferData(LocalObjectTransferable.FLAVOR);
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 {
+ 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();
}
- } catch( IOException exception ) {
- exception.printStackTrace();
- dtde.rejectDrop();
- } catch( UnsupportedFlavorException ufException ) {
- ufException.printStackTrace();
+ } catch( Exception exception ) {
+ LOGGER.warn("Drop failed.", exception);
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:
if(resource != null)
return resource;
}
+ if(obj instanceof Resource)
+ return (Resource)obj;
return null;
}
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();