]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.g2d/src/org/simantics/g2d/diagram/handler/PickRequest.java
Take zoom level into account when picking connections
[simantics/platform.git] / bundles / org.simantics.g2d / src / org / simantics / g2d / diagram / handler / PickRequest.java
index 265caa805b604210e12612d49b22a2126ada9c35..912e79cd9ce3e8caec89606ba61c495e797c0923 100644 (file)
@@ -14,12 +14,17 @@ package org.simantics.g2d.diagram.handler;
 import java.awt.Shape;
 import java.awt.geom.AffineTransform;
 import java.awt.geom.Area;
+import java.awt.geom.Line2D;
 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.diagram.connection.RouteLine;
+import org.simantics.diagram.connection.RoutePoint;
+import org.simantics.diagram.connection.segments.Segment;
 import org.simantics.g2d.canvas.ICanvasContext;
 import org.simantics.g2d.connection.handler.ConnectionHandler;
 import org.simantics.g2d.element.IElement;
@@ -28,8 +33,11 @@ import org.simantics.g2d.element.handler.TerminalTopology;
 import org.simantics.g2d.element.handler.impl.ConnectionSelectionOutline;
 import org.simantics.g2d.elementclass.BranchPoint;
 import org.simantics.g2d.elementclass.MonitorHandler;
+import org.simantics.g2d.elementclass.RouteGraphConnectionClass;
 import org.simantics.g2d.utils.GeometryUtils;
+import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode;
 import org.simantics.scenegraph.utils.TransformedRectangle;
+import org.simantics.utils.datastructures.Pair;
 
 /**
  *
@@ -172,6 +180,64 @@ public class PickRequest {
                 });
             }
         };
+
+        /*
+         * First use the default sorting if available, then sort successive connections by their distance to cursor.
+         */
+        public static PickSorter connectionSorter(PickSorter sorter, double x, double y) {
+            return new PickSorter() {
+
+                private double getDistanceSqToRouteGraphConnection(RouteGraphNode rgn, double x, double y) {
+                    double minDistanceSq = Double.MAX_VALUE;
+                    for (RouteLine line : rgn.getRouteGraph().getAllLines()) {
+                        ArrayList<Segment> segments = new ArrayList<Segment>();
+                        line.collectSegments(segments);
+                        for (Segment segment : segments) {
+                            RoutePoint p1 = segment.p1;
+                            RoutePoint p2 = segment.p2;
+
+                            double distanceSq = Line2D.ptSegDistSq(p1.getX(), p1.getY(), p2.getX(), p2.getY(), x, y);
+                            if (distanceSq < minDistanceSq) {
+                                minDistanceSq = distanceSq;
+                            }
+                        }
+                    }
+                    return minDistanceSq;
+                }
+                
+                @Override
+                public void sort(List<IElement> elements) {
+                    if (sorter != null)
+                        sorter.sort(elements);
+
+                    List<Pair<Double, IElement>> connections = new ArrayList<>(elements.size());
+                    int tail = 0;
+                    for (int i = 0; i < elements.size(); i++) {
+                        IElement element = elements.get(i);
+                        RouteGraphNode rgn = element.getHint(RouteGraphConnectionClass.KEY_RG_NODE);
+                        if (rgn != null) {
+                            double distanceSq = getDistanceSqToRouteGraphConnection(rgn, x, y);
+                            connections.add(new Pair<Double, IElement>(distanceSq, element));
+                        }
+                        
+                        if (rgn == null || i == elements.size() - 1) {
+                            Collections.sort(connections, new Comparator<Pair<Double, IElement>>() {
+                                @Override
+                                public int compare(Pair<Double, IElement> connection1, Pair<Double, IElement> connection2) {
+                                    return Double.compare(connection2.first, connection1.first);
+                                }
+                            });
+                            for (Pair<Double, IElement> connection : connections) {
+                                elements.set(tail, connection.second);
+                                tail++;
+                            }
+                            connections.clear();
+                            tail = i + 1;
+                        }
+                    }
+                }
+            }; 
+        }
     }
 
 }