]> gerrit.simantics Code Review - simantics/district.git/blob - org.simantics.district.network.ui/src/org/simantics/district/network/ui/nodes/NetworkDrawingNode.java
Enhancements to district functionalities and code
[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 scale = 100000;
167 //        double scale = 1;
168         double startLat = ModelledCRS.yToLatitude(start.getY() / scale);
169         double startLon = ModelledCRS.xToLongitude(start.getX() / scale);
170         
171         double endLat = ModelledCRS.yToLatitude(end.getY() / scale);
172         double endLon = ModelledCRS.xToLongitude(end.getX() / scale);
173         
174         double[] startCoords = new double[] { startLon, startLat };
175         double[] endCoords = new double[] { endLon, endLat };
176         
177         DNEdgeBuilder builder = new DNEdgeBuilder(diagramResource, diagram);
178         Simantics.getSession().asyncRequest(new WriteRequest() {
179             
180             @Override
181             public void perform(WriteGraph graph) throws DatabaseException {
182                 builder.create(graph, startCoords, endCoords, padding / scale);
183             }
184         });
185         
186     }
187
188     @Override
189     protected boolean mouseClicked(MouseClickEvent e) {
190         // check ToolMode
191         IToolMode mode = getToolMode();
192         if (mode == Hints.CONNECTTOOL || e.hasAnyModifier(MouseEvent.ALT_MASK | MouseEvent.ALT_GRAPH_MASK)) {
193             if (committed) {
194                 committed = false;
195                 return false;
196             }
197             if (e.button == MouseEvent.RIGHT_BUTTON && !nodes.isEmpty()) {
198                 nodes.remove(nodes.size() - 1);
199             } else if (e.button == MouseEvent.LEFT_BUTTON) {
200                 Point2D localPos = NodeUtil.worldToLocal(this, e.controlPosition, new Point2D.Double());
201                 nodes.add(new Point2D.Double(localPos.getX(), localPos.getY()));
202             }
203             repaint();
204             return true;
205         }
206         return super.mouseClicked(e);
207     }
208     
209     private IToolMode getToolMode() {
210         return participant.getHint(Hints.KEY_TOOL);
211     }
212
213     @Override
214     protected boolean mouseMoved(MouseMovedEvent e) {
215         IToolMode mode = getToolMode();
216         if (mode == Hints.CONNECTTOOL || e.hasAnyModifier(MouseEvent.ALT_MASK | MouseEvent.ALT_GRAPH_MASK)) {
217             boolean repaint = false;
218             Point2D p = NodeUtil.worldToLocal(this, e.controlPosition, new Point2D.Double());
219             if (participant.pickHoveredElement(p)) {
220                 repaint = true;
221             }
222             if (!nodes.isEmpty()) {
223                 currentMousePos = p;
224                 
225                 repaint();
226                 return true;
227             }
228             currentMousePos = null;
229             if (repaint == true)
230                 repaint();
231         }
232         return super.mouseMoved(e);
233     }
234     
235     @Override
236     protected boolean keyPressed(KeyPressedEvent e) {
237         if (e.keyCode == java.awt.event.KeyEvent.VK_ESCAPE) {
238             nodes.clear();
239             repaint();
240             return true;
241         }
242         return super.keyPressed(e);
243             
244     }
245 }