]> gerrit.simantics Code Review - simantics/district.git/blobdiff - org.simantics.district.network.ui/src/org/simantics/district/network/ui/NetworkDrawingParticipant.java
Expose transform of NetworkDrawingParticipant
[simantics/district.git] / org.simantics.district.network.ui / src / org / simantics / district / network / ui / NetworkDrawingParticipant.java
index a8cd239b3d520edea52266c045979aa98d624a3d..73abf31e575bb7f03047793df0f272146ba67c01 100644 (file)
-\r
-package org.simantics.district.network.ui;\r
-\r
-import java.awt.Color;\r
-import java.awt.Graphics2D;\r
-import java.awt.Shape;\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.Collections;\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.g2d.canvas.impl.DependencyReflection.Dependency;\r
-import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;\r
-import org.simantics.g2d.diagram.IDiagram;\r
-import org.simantics.g2d.diagram.handler.PickContext;\r
-import org.simantics.g2d.diagram.handler.PickRequest;\r
-import org.simantics.g2d.diagram.handler.PickRequest.PickPolicy;\r
-import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;\r
-import org.simantics.g2d.diagram.participant.Selection;\r
-import org.simantics.g2d.element.IElement;\r
-import org.simantics.g2d.participant.TransformUtil;\r
-import org.simantics.g2d.utils.GeometryUtils;\r
-import org.simantics.scenegraph.g2d.G2DNode;\r
-import org.simantics.scenegraph.g2d.G2DParentNode;\r
-import org.simantics.scenegraph.g2d.events.EventTypes;\r
-import org.simantics.scenegraph.g2d.events.MouseEvent;\r
-import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;\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
-import org.simantics.utils.datastructures.hints.IHintContext.Key;\r
-import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;\r
-\r
-public class NetworkDrawingParticipant extends AbstractDiagramParticipant {\r
-\r
-    /**\r
-     * A hint key for terminal pick distance in control pixels.\r
-     * @see #PICK_DIST\r
-     */\r
-    public static final Key KEY_PICK_DISTANCE = new KeyOf(Double.class, "PICK_DISTANCE");\r
-\r
-    /**\r
-     * Default terminal pick distance in control pixels.\r
-     * @see #DEFAULT_PICK_DISTANCE\r
-     */\r
-    public static final double PICK_DIST = 10;\r
-    \r
-    private NetworkDrawingNode node;\r
-    \r
-    @Dependency Selection selection;\r
-    @Dependency TransformUtil util;\r
-    @Dependency PickContext pickContext;\r
-    \r
-    @SGInit\r
-    public void initSG(G2DParentNode parent) {\r
-        node = parent.addNode("networkDrawingNode", NetworkDrawingNode.class);\r
-    }\r
-    \r
-    @Override\r
-    protected void onDiagramSet(IDiagram newDiagram, IDiagram oldDiagram) {\r
-        node.setDiagram(newDiagram);\r
-    }\r
-    \r
-    @EventHandler(priority = 1 << 21)\r
-    public boolean handleClick(MouseClickEvent me) {\r
-        \r
-        boolean isLeft = me.button == MouseEvent.LEFT_BUTTON;\r
-        boolean isRight = me.button == MouseEvent.RIGHT_BUTTON;\r
-        if (!isLeft && !isRight)\r
-            return false;\r
-        boolean isShiftPressed = me.hasAllModifiers(MouseEvent.SHIFT_MASK);\r
-        \r
-        int selectionId = me.mouseId;\r
-        \r
-        double pickDist = getPickDistance();\r
-        Rectangle2D controlPickRect = new Rectangle2D.Double(me.controlPosition.getX()-pickDist, me.controlPosition.getY()-pickDist, pickDist*2+1, pickDist*2+1);\r
-        Shape canvasPickRect  = GeometryUtils.transformShape(controlPickRect, util.getInverseTransform());\r
-        \r
-        PickRequest req = new PickRequest(canvasPickRect);\r
-        req.pickPolicy = PickPolicy.PICK_INTERSECTING_OBJECTS;\r
-        //req.pickSorter = PickRequest.PickSorter.CONNECTIONS_LAST;\r
-        List<IElement> pickables = new ArrayList<IElement>();\r
-        pickContext.pick(diagram, req, pickables);\r
-        \r
-        Set<IElement> currentSelection = selection.getSelection(selectionId);\r
-        \r
-        if (!pickables.isEmpty()) {\r
-            /*\r
-             * Select the one object the mouse points to. If multiple object\r
-             * are picked, select the one that is after the earliest by\r
-             * index of the current selection when shift is pressed. Otherwise\r
-             * always pick the topmost element.\r
-             */\r
-            IElement selectedPick = isShiftPressed\r
-                    ? rotatingPick(currentSelection, pickables)\r
-                            : pickables.get(pickables.size() - 1);\r
-    \r
-            // Only select when\r
-            // 1. the selection would actually change\r
-            // AND\r
-            //   2.1. left button was pressed\r
-            //   OR\r
-            //   2.2. right button was pressed and the element to-be-selected\r
-            //        is NOT a part of the current selection\r
-            if (!Collections.singleton(selectedPick).equals(currentSelection)\r
-                    && (isLeft || (isRight && !currentSelection.contains(selectedPick)))) {\r
-                selection.setSelection(selectionId, selectedPick);\r
-            }\r
-        }\r
-        \r
-        return false;\r
-    }\r
-    \r
-    private double getPickDistance() {\r
-        Double pickDistance = getHint(KEY_PICK_DISTANCE);\r
-        return pickDistance == null ? PICK_DIST : Math.max(pickDistance, 0);\r
-    }\r
-    \r
-    private IElement rotatingPick(int selectionId, List<IElement> pickables) {\r
-        Set<IElement> sel = selection.getSelection(selectionId);\r
-        return rotatingPick(sel, pickables);\r
-    }\r
-\r
-    private IElement rotatingPick(Set<IElement> sel, List<IElement> pickables) {\r
-        int earliestIndex = pickables.size();\r
-        for (int i = pickables.size() - 1; i >= 0; --i) {\r
-            if (sel.contains(pickables.get(i))) {\r
-                earliestIndex = i;\r
-                break;\r
-            }\r
-        }\r
-        if (earliestIndex == 0)\r
-            earliestIndex = pickables.size();\r
-        IElement selectedPick = pickables.get(earliestIndex - 1);\r
-        return selectedPick;\r
-    }\r
-\r
-    public static 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
-        @Override\r
-        public void init() {\r
-            super.init();\r
-            addEventHandler(this);\r
-        }\r
-        \r
-        public void setDiagram(IDiagram diagram) {\r
-            if (diagram != null)\r
-                this.diagramResource = diagram.getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE);\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
-            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
-        \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);\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
-            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
-            return super.mouseClicked(e);\r
-        }\r
-        \r
-        @Override\r
-        protected boolean mouseMoved(MouseMovedEvent e) {\r
-            return super.mouseMoved(e);\r
-        }\r
-    }\r
-}\r
+
+package org.simantics.district.network.ui;
+
+import java.awt.geom.AffineTransform;
+import java.awt.geom.Point2D;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.simantics.district.network.ui.adapters.DistrictNetworkVertexElement;
+import org.simantics.district.network.ui.nodes.DistrictNetworkVertexNode;
+import org.simantics.district.network.ui.nodes.NetworkDrawingNode;
+import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
+import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;
+import org.simantics.g2d.diagram.IDiagram;
+import org.simantics.g2d.diagram.handler.PickContext;
+import org.simantics.g2d.diagram.handler.PickRequest;
+import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;
+import org.simantics.g2d.element.IElement;
+import org.simantics.scenegraph.Node;
+import org.simantics.scenegraph.g2d.G2DParentNode;
+import org.simantics.utils.datastructures.hints.IHintContext.Key;
+import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
+
+public class NetworkDrawingParticipant extends AbstractDiagramParticipant {
+
+    @Dependency
+    PickContext pick;
+    
+    /**
+     * A hint key for terminal pick distance in control pixels.
+     * @see #PICK_DIST
+     */
+    public static final Key KEY_PICK_DISTANCE = new KeyOf(Double.class, "PICK_DISTANCE");
+
+    /**
+     * Default terminal pick distance in control pixels.
+     * @see #DEFAULT_PICK_DISTANCE
+     */
+    public static final double PICK_DIST = 10;
+    
+    private NetworkDrawingNode node;
+
+    private AffineTransform transform;
+    
+    public NetworkDrawingParticipant(AffineTransform transform) {
+        this.transform = transform;
+    }
+
+    @SGInit
+    public void initSG(G2DParentNode parent) {
+        node = parent.addNode("networkDrawingNode", NetworkDrawingNode.class);
+        node.setTransform(transform);
+        node.setNetworkDrawingParticipant(this);
+    }
+    
+    @Override
+    protected void onDiagramSet(IDiagram newDiagram, IDiagram oldDiagram) {
+        node.setDiagram(newDiagram);
+    }
+
+    public boolean pickHoveredElement(Point2D currentMousePos) {
+        PickRequest req = new PickRequest(currentMousePos.getX(), currentMousePos.getY()).context(getContext());
+        List<IElement> pickables = new ArrayList<IElement>();
+        pick.pick(diagram, req, pickables);
+        
+        List<IElement> snap = new ArrayList<>(diagram.getSnapshot());
+        
+        snap.removeAll(pickables);
+        
+        boolean changed = false;
+        for (IElement sn : snap) {
+            Node node = sn.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
+            if (node instanceof DistrictNetworkVertexNode) {
+                if (((DistrictNetworkVertexNode) node).hover(false) && !changed) {
+                    changed = true;
+                }
+            }
+        }
+        
+        for (IElement elem : pickables) {
+            Node node = elem.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
+            if (node instanceof DistrictNetworkVertexNode) {
+                if (((DistrictNetworkVertexNode) node).hover(true) && !changed) {
+                    changed = true;
+                }
+            }
+        }
+        return changed;
+    }
+
+    public AffineTransform getTransform() {
+        return transform;
+    }
+}