-package org.simantics.district.network.ui.nodes;\r
-\r
-import java.awt.Color;\r
-import java.awt.Graphics2D;\r
-import java.awt.geom.Path2D;\r
-import java.awt.geom.Point2D;\r
-import java.awt.geom.Rectangle2D;\r
-import java.util.ArrayList;\r
-import java.util.HashSet;\r
-import java.util.Iterator;\r
-import java.util.List;\r
-import java.util.Set;\r
-\r
-import org.simantics.Simantics;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.common.request.WriteRequest;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.diagram.ui.DiagramModelHints;\r
-import org.simantics.district.network.ui.DNEdgeBuilder;\r
-import org.simantics.district.network.ui.NetworkDrawingParticipant;\r
-import org.simantics.g2d.canvas.Hints;\r
-import org.simantics.g2d.canvas.IToolMode;\r
-import org.simantics.g2d.diagram.IDiagram;\r
-import org.simantics.scenegraph.g2d.G2DNode;\r
-import org.simantics.scenegraph.g2d.events.EventTypes;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDoubleClickedEvent;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;\r
-import org.simantics.scenegraph.utils.NodeUtil;\r
-\r
-public class NetworkDrawingNode extends G2DNode {\r
-\r
- private static final long serialVersionUID = -3475301184009620573L;\r
- \r
- private List<Point2D> nodes = new ArrayList<>();\r
-\r
- private Rectangle2D rect = new Rectangle2D.Double(10, 10, 10, 10);\r
-\r
- private Set<Path2D> paths = new HashSet<>();\r
-\r
- private Resource diagramResource;\r
-\r
- private boolean committed;\r
-\r
- private NetworkDrawingParticipant participant;\r
-\r
- private IDiagram diagram;\r
- \r
- @Override\r
- public void init() {\r
- super.init();\r
- addEventHandler(this);\r
- }\r
- \r
- public void setNetworkDrawingParticipant(NetworkDrawingParticipant participant) {\r
- this.participant = participant;\r
- }\r
- \r
- public void setDiagram(IDiagram diagram) {\r
- if (diagram != null) {\r
- this.diagram = diagram;\r
- this.diagramResource = diagram.getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE);\r
- }\r
- }\r
-\r
- @Override\r
- public void render(Graphics2D g2d) {\r
- Color old = g2d.getColor();\r
- g2d.setColor(Color.BLUE);\r
- \r
- paths.forEach(p -> {\r
- g2d.draw(p);\r
- });\r
- \r
- g2d.setColor(old);\r
- }\r
-\r
- @Override\r
- public Rectangle2D getBoundsInLocal() {\r
- return rect.getBounds2D();\r
- }\r
- \r
- @Override\r
- public int getEventMask() {\r
- return EventTypes.MouseMask;\r
- }\r
- \r
- @Override\r
- protected boolean mouseDoubleClicked(MouseDoubleClickedEvent e) {\r
- // nodes to path2d\r
- IToolMode mode = getToolMode();\r
- if (mode == Hints.CONNECTTOOL || e.hasAnyModifier(MouseEvent.ALT_MASK | MouseEvent.ALT_GRAPH_MASK)) {\r
- Point2D start = null;\r
- Point2D end = null;\r
- Iterator<Point2D> nodeIter = nodes.iterator();\r
- while (nodeIter.hasNext()) {\r
- if (end == null) {\r
- start = nodeIter.next();\r
- } else {\r
- start = end;\r
- }\r
- end = nodeIter.next();\r
- \r
- createEdge(start, end);\r
- }\r
- \r
- nodes.clear();\r
- committed = true;\r
- \r
- repaint();\r
- \r
- return true;\r
- }\r
- return super.mouseDoubleClicked(e);\r
- }\r
- \r
- private void createEdge(Point2D start, Point2D end) {\r
- double[] startCoords = new double[] { start.getX(), start.getY() };\r
- double[] endCoords = new double[] { end.getX(), end.getY() };\r
- \r
- DNEdgeBuilder builder = new DNEdgeBuilder(diagramResource, diagram);\r
- Simantics.getSession().asyncRequest(new WriteRequest() {\r
- \r
- @Override\r
- public void perform(WriteGraph graph) throws DatabaseException {\r
- builder.create(graph, startCoords, endCoords);\r
- }\r
- });\r
- \r
- }\r
- \r
- @Override\r
- protected boolean mouseClicked(MouseClickEvent e) {\r
- // check ToolMode\r
- IToolMode mode = getToolMode();\r
- if (mode == Hints.CONNECTTOOL || e.hasAnyModifier(MouseEvent.ALT_MASK | MouseEvent.ALT_GRAPH_MASK)) {\r
- if (committed) {\r
- committed = false;\r
- return false;\r
- }\r
- Point2D localPos = NodeUtil.worldToLocal(this, e.controlPosition, new Point2D.Double());\r
- nodes.add(new Point2D.Double(localPos.getX(), localPos.getY()));\r
- }\r
- return super.mouseClicked(e);\r
- }\r
- \r
- private IToolMode getToolMode() {\r
- return participant.getHint(Hints.KEY_TOOL);\r
- }\r
-\r
- @Override\r
- protected boolean mouseMoved(MouseMovedEvent e) {\r
- return super.mouseMoved(e);\r
- }\r
+package org.simantics.district.network.ui.nodes;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Stroke;
+import java.awt.geom.Path2D;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.simantics.Simantics;
+import org.simantics.db.Resource;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.diagram.ui.DiagramModelHints;
+import org.simantics.district.network.ModelledCRS;
+import org.simantics.district.network.ui.DNEdgeBuilder;
+import org.simantics.district.network.ui.NetworkDrawingParticipant;
+import org.simantics.g2d.canvas.Hints;
+import org.simantics.g2d.canvas.IToolMode;
+import org.simantics.g2d.diagram.IDiagram;
+import org.simantics.scenegraph.g2d.G2DNode;
+import org.simantics.scenegraph.g2d.events.EventTypes;
+import org.simantics.scenegraph.g2d.events.KeyEvent.KeyPressedEvent;
+import org.simantics.scenegraph.g2d.events.MouseEvent;
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent;
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDoubleClickedEvent;
+import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;
+import org.simantics.scenegraph.utils.GeometryUtils;
+import org.simantics.scenegraph.utils.NodeUtil;
+
+public class NetworkDrawingNode extends G2DNode {
+
+ private static final long serialVersionUID = -3475301184009620573L;
+
+ private Point2D currentMousePos = null;
+
+ private List<Point2D> nodes = new ArrayList<>();
+
+ private Resource diagramResource;
+
+ private boolean committed;
+
+ private NetworkDrawingParticipant participant;
+
+ private IDiagram diagram;
+
+ private static final Stroke DASHED_STROKE = new BasicStroke(2.0f,
+ BasicStroke.CAP_ROUND,
+ BasicStroke.JOIN_ROUND,
+ 4.0f, new float[]{4.0f}, 0.0f);
+
+ private static final Color BLUE_ALPHA = new Color(0, 0, 255, 100);
+
+ private boolean scaleStroke = true;
+
+ @Override
+ public void init() {
+ super.init();
+ addEventHandler(this);
+ }
+
+ public void setNetworkDrawingParticipant(NetworkDrawingParticipant participant) {
+ this.participant = participant;
+ }
+
+ public void setDiagram(IDiagram diagram) {
+ if (diagram != null) {
+ this.diagram = diagram;
+ this.diagramResource = diagram.getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE);
+ }
+ }
+
+ @Override
+ public void render(Graphics2D g2d) {
+ if (nodes.isEmpty())
+ return;
+
+ Path2D path = new Path2D.Double();
+ Iterator<Point2D> nodeIter = nodes.iterator();
+ if (nodeIter.hasNext()) {
+ Point2D node = nodeIter.next();
+ path.moveTo(node.getX(), node.getY());
+ }
+ while (nodeIter.hasNext()) {
+ Point2D node = nodeIter.next();
+ path.lineTo(node.getX(), node.getY());
+ }
+ if (currentMousePos != null)
+ path.lineTo(currentMousePos.getX(), currentMousePos.getY());
+
+ Color old = g2d.getColor();
+ Stroke oldStroke = g2d.getStroke();
+
+ if (DASHED_STROKE != null) {
+ if (scaleStroke && DASHED_STROKE instanceof BasicStroke) {
+ BasicStroke bs = GeometryUtils.scaleStroke(DASHED_STROKE, (float) (1.0 / GeometryUtils.getScale(g2d.getTransform())));
+ g2d.setStroke(bs);
+ } else {
+ g2d.setStroke(DASHED_STROKE);
+ }
+ }
+
+ g2d.setColor(BLUE_ALPHA);
+
+ g2d.draw(path);
+
+ g2d.setStroke(oldStroke);
+ g2d.setColor(old);
+ }
+
+ @Override
+ public Rectangle2D getBoundsInLocal() {
+ return null;
+ }
+
+ @Override
+ public int getEventMask() {
+ return EventTypes.AnyMask;
+ }
+
+ @Override
+ protected boolean mouseDoubleClicked(MouseDoubleClickedEvent e) {
+ // nodes to path2d
+ IToolMode mode = getToolMode();
+ if (mode == Hints.CONNECTTOOL || e.hasAnyModifier(MouseEvent.ALT_MASK | MouseEvent.ALT_GRAPH_MASK)) {
+ Point2D start = null;
+ Point2D end = null;
+ Iterator<Point2D> nodeIter = nodes.iterator();
+ while (nodeIter.hasNext()) {
+ if (end == null) {
+ start = nodeIter.next();
+ } else {
+ start = end;
+ }
+ end = nodeIter.next();
+
+ createEdge(start, end);
+ }
+
+ nodes.clear();
+ committed = true;
+
+ repaint();
+
+ return true;
+ }
+ return super.mouseDoubleClicked(e);
+ }
+
+ private void createEdge(Point2D start, Point2D end) {
+
+ double padding = GeometryUtils.getScale(getTransform());
+
+ /*
+ * To convert y-coordinates to map coordinates in ruler, use:
+ * double val = (y-offsetY)/scaleY;
+ * val = Math.toDegrees(Math.atan(Math.sinh(Math.toRadians(val))));
+ * String str = formatValue(val);
+ */
+ // TODO: fix scale
+ double scale = 100000;
+ double startLat = ModelledCRS.yToLatitude(start.getY() / scale);
+ double startLon = ModelledCRS.xToLongitude(start.getX() / scale);
+
+ double endLat = ModelledCRS.yToLatitude(end.getY() / scale);
+ double endLon = ModelledCRS.xToLongitude(end.getX() / scale);
+
+ double[] startCoords = new double[] { startLon, startLat };
+ double[] endCoords = new double[] { endLon, endLat };
+
+ DNEdgeBuilder builder = new DNEdgeBuilder(diagramResource, diagram);
+ Simantics.getSession().asyncRequest(new WriteRequest() {
+
+ @Override
+ public void perform(WriteGraph graph) throws DatabaseException {
+ builder.create(graph, startCoords, endCoords, padding / scale);
+ }
+ });
+
+ }
+
+ @Override
+ protected boolean mouseClicked(MouseClickEvent e) {
+ // check ToolMode
+ IToolMode mode = getToolMode();
+ if (mode == Hints.CONNECTTOOL || e.hasAnyModifier(MouseEvent.ALT_MASK | MouseEvent.ALT_GRAPH_MASK)) {
+ if (committed) {
+ committed = false;
+ return false;
+ }
+ if (e.button == MouseEvent.RIGHT_BUTTON && !nodes.isEmpty()) {
+ nodes.remove(nodes.size() - 1);
+ } else if (e.button == MouseEvent.LEFT_BUTTON) {
+ Point2D localPos = NodeUtil.worldToLocal(this, e.controlPosition, new Point2D.Double());
+ nodes.add(new Point2D.Double(localPos.getX(), localPos.getY()));
+ }
+ repaint();
+ return true;
+ }
+ return super.mouseClicked(e);
+ }
+
+ private IToolMode getToolMode() {
+ return participant.getHint(Hints.KEY_TOOL);
+ }
+
+ @Override
+ protected boolean mouseMoved(MouseMovedEvent e) {
+ IToolMode mode = getToolMode();
+ if (mode == Hints.CONNECTTOOL || e.hasAnyModifier(MouseEvent.ALT_MASK | MouseEvent.ALT_GRAPH_MASK)) {
+ boolean repaint = false;
+ Point2D p = NodeUtil.worldToLocal(this, e.controlPosition, new Point2D.Double());
+ if (participant.pickHoveredElement(p)) {
+ repaint = true;
+ }
+ if (!nodes.isEmpty()) {
+ currentMousePos = p;
+
+ repaint();
+ return true;
+ }
+ currentMousePos = null;
+ if (repaint == true)
+ repaint();
+ }
+ return super.mouseMoved(e);
+ }
+
+ @Override
+ protected boolean keyPressed(KeyPressedEvent e) {
+ if (e.keyCode == java.awt.event.KeyEvent.VK_ESCAPE) {
+ nodes.clear();
+ repaint();
+ return true;
+ }
+ return super.keyPressed(e);
+
+ }