]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/NetworkDrawingNode.java
1ccde2c7b18db0c459648af546428b57c3205428
[simantics/district.git] / org.simantics.district.network.ui / src / org / simantics / district / network / ui / nodes / NetworkDrawingNode.java
1 package org.simantics.district.network.ui.nodes;
2
3 import java.awt.BasicStroke;
4 import java.awt.Color;
5 import java.awt.Graphics2D;
6 import java.awt.Stroke;
7 import java.awt.geom.Path2D;
8 import java.awt.geom.Point2D;
9 import java.awt.geom.Rectangle2D;
10 import java.util.ArrayList;
11 import java.util.Iterator;
12 import java.util.List;
13
14 import org.simantics.Simantics;
15 import org.simantics.db.Resource;
16 import org.simantics.db.WriteGraph;
17 import org.simantics.db.common.request.WriteRequest;
18 import org.simantics.db.exception.DatabaseException;
19 import org.simantics.diagram.ui.DiagramModelHints;
20 import org.simantics.district.network.ModelledCRS;
21 import org.simantics.district.network.ui.DNEdgeBuilder;
22 import org.simantics.district.network.ui.NetworkDrawingParticipant;
23 import org.simantics.g2d.canvas.Hints;
24 import org.simantics.g2d.canvas.IToolMode;
25 import org.simantics.g2d.diagram.IDiagram;
26 import org.simantics.scenegraph.g2d.G2DNode;
27 import org.simantics.scenegraph.g2d.events.EventTypes;
28 import org.simantics.scenegraph.g2d.events.KeyEvent.KeyPressedEvent;
29 import org.simantics.scenegraph.g2d.events.MouseEvent;
30 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent;
31 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDoubleClickedEvent;
32 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;
33 import org.simantics.scenegraph.utils.GeometryUtils;
34 import org.simantics.scenegraph.utils.NodeUtil;
35
36 public class NetworkDrawingNode extends G2DNode {
37
38     private static final long serialVersionUID = -3475301184009620573L;
39     
40     private Point2D currentMousePos = null;
41     
42     private List<Point2D> nodes = new ArrayList<>();
43
44     private Resource diagramResource;
45
46     private boolean committed;
47
48     private NetworkDrawingParticipant participant;
49
50     private IDiagram diagram;
51
52     private static final Stroke DASHED_STROKE = new BasicStroke(2.0f,
53             BasicStroke.CAP_ROUND,
54             BasicStroke.JOIN_ROUND,
55             4.0f, new float[]{4.0f}, 0.0f);
56
57     private static final Color BLUE_ALPHA = new Color(0, 0, 255, 100);
58
59     private boolean scaleStroke = true;
60     
61     @Override
62     public void init() {
63         super.init();
64         addEventHandler(this);
65     }
66     
67     public void setNetworkDrawingParticipant(NetworkDrawingParticipant participant) {
68         this.participant = participant;
69     }
70     
71     public void setDiagram(IDiagram diagram) {
72         if (diagram != null) {
73             this.diagram = diagram;
74             this.diagramResource = diagram.getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE);
75         }
76     }
77
78     @Override
79     public void render(Graphics2D g2d) {
80         if (nodes.isEmpty())
81             return;
82         
83         Path2D path = new Path2D.Double();
84         Iterator<Point2D> nodeIter = nodes.iterator();
85         if (nodeIter.hasNext()) {
86             Point2D node = nodeIter.next();
87             path.moveTo(node.getX(), node.getY());
88         }
89         while (nodeIter.hasNext()) {
90             Point2D node = nodeIter.next();
91             path.lineTo(node.getX(), node.getY());
92         }
93         if (currentMousePos != null)
94             path.lineTo(currentMousePos.getX(), currentMousePos.getY());
95         
96         Color old = g2d.getColor();
97         Stroke oldStroke = g2d.getStroke();
98         
99         if (DASHED_STROKE != null) {
100             if (scaleStroke && DASHED_STROKE instanceof BasicStroke) {
101                 BasicStroke bs = GeometryUtils.scaleStroke(DASHED_STROKE, (float) (1.0 / GeometryUtils.getScale(g2d.getTransform())));
102                 g2d.setStroke(bs);
103             } else {
104                 g2d.setStroke(DASHED_STROKE);
105             }
106         }
107         
108         g2d.setColor(BLUE_ALPHA);
109
110         g2d.draw(path);
111         
112         g2d.setStroke(oldStroke);
113         g2d.setColor(old);
114     }
115
116     @Override
117     public Rectangle2D getBoundsInLocal() {
118         return null;
119     }
120     
121     @Override
122     public int getEventMask() {
123         return EventTypes.AnyMask;
124     }
125     
126     @Override
127     protected boolean mouseDoubleClicked(MouseDoubleClickedEvent e) {
128         // nodes to path2d
129         IToolMode mode = getToolMode();
130         if (mode == Hints.CONNECTTOOL || e.hasAnyModifier(MouseEvent.ALT_MASK | MouseEvent.ALT_GRAPH_MASK)) {
131             Point2D start = null;
132             Point2D end = null;
133             Iterator<Point2D> nodeIter = nodes.iterator();
134             while (nodeIter.hasNext()) {
135                 if (end == null) {
136                     start = nodeIter.next();
137                 } else {
138                     start = end;
139                 }
140                 end = nodeIter.next();
141                 
142                 createEdge(start, end);
143             }
144             
145             nodes.clear();
146             committed = true;
147             
148             repaint();
149             
150             return true;
151         }
152         return super.mouseDoubleClicked(e);
153     }
154
155     private void createEdge(Point2D start, Point2D end) {
156         
157         double padding = GeometryUtils.getScale(getTransform());
158         
159         /*
160          *  To convert y-coordinates to map coordinates in ruler, use:
161          *    double val = (y-offsetY)/scaleY;
162          *    val = Math.toDegrees(Math.atan(Math.sinh(Math.toRadians(val))));
163          *    String str = formatValue(val);
164          */
165         // TODO: fix scale
166         double scaleY = getTransform().getScaleY();
167         double scaleX = getTransform().getScaleX();
168         
169         double startLat = ModelledCRS.yToLatitude(start.getY() / scaleY);
170         double startLon = ModelledCRS.xToLongitude(start.getX() / scaleX);
171         
172         double endLat = ModelledCRS.yToLatitude(end.getY() / scaleY);
173         double endLon = ModelledCRS.xToLongitude(end.getX() / scaleX);
174         
175         double[] startCoords = new double[] { startLon, startLat };
176         double[] endCoords = new double[] { endLon, endLat };
177         
178         DNEdgeBuilder builder = new DNEdgeBuilder(diagramResource, diagram);
179         Simantics.getSession().asyncRequest(new WriteRequest() {
180             
181             @Override
182             public void perform(WriteGraph graph) throws DatabaseException {
183                 builder.create(graph, startCoords, endCoords, 1 / padding);
184             }
185         });
186         
187     }
188
189     @Override
190     protected boolean mouseClicked(MouseClickEvent e) {
191         // check ToolMode
192         IToolMode mode = getToolMode();
193         if (mode == Hints.CONNECTTOOL || e.hasAnyModifier(MouseEvent.ALT_MASK | MouseEvent.ALT_GRAPH_MASK)) {
194             if (committed) {
195                 committed = false;
196                 return false;
197             }
198             if (e.button == MouseEvent.RIGHT_BUTTON && !nodes.isEmpty()) {
199                 nodes.remove(nodes.size() - 1);
200             } else if (e.button == MouseEvent.LEFT_BUTTON) {
201                 Point2D localPos = NodeUtil.worldToLocal(this, e.controlPosition, new Point2D.Double());
202                 nodes.add(new Point2D.Double(localPos.getX(), localPos.getY()));
203             }
204             repaint();
205             return true;
206         }
207         return super.mouseClicked(e);
208     }
209     
210     private IToolMode getToolMode() {
211         return participant.getHint(Hints.KEY_TOOL);
212     }
213
214     @Override
215     protected boolean mouseMoved(MouseMovedEvent e) {
216         IToolMode mode = getToolMode();
217         if (mode == Hints.CONNECTTOOL || e.hasAnyModifier(MouseEvent.ALT_MASK | MouseEvent.ALT_GRAPH_MASK)) {
218             boolean repaint = false;
219             Point2D p = NodeUtil.worldToLocal(this, e.controlPosition, new Point2D.Double());
220             if (participant.pickHoveredElement(p)) {
221                 repaint = true;
222             }
223             if (!nodes.isEmpty()) {
224                 currentMousePos = p;
225                 
226                 repaint();
227                 return true;
228             }
229             currentMousePos = null;
230             if (repaint == true)
231                 repaint();
232         }
233         return super.mouseMoved(e);
234     }
235     
236     @Override
237     protected boolean keyPressed(KeyPressedEvent e) {
238         if (e.keyCode == java.awt.event.KeyEvent.VK_ESCAPE) {
239             nodes.clear();
240             repaint();
241             return true;
242         }
243         return super.keyPressed(e);
244             
245     }
246 }