/*******************************************************************************
- * Copyright (c) 2007, 2010 Association for Decentralized Information Management
+ * Copyright (c) 2007, 2020 Association for Decentralized Information Management
* in Industry THTH ry.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
*
* Contributors:
* VTT Technical Research Centre of Finland - initial API and implementation
+ * Semantum Oy - gitlab #454
*******************************************************************************/
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;
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;
/**
*
}
public static interface PickSorter {
+ /**
+ * Sorts the specified element list.
+ *
+ * @param elements the element list to sort
+ */
void sort(List<IElement> elements);
+ /**
+ * Extended interface-method that receives the pick request in addition to the
+ * picked elements to be sorted. Allows e.g. looking at the pick area in the
+ * sorter.
+ *
+ * <p>
+ * The default implementation just invokes {@link #sort(List)} ignoring the pick
+ * request. The default implementation also keeps PickSorter API/ABI-compatible.
+ *
+ * @param request the original pick request that produced the hits listed in
+ * <code>elements</code>
+ * @param elements the element list to sort
+ *
+ * @author Tuukka Lehtonen
+ * @since 1.43.0, 1.35.3
+ */
+ default void sort(PickRequest request, List<IElement> elements) {
+ sort(elements);
+ }
+
//
public static final PickSorter CONNECTIONS_LAST = new PickSorter() {
@Override
});
}
};
+
+ /*
+ * 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;
+ }
+
+ private void sortConnections(List<IElement> 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(Pair.make(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;
+ }
+ }
+ }
+
+ @Override
+ public void sort(PickRequest request, List<IElement> elements) {
+ if (sorter != null)
+ sorter.sort(request, elements);
+ sortConnections(elements);
+ }
+
+ @Override
+ public void sort(List<IElement> elements) {
+ if (sorter != null)
+ sorter.sort(elements);
+ sortConnections(elements);
+ }
+ };
+ }
}
}