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