]> gerrit.simantics Code Review - simantics/district.git/blob
b3e7fda3b822401b2d525d51ef7f0c1c0bb70e38
[simantics/district.git] /
1 package org.simantics.district.network.ui.adapters;
2
3 import java.awt.Color;
4 import java.awt.Shape;
5 import java.awt.geom.AffineTransform;
6 import java.awt.geom.Rectangle2D;
7
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;
28
29 public class DistrictNetworkVertexElement {
30
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");
34     
35     public static final ElementClass CLASS =
36             ElementClass.compile(
37                     DefaultTransform.INSTANCE,
38                     DNVertexInternalSize.INSTANCE,
39                     DNVertexSceneGraph.INSTANCE,
40                     SimpleElementLayers.INSTANCE,
41                     DistrictNetworkAdditionalColor.INSTANCE
42             ).setId(DistrictNetworkVertexElement.class.getSimpleName());
43     
44     static final class DNVertexSceneGraph implements SceneGraph {
45         
46         public static final DNVertexSceneGraph INSTANCE = new DNVertexSceneGraph();
47
48         private static final long serialVersionUID = 8894367073815556871L;
49
50         @Override
51         public void init(IElement vertexElement, G2DParentNode parent) {
52             DistrictNetworkVertex vertex = vertexElement.getHint(KEY_DN_VERTEX);
53             if (vertex == null) {
54                 cleanup(vertexElement);
55             } else {
56                 DistrictNetworkVertexNode node = vertexElement.getHint(KEY_DN_VERTEX_NODE);
57                 if (node == null) {
58                     node = parent.addNode(ElementUtils.generateNodeId(vertexElement), DistrictNetworkVertexNode.class);
59                     vertexElement.setHint(KEY_DN_VERTEX_NODE, node);
60                     
61                     SVGNode symbol = node.addNode(ElementUtils.generateNodeId(vertexElement), SVGNode.class);
62                     vertexElement.setHint(KEY_DN_VERTEX_SYMBOL_NODE, symbol);
63                 }
64                 
65                 node.setVertex(vertex);
66                 
67                 node.setColor(ElementUtils.getAdditionalColor(vertexElement, Color.BLUE));
68                 
69                 AffineTransform at = ElementUtils.getTransform(vertexElement);
70                 if(at != null)
71                     node.setTransform(at);
72             }
73         }
74
75         @Override
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);
79             if (node != null)
80                 node.getParent().remove();
81             
82             edge.removeHint(KEY_DN_VERTEX_NODE);
83             edge.removeHint(KEY_DN_VERTEX_SYMBOL_NODE);
84         }
85     }
86     
87     static final class DNVertexInternalSize implements InternalSize, Pick {
88
89         public static final DNVertexInternalSize INSTANCE = new DNVertexInternalSize();
90         
91         private static final long serialVersionUID = 2625702114278956461L;
92
93         @Override
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() / canvasTransform.getScaleX() / 10000.0;
104             double scaledHeight = boundsInLocal.getHeight() / canvasTransform.getScaleY() / 10000.0;
105             double width = scaledWidth - 2*counterExpansion;
106             double height = scaledHeight - 2*counterExpansion;
107             size.setFrame(x, y, width, height);
108             
109             return size;
110         }
111
112         @Override
113         public boolean pickTest(IElement e, Shape s, PickPolicy policy) {
114             DistrictNetworkVertexNode node = e.getHint(KEY_DN_VERTEX_NODE);
115             Rectangle2D boundsInLocal = node.getBounds();
116             ICanvasContext ctx = DiagramNodeUtil.getCanvasContext(node);
117             AffineTransform canvasTransform = ctx.getHintStack().getHint(Hints.KEY_CANVAS_TRANSFORM);
118             Rectangle2D scaledBounds = new Rectangle2D.Double(boundsInLocal.getX(), boundsInLocal.getY(), boundsInLocal.getWidth() / canvasTransform.getScaleX() * 2, boundsInLocal.getHeight() / canvasTransform.getScaleY() * 2);
119             Rectangle2D bounds = getBounds(s);
120             switch (policy) {
121             case PICK_CONTAINED_OBJECTS:
122                 return org.simantics.g2d.utils.GeometryUtils.contains(bounds, boundsInLocal);
123             case PICK_INTERSECTING_OBJECTS:
124                 return org.simantics.g2d.utils.GeometryUtils.intersects(boundsInLocal, bounds);
125             }
126             return false;
127         }
128         
129         private Rectangle2D getBounds(Shape shape) {
130             if (shape instanceof Rectangle2D)
131                 return (Rectangle2D) shape;
132             return shape.getBounds2D();
133         }
134     }
135 }