1 package org.simantics.district.network.ui.participants;
3 import java.awt.geom.Rectangle2D;
4 import java.util.Collections;
5 import java.util.Comparator;
7 import java.util.function.ToDoubleFunction;
9 import org.simantics.district.network.ui.adapters.DistrictNetworkEdgeElement;
10 import org.simantics.district.network.ui.adapters.DistrictNetworkVertexElement;
11 import org.simantics.district.network.ui.nodes.DistrictNetworkVertexNode;
12 import org.simantics.g2d.diagram.handler.PickRequest;
13 import org.simantics.g2d.diagram.handler.PickRequest.PickSorter;
14 import org.simantics.g2d.element.ElementHints;
15 import org.simantics.g2d.element.IElement;
16 import org.simantics.scenegraph.g2d.IG2DNode;
17 import org.simantics.scenegraph.g2d.nodes.SingleElementNode;
20 * @author Jani Simomaa
21 * @author Tuukka Lehtonen
23 public class DNPickSorter implements PickSorter {
25 public static ToDoubleFunction<Rectangle2D> centerDistSq(double x, double y) {
27 double dx = r.getCenterX() - x;
28 double dy = r.getCenterY() - y;
29 return dx * dx + dy * dy;
33 public static ToDoubleFunction<Rectangle2D> centerDistSq(Rectangle2D r1) {
34 return centerDistSq(r1.getCenterX(), r1.getCenterY());
38 * @param nearestLast if <code>true</code> the nearest elements are sorted
39 * into the tail of the list, if <code>false</code>
40 * nearest elements are at the beginning of the list
41 * @param distanceFunction function used for calculating the distance of each
42 * element's bounding box
43 * @return comparator implementing the requested diagram element comparison
45 public static Comparator<IElement> nearestVerticesFirst(boolean nearestLast, ToDoubleFunction<Rectangle2D> distanceFunction) {
46 int sign = nearestLast ? 1 : -1;
47 return (IElement e1, IElement e2) -> {
48 // If there are any vertices in the elements, prefer those primarily.
49 DistrictNetworkVertexNode v1 = e1.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
50 DistrictNetworkVertexNode v2 = e2.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
52 // Don't reorder edges
53 if ((v1 == null && v2 == null))
56 // Sort vertices in nearest first order
57 if (v1 != null && v2 != null) {
58 double dist1 = distanceFunction.applyAsDouble(v1.getBounds());
59 double dist2 = distanceFunction.applyAsDouble(v2.getBounds());
60 return dist1 < dist2 ? sign : dist1 > dist2 ? -sign : 0;
63 // Always vertices before edges
64 return v1 != null && v2 == null ? sign : -sign;
68 private static IG2DNode getNode(IElement element) {
69 IG2DNode node = element.getHint(DistrictNetworkEdgeElement.KEY_DN_EDGE_NODE);
71 node = element.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
73 node = element.getHint(ElementHints.KEY_SG_NODE);
74 if (node instanceof SingleElementNode) {
75 SingleElementNode snode = (SingleElementNode) node;
76 node = snode.getNodes().iterator().next();
82 private static Comparator<IElement> zSorter() {
84 IG2DNode e1node = getNode(e1);
85 IG2DNode e2node = getNode(e2);
86 if (e1node.getZIndex() < e2node.getZIndex())
88 else if (e1node.getZIndex() > e2node.getZIndex())
95 public void sort(List<IElement> elements) {
96 Collections.sort(elements, zSorter());
100 public void sort(PickRequest req, List<IElement> elements) {
101 Collections.sort(elements, zSorter());
102 Collections.sort(elements, nearestVerticesFirst( true, centerDistSq( req.pickArea.getBounds2D() ) ));