]> gerrit.simantics Code Review - simantics/district.git/blobdiff - org.simantics.district.network.ui/src/org/simantics/district/network/ui/NetworkDrawingParticipant.java
Usability fixes for district network node hover info showing
[simantics/district.git] / org.simantics.district.network.ui / src / org / simantics / district / network / ui / NetworkDrawingParticipant.java
index 77ec735f6d2cc14c9f6013127244b6e82fac3ace..e5ce207e51af69f3760724a92c5697aa3748d591 100644 (file)
@@ -5,15 +5,15 @@ import java.awt.geom.AffineTransform;
 import java.awt.geom.Point2D;
 import java.awt.geom.Rectangle2D;
 import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
 import java.util.List;
 
 import org.simantics.db.Resource;
 import org.simantics.diagram.ui.DiagramModelHints;
 import org.simantics.district.network.ui.adapters.DistrictNetworkEdgeElement;
 import org.simantics.district.network.ui.adapters.DistrictNetworkVertexElement;
-import org.simantics.district.network.ui.nodes.DistrictNetworkEdgeNode;
 import org.simantics.district.network.ui.nodes.DistrictNetworkVertexNode;
-import org.simantics.district.network.ui.nodes.HoverSensitiveNode;
 import org.simantics.district.network.ui.nodes.NetworkDrawingNode;
 import org.simantics.district.network.ui.participants.DynamicVisualisationContributionsParticipant;
 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
@@ -24,36 +24,29 @@ import org.simantics.g2d.diagram.handler.PickRequest;
 import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;
 import org.simantics.g2d.element.ElementHints;
 import org.simantics.g2d.element.IElement;
+import org.simantics.maps.MapScalingTransform;
+import org.simantics.scenegraph.INode;
 import org.simantics.scenegraph.Node;
 import org.simantics.scenegraph.g2d.G2DParentNode;
-import org.simantics.scenegraph.g2d.IG2DNode;
-import org.simantics.utils.datastructures.hints.IHintContext.Key;
-import org.simantics.utils.datastructures.hints.IHintContext.KeyOf;
+import org.simantics.scenegraph.utils.GeometryUtils;
 
 public class NetworkDrawingParticipant extends AbstractDiagramParticipant {
 
     public static final String NETWORK_DRAWING_NODE = "networkDrawingNode";
 
-       @Dependency
+    @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 DynamicVisualisationContributionsParticipant dynamicVisualisationContributionsParticipant;
     private AffineTransform transform;
-    
+
+    /**
+     * Holds the current element for which hover information is shown.
+     * This is just to optimize the 
+     */
+    private IElement currentHoverElement;
+
     public NetworkDrawingParticipant(DynamicVisualisationContributionsParticipant dynamicVisualisationContributionsParticipant, AffineTransform transform) {
         this.dynamicVisualisationContributionsParticipant = dynamicVisualisationContributionsParticipant;
         this.transform = transform;
@@ -65,77 +58,76 @@ public class NetworkDrawingParticipant extends AbstractDiagramParticipant {
         node.setTransform(transform);
         node.setNetworkDrawingParticipant(this);
     }
-    
+
     @Override
     protected void onDiagramSet(IDiagram newDiagram, IDiagram oldDiagram) {
         node.setDiagram(newDiagram);
     }
 
-    public boolean pickHoveredElement(Point2D currentMousePos, boolean isConnectionTool) {
-        PickRequest req = new PickRequest(new Rectangle2D.Double(currentMousePos.getX(), currentMousePos.getY(), 1e-8, 1e-8)).context(getContext());
+    public boolean pickHoveredElement(Point2D canvasPos, boolean isConnectionTool, AffineTransform viewTransform) {
+        PickRequest req = new PickRequest(getPickRect(canvasPos, viewTransform)).context(getContext());
         List<IElement> pickables = new ArrayList<>();
         pick.pick(diagram, req, pickables);
+        
+
+        Comparator<IElement> nearestVerticesFirst = (IElement e1, IElement e2) -> {
+            // If there are any vertices in the elements, prefer those primarily.
+            DistrictNetworkVertexNode v1 = e1.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
+            DistrictNetworkVertexNode v2 = e2.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
+
+            // Don't reorder edges
+            if ((v1 == null && v2 == null))
+                return 0;
+
+            // Sort vertices in nearest first order
+            if (v1 != null && v2 != null) {
+                Rectangle2D b1 = v1.getBounds();
+                Rectangle2D b2 = v2.getBounds();
+                double dist1 = canvasPos.distanceSq(b1.getCenterX(), b1.getCenterY());
+                double dist2 = canvasPos.distanceSq(b2.getCenterX(), b2.getCenterY());
+                return dist1 < dist2 ? -1 : dist1 > dist2 ? 1 : 0;
+            }
+
+            // Always vertices before edges
+            return v1 != null && v2 == null ? -1 : 1;
+        };
 
-        List<IElement> snap = diagram.getSnapshot();
+        Collections.sort(pickables, nearestVerticesFirst);
 
-        hoverNodes2(pickables, true, isConnectionTool, currentMousePos);
-        // we repaint ourselves once the async calulation is ready
+        updateHoveredElement(pickables, true, isConnectionTool, viewTransform);
+        // Will repaint once the async hover info calculation is ready, no need to do it here
         return false;
-        
-//        boolean changed = false;
-//        changed |= hoverNodes(snap, false, isConnectionTool, currentMousePos);
-//        changed |= hoverNodes(pickables, true, isConnectionTool, currentMousePos);
-        //return changed;
     }
 
-    private boolean hoverNodes2(List<IElement> elements, boolean hover, boolean isConnectionTool, Point2D p) {
+    private boolean updateHoveredElement(List<IElement> elements, boolean hover, boolean isConnectionTool, AffineTransform viewTransform) {
         if (elements == null || elements.isEmpty()) {
+            currentHoverElement = null;
             return dynamicVisualisationContributionsParticipant.doHover(false, isConnectionTool);
         } else {
-            boolean changed = dynamicVisualisationContributionsParticipant.doHover(true, isConnectionTool);
-            if (changed) {
-                // we prefer the first picked element only
-                IElement elem = elements.get(0);
-                G2DParentNode node = elem.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
-                if (node instanceof DistrictNetworkVertexNode) {
-                } else {
-                    node = elem.getHint(DistrictNetworkEdgeElement.KEY_DN_EDGE_NODE);
-                }
-                Resource mapElement = elem.getHint(ElementHints.KEY_OBJECT);
-                Resource runtimeDiagram = diagram.getHint(DiagramModelHints.KEY_DIAGRAM_RUNTIME_RESOURCE);
-                dynamicVisualisationContributionsParticipant.hoverNode(runtimeDiagram, mapElement, node);
-            }
-            return changed;
-        }
-    }
+            dynamicVisualisationContributionsParticipant.doHover(true, isConnectionTool);
 
-    private boolean hoverNodes(List<IElement> elements, boolean hover, boolean isConnectionTool, Point2D p) {
-        boolean changed = false;
-        for (IElement elem : elements) {
-            Node node = elem.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
-            if (node instanceof DistrictNetworkVertexNode) {
-                changed |= ((DistrictNetworkVertexNode) node).hover(hover, isConnectionTool);
-                if (hover)
-                    ((DistrictNetworkVertexNode) node).setMousePosition(p);
-            } else {
+            // we prefer the first picked element only
+            IElement elem = elements.get(0);
+            if (elem.equals(currentHoverElement))
+                return false;
+
+            INode node = elem.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
+            if (node == null)
                 node = elem.getHint(DistrictNetworkEdgeElement.KEY_DN_EDGE_NODE);
-                if (node instanceof DistrictNetworkEdgeNode) {
-                    for (IG2DNode n : ((DistrictNetworkEdgeNode) node).getNodes()) {
-                        if (n instanceof HoverSensitiveNode) {
-                            changed |= ((HoverSensitiveNode)n).hover(hover, isConnectionTool);
-                            if (hover)
-                                ((HoverSensitiveNode)n).setMousePosition(p);
-                        }
-                    }
-                }
-            }
+            if (node == null)
+                return false;
+
+            Resource mapElement = elem.getHint(ElementHints.KEY_OBJECT);
+            Resource runtimeDiagram = diagram.getHint(DiagramModelHints.KEY_DIAGRAM_RUNTIME_RESOURCE);
+            currentHoverElement = elem;
+            dynamicVisualisationContributionsParticipant.hoverNode(runtimeDiagram, mapElement, node, MapScalingTransform.zoomLevel(viewTransform));
+            return true;
         }
-        return changed;
     }
 
-    public boolean isHoveringOverNode(Point2D currentMousePos) {
-        PickRequest req = new PickRequest(currentMousePos).context(getContext());
-        List<IElement> pickables = new ArrayList<IElement>();
+    public boolean isHoveringOverNode(Point2D canvasPos, AffineTransform viewTransform) {
+        PickRequest req = new PickRequest(getPickRect(canvasPos, viewTransform)).context(getContext());
+        List<IElement> pickables = new ArrayList<>();
         pick.pick(diagram, req, pickables);
         for (IElement elem : pickables) {
             Node node = elem.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
@@ -146,7 +138,20 @@ public class NetworkDrawingParticipant extends AbstractDiagramParticipant {
         return false;
     }
 
+    private Rectangle2D getPickRect(Point2D canvasPos, AffineTransform viewTransform) {
+        double pixelScale = 1.0 / GeometryUtils.getScale(viewTransform);
+        if (Double.isInfinite(pixelScale))
+            pixelScale = 1e-8;
+
+        Rectangle2D pickRect = GeometryUtils.expandRectangle(
+                new Rectangle2D.Double(canvasPos.getX(), canvasPos.getY(), 0, 0),
+                pixelScale * 4);
+
+        return pickRect;
+    }
+
     public AffineTransform getTransform() {
         return transform;
     }
+
 }