2 package org.simantics.district.network.ui;
4 import java.awt.geom.AffineTransform;
5 import java.awt.geom.Point2D;
6 import java.awt.geom.Rectangle2D;
7 import java.util.ArrayList;
8 import java.util.Collections;
9 import java.util.Comparator;
10 import java.util.List;
12 import org.simantics.db.Resource;
13 import org.simantics.diagram.ui.DiagramModelHints;
14 import org.simantics.district.network.ui.adapters.DistrictNetworkEdgeElement;
15 import org.simantics.district.network.ui.adapters.DistrictNetworkVertexElement;
16 import org.simantics.district.network.ui.nodes.DistrictNetworkVertexNode;
17 import org.simantics.district.network.ui.nodes.NetworkDrawingNode;
18 import org.simantics.district.network.ui.participants.DynamicVisualisationContributionsParticipant;
19 import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency;
20 import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;
21 import org.simantics.g2d.diagram.IDiagram;
22 import org.simantics.g2d.diagram.handler.PickContext;
23 import org.simantics.g2d.diagram.handler.PickRequest;
24 import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant;
25 import org.simantics.g2d.element.ElementHints;
26 import org.simantics.g2d.element.IElement;
27 import org.simantics.maps.MapScalingTransform;
28 import org.simantics.scenegraph.INode;
29 import org.simantics.scenegraph.Node;
30 import org.simantics.scenegraph.g2d.G2DParentNode;
31 import org.simantics.scenegraph.utils.GeometryUtils;
33 public class NetworkDrawingParticipant extends AbstractDiagramParticipant {
35 public static final String NETWORK_DRAWING_NODE = "networkDrawingNode";
40 private NetworkDrawingNode node;
41 private DynamicVisualisationContributionsParticipant dynamicVisualisationContributionsParticipant;
42 private AffineTransform transform;
45 * Holds the current element for which hover information is shown.
46 * This is just to optimize the
48 private IElement currentHoverElement;
50 public NetworkDrawingParticipant(DynamicVisualisationContributionsParticipant dynamicVisualisationContributionsParticipant, AffineTransform transform) {
51 this.dynamicVisualisationContributionsParticipant = dynamicVisualisationContributionsParticipant;
52 this.transform = transform;
56 public void initSG(G2DParentNode parent) {
57 node = parent.addNode(NETWORK_DRAWING_NODE, NetworkDrawingNode.class);
58 node.setTransform(transform);
59 node.setNetworkDrawingParticipant(this);
63 protected void onDiagramSet(IDiagram newDiagram, IDiagram oldDiagram) {
64 node.setDiagram(newDiagram);
67 public boolean pickHoveredElement(Point2D canvasPos, boolean isConnectionTool, AffineTransform viewTransform) {
68 PickRequest req = new PickRequest(getPickRect(canvasPos, viewTransform)).context(getContext());
69 List<IElement> pickables = new ArrayList<>();
70 pick.pick(diagram, req, pickables);
73 Comparator<IElement> nearestVerticesFirst = (IElement e1, IElement e2) -> {
74 // If there are any vertices in the elements, prefer those primarily.
75 DistrictNetworkVertexNode v1 = e1.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
76 DistrictNetworkVertexNode v2 = e2.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
78 // Don't reorder edges
79 if ((v1 == null && v2 == null))
82 // Sort vertices in nearest first order
83 if (v1 != null && v2 != null) {
84 Rectangle2D b1 = v1.getBounds();
85 Rectangle2D b2 = v2.getBounds();
86 double dist1 = canvasPos.distanceSq(b1.getCenterX(), b1.getCenterY());
87 double dist2 = canvasPos.distanceSq(b2.getCenterX(), b2.getCenterY());
88 return dist1 < dist2 ? -1 : dist1 > dist2 ? 1 : 0;
91 // Always vertices before edges
92 return v1 != null && v2 == null ? -1 : 1;
95 Collections.sort(pickables, nearestVerticesFirst);
97 updateHoveredElement(pickables, true, isConnectionTool, viewTransform);
98 // Will repaint once the async hover info calculation is ready, no need to do it here
102 private boolean updateHoveredElement(List<IElement> elements, boolean hover, boolean isConnectionTool, AffineTransform viewTransform) {
103 if (elements == null || elements.isEmpty()) {
104 currentHoverElement = null;
105 return dynamicVisualisationContributionsParticipant.doHover(false, isConnectionTool);
107 dynamicVisualisationContributionsParticipant.doHover(true, isConnectionTool);
109 // we prefer the first picked element only
110 IElement elem = elements.get(0);
111 if (elem.equals(currentHoverElement))
114 INode node = elem.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
116 node = elem.getHint(DistrictNetworkEdgeElement.KEY_DN_EDGE_NODE);
120 Resource mapElement = elem.getHint(ElementHints.KEY_OBJECT);
121 Resource runtimeDiagram = diagram.getHint(DiagramModelHints.KEY_DIAGRAM_RUNTIME_RESOURCE);
122 currentHoverElement = elem;
123 dynamicVisualisationContributionsParticipant.hoverNode(runtimeDiagram, mapElement, node, MapScalingTransform.zoomLevel(viewTransform));
128 public boolean isHoveringOverNode(Point2D canvasPos, AffineTransform viewTransform) {
129 PickRequest req = new PickRequest(getPickRect(canvasPos, viewTransform)).context(getContext());
130 List<IElement> pickables = new ArrayList<>();
131 pick.pick(diagram, req, pickables);
132 for (IElement elem : pickables) {
133 Node node = elem.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE);
134 if (node instanceof DistrictNetworkVertexNode) {
141 private Rectangle2D getPickRect(Point2D canvasPos, AffineTransform viewTransform) {
142 double pixelScale = 1.0 / GeometryUtils.getScale(viewTransform);
143 if (Double.isInfinite(pixelScale))
146 Rectangle2D pickRect = GeometryUtils.expandRectangle(
147 new Rectangle2D.Double(canvasPos.getX(), canvasPos.getY(), 0, 0),
153 public AffineTransform getTransform() {