1 package org.simantics.district.network.ui.adapters;
5 import java.awt.geom.AffineTransform;
6 import java.awt.geom.Rectangle2D;
8 import org.simantics.diagram.elements.DiagramNodeUtil;
9 import org.simantics.district.network.ui.nodes.DistrictNetworkVertexNode;
10 import org.simantics.g2d.canvas.Hints;
11 import org.simantics.g2d.canvas.ICanvasContext;
12 import org.simantics.g2d.diagram.handler.PickRequest.PickPolicy;
13 import org.simantics.g2d.element.ElementClass;
14 import org.simantics.g2d.element.ElementUtils;
15 import org.simantics.g2d.element.IElement;
16 import org.simantics.g2d.element.SceneGraphNodeKey;
17 import org.simantics.g2d.element.handler.InternalSize;
18 import org.simantics.g2d.element.handler.Pick;
19 import org.simantics.g2d.element.handler.SceneGraph;
20 import org.simantics.g2d.element.handler.impl.DefaultTransform;
21 import org.simantics.g2d.element.handler.impl.SimpleElementLayers;
22 import org.simantics.scenegraph.INode;
23 import org.simantics.scenegraph.g2d.G2DParentNode;
24 import org.simantics.scenegraph.g2d.nodes.SVGNode;
25 import org.simantics.scenegraph.utils.GeometryUtils;
26 import org.simantics.utils.datastructures.hints.IHintContext.Key;
27 import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
29 public class DistrictNetworkVertexElement {
31 public static final Key KEY_DN_VERTEX = new KeyOf(DistrictNetworkVertex.class, "DN_VERTEX");
32 public static final Key KEY_DN_VERTEX_NODE = new SceneGraphNodeKey(DistrictNetworkVertexNode.class, "DN_VERTEX_NODE");
33 public static final Key KEY_DN_VERTEX_SYMBOL_NODE = new SceneGraphNodeKey(SVGNode.class, "DN_VERTEX_SYMBOL_NODE");
35 public static final ElementClass CLASS =
37 DefaultTransform.INSTANCE,
38 DNVertexInternalSize.INSTANCE,
39 DNVertexSceneGraph.INSTANCE,
40 SimpleElementLayers.INSTANCE,
41 DistrictNetworkAdditionalColor.INSTANCE
42 ).setId(DistrictNetworkVertexElement.class.getSimpleName());
44 static final class DNVertexSceneGraph implements SceneGraph {
46 public static final DNVertexSceneGraph INSTANCE = new DNVertexSceneGraph();
48 private static final long serialVersionUID = 8894367073815556871L;
51 public void init(IElement vertexElement, G2DParentNode parent) {
52 DistrictNetworkVertex vertex = vertexElement.getHint(KEY_DN_VERTEX);
54 cleanup(vertexElement);
56 DistrictNetworkVertexNode node = vertexElement.getHint(KEY_DN_VERTEX_NODE);
58 node = parent.addNode(ElementUtils.generateNodeId(vertexElement), DistrictNetworkVertexNode.class);
59 vertexElement.setHint(KEY_DN_VERTEX_NODE, node);
61 SVGNode symbol = node.addNode(ElementUtils.generateNodeId(vertexElement), SVGNode.class);
62 vertexElement.setHint(KEY_DN_VERTEX_SYMBOL_NODE, symbol);
65 node.setVertex(vertex);
67 node.setColor(ElementUtils.getAdditionalColor(vertexElement, Color.BLUE));
69 AffineTransform at = ElementUtils.getTransform(vertexElement);
71 node.setTransform(at);
76 public void cleanup(IElement edge) {
77 ElementUtils.removePossibleNode(edge, KEY_DN_VERTEX_SYMBOL_NODE);
78 INode node = ElementUtils.removePossibleNode(edge, KEY_DN_VERTEX_NODE);
80 node.getParent().remove();
82 edge.removeHint(KEY_DN_VERTEX_NODE);
83 edge.removeHint(KEY_DN_VERTEX_SYMBOL_NODE);
87 static final class DNVertexInternalSize implements InternalSize, Pick {
89 public static final DNVertexInternalSize INSTANCE = new DNVertexInternalSize();
91 private static final long serialVersionUID = 2625702114278956461L;
94 public Rectangle2D getBounds(IElement e, Rectangle2D size) {
95 DistrictNetworkVertexNode node = e.getHint(KEY_DN_VERTEX_NODE);
96 Rectangle2D boundsInLocal = node.getBoundsInLocal();
97 ICanvasContext ctx = DiagramNodeUtil.getCanvasContext(node);
98 AffineTransform canvasTransform = ctx.getHintStack().getHint(Hints.KEY_CANVAS_TRANSFORM);
99 // for some reason PickContextImpl expands the rectangle by 0.001 (too much) - let's counter it
100 double counterExpansion = 0.001;
101 double x = boundsInLocal.getX() + counterExpansion;
102 double y = boundsInLocal.getY() + counterExpansion;
103 double scaledWidth = boundsInLocal.getWidth();
104 double scaledHeight = boundsInLocal.getHeight();
105 if (canvasTransform != null) {
106 scaledWidth = boundsInLocal.getWidth() / canvasTransform.getScaleX() / 10000.0;
107 scaledHeight= boundsInLocal.getHeight() / canvasTransform.getScaleY() / 10000.0;
109 double width = scaledWidth - 2*counterExpansion;
110 double height = scaledHeight - 2*counterExpansion;
111 size.setFrame(x, y, width, height);
117 public boolean pickTest(IElement e, Shape s, PickPolicy policy) {
118 DistrictNetworkVertexNode node = e.getHint(KEY_DN_VERTEX_NODE);
119 Rectangle2D boundsInLocal = node.getBounds();
120 ICanvasContext ctx = DiagramNodeUtil.getCanvasContext(node);
121 AffineTransform canvasTransform = ctx.getHintStack().getHint(Hints.KEY_CANVAS_TRANSFORM);
122 Rectangle2D scaledBounds = new Rectangle2D.Double(boundsInLocal.getX(), boundsInLocal.getY(), boundsInLocal.getWidth() / canvasTransform.getScaleX() * 2, boundsInLocal.getHeight() / canvasTransform.getScaleY() * 2);
123 Rectangle2D bounds = getBounds(s);
125 case PICK_CONTAINED_OBJECTS:
126 return org.simantics.g2d.utils.GeometryUtils.contains(bounds, boundsInLocal);
127 case PICK_INTERSECTING_OBJECTS:
128 return org.simantics.g2d.utils.GeometryUtils.intersects(boundsInLocal, bounds);
133 private Rectangle2D getBounds(Shape shape) {
134 if (shape instanceof Rectangle2D)
135 return (Rectangle2D) shape;
136 return shape.getBounds2D();