X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;ds=sidebyside;f=org.simantics.district.network.ui%2Fsrc%2Forg%2Fsimantics%2Fdistrict%2Fnetwork%2Fui%2FNetworkDrawingParticipant.java;h=da2bf32aec1a6ab3170e1386da2dddda8a2e9b7b;hb=refs%2Fchanges%2F55%2F3355%2F2;hp=a8cd239b3d520edea52266c045979aa98d624a3d;hpb=a2e0d3dfba1245a13dcc8aa23c0188926e2a03c5;p=simantics%2Fdistrict.git diff --git a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/NetworkDrawingParticipant.java b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/NetworkDrawingParticipant.java index a8cd239b..da2bf32a 100644 --- a/org.simantics.district.network.ui/src/org/simantics/district/network/ui/NetworkDrawingParticipant.java +++ b/org.simantics.district.network.ui/src/org/simantics/district/network/ui/NetworkDrawingParticipant.java @@ -1,253 +1,121 @@ - -package org.simantics.district.network.ui; - -import java.awt.Color; -import java.awt.Graphics2D; -import java.awt.Shape; -import java.awt.geom.Path2D; -import java.awt.geom.Point2D; -import java.awt.geom.Rectangle2D; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Set; - -import org.simantics.Simantics; -import org.simantics.db.Resource; -import org.simantics.db.WriteGraph; -import org.simantics.db.common.request.WriteRequest; -import org.simantics.db.exception.DatabaseException; -import org.simantics.diagram.ui.DiagramModelHints; -import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency; -import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit; -import org.simantics.g2d.diagram.IDiagram; -import org.simantics.g2d.diagram.handler.PickContext; -import org.simantics.g2d.diagram.handler.PickRequest; -import org.simantics.g2d.diagram.handler.PickRequest.PickPolicy; -import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant; -import org.simantics.g2d.diagram.participant.Selection; -import org.simantics.g2d.element.IElement; -import org.simantics.g2d.participant.TransformUtil; -import org.simantics.g2d.utils.GeometryUtils; -import org.simantics.scenegraph.g2d.G2DNode; -import org.simantics.scenegraph.g2d.G2DParentNode; -import org.simantics.scenegraph.g2d.events.EventTypes; -import org.simantics.scenegraph.g2d.events.MouseEvent; -import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseClickEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDoubleClickedEvent; -import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent; -import org.simantics.scenegraph.utils.NodeUtil; -import org.simantics.utils.datastructures.hints.IHintContext.Key; -import org.simantics.utils.datastructures.hints.IHintContext.KeyOf; - -public class NetworkDrawingParticipant extends AbstractDiagramParticipant { - - /** - * 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; - - @Dependency Selection selection; - @Dependency TransformUtil util; - @Dependency PickContext pickContext; - - @SGInit - public void initSG(G2DParentNode parent) { - node = parent.addNode("networkDrawingNode", NetworkDrawingNode.class); - } - - @Override - protected void onDiagramSet(IDiagram newDiagram, IDiagram oldDiagram) { - node.setDiagram(newDiagram); - } - - @EventHandler(priority = 1 << 21) - public boolean handleClick(MouseClickEvent me) { - - boolean isLeft = me.button == MouseEvent.LEFT_BUTTON; - boolean isRight = me.button == MouseEvent.RIGHT_BUTTON; - if (!isLeft && !isRight) - return false; - boolean isShiftPressed = me.hasAllModifiers(MouseEvent.SHIFT_MASK); - - int selectionId = me.mouseId; - - double pickDist = getPickDistance(); - Rectangle2D controlPickRect = new Rectangle2D.Double(me.controlPosition.getX()-pickDist, me.controlPosition.getY()-pickDist, pickDist*2+1, pickDist*2+1); - Shape canvasPickRect = GeometryUtils.transformShape(controlPickRect, util.getInverseTransform()); - - PickRequest req = new PickRequest(canvasPickRect); - req.pickPolicy = PickPolicy.PICK_INTERSECTING_OBJECTS; - //req.pickSorter = PickRequest.PickSorter.CONNECTIONS_LAST; - List pickables = new ArrayList(); - pickContext.pick(diagram, req, pickables); - - Set currentSelection = selection.getSelection(selectionId); - - if (!pickables.isEmpty()) { - /* - * Select the one object the mouse points to. If multiple object - * are picked, select the one that is after the earliest by - * index of the current selection when shift is pressed. Otherwise - * always pick the topmost element. - */ - IElement selectedPick = isShiftPressed - ? rotatingPick(currentSelection, pickables) - : pickables.get(pickables.size() - 1); - - // Only select when - // 1. the selection would actually change - // AND - // 2.1. left button was pressed - // OR - // 2.2. right button was pressed and the element to-be-selected - // is NOT a part of the current selection - if (!Collections.singleton(selectedPick).equals(currentSelection) - && (isLeft || (isRight && !currentSelection.contains(selectedPick)))) { - selection.setSelection(selectionId, selectedPick); - } - } - - return false; - } - - private double getPickDistance() { - Double pickDistance = getHint(KEY_PICK_DISTANCE); - return pickDistance == null ? PICK_DIST : Math.max(pickDistance, 0); - } - - private IElement rotatingPick(int selectionId, List pickables) { - Set sel = selection.getSelection(selectionId); - return rotatingPick(sel, pickables); - } - - private IElement rotatingPick(Set sel, List pickables) { - int earliestIndex = pickables.size(); - for (int i = pickables.size() - 1; i >= 0; --i) { - if (sel.contains(pickables.get(i))) { - earliestIndex = i; - break; - } - } - if (earliestIndex == 0) - earliestIndex = pickables.size(); - IElement selectedPick = pickables.get(earliestIndex - 1); - return selectedPick; - } - - public static class NetworkDrawingNode extends G2DNode { - - private static final long serialVersionUID = -3475301184009620573L; - - private List nodes = new ArrayList<>(); - - private Rectangle2D rect = new Rectangle2D.Double(10, 10, 10, 10); - - private Set paths = new HashSet<>(); - - private Resource diagramResource; - - private boolean committed; - - @Override - public void init() { - super.init(); - addEventHandler(this); - } - - public void setDiagram(IDiagram diagram) { - if (diagram != null) - this.diagramResource = diagram.getHint(DiagramModelHints.KEY_DIAGRAM_RESOURCE); - } - - @Override - public void render(Graphics2D g2d) { - Color old = g2d.getColor(); - g2d.setColor(Color.BLUE); - - paths.forEach(p -> { - g2d.draw(p); - }); - - g2d.setColor(old); - } - - @Override - public Rectangle2D getBoundsInLocal() { - return rect.getBounds2D(); - } - - @Override - public int getEventMask() { - return EventTypes.MouseMask; - } - - @Override - protected boolean mouseDoubleClicked(MouseDoubleClickedEvent e) { - // nodes to path2d - Point2D start = null; - Point2D end = null; - Iterator nodeIter = nodes.iterator(); - while (nodeIter.hasNext()) { - if (end == null) { - start = nodeIter.next(); - } else { - start = end; - } - end = nodeIter.next(); - - createEdge(start, end); - } - - nodes.clear(); - committed = true; - - repaint(); - - return true; - } - - private void createEdge(Point2D start, Point2D end) { - double[] startCoords = new double[] { start.getX(), start.getY() }; - double[] endCoords = new double[] { end.getX(), end.getY() }; - - DNEdgeBuilder builder = new DNEdgeBuilder(diagramResource); - Simantics.getSession().asyncRequest(new WriteRequest() { - - @Override - public void perform(WriteGraph graph) throws DatabaseException { - builder.create(graph, startCoords, endCoords); - } - }); - - } - - @Override - protected boolean mouseClicked(MouseClickEvent e) { - if (committed) { - committed = false; - return false; - } - Point2D localPos = NodeUtil.worldToLocal(this, e.controlPosition, new Point2D.Double()); - nodes.add(new Point2D.Double(localPos.getX(), localPos.getY())); - return super.mouseClicked(e); - } - - @Override - protected boolean mouseMoved(MouseMovedEvent e) { - return super.mouseMoved(e); - } - } -} + +package org.simantics.district.network.ui; + +import java.awt.geom.AffineTransform; +import java.awt.geom.Point2D; +import java.awt.geom.Rectangle2D; +import java.util.ArrayList; +import java.util.List; + +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.g2d.canvas.impl.DependencyReflection.Dependency; +import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit; +import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.diagram.handler.PickContext; +import org.simantics.g2d.diagram.handler.PickRequest; +import org.simantics.g2d.diagram.participant.AbstractDiagramParticipant; +import org.simantics.g2d.element.IElement; +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; + +public class NetworkDrawingParticipant extends AbstractDiagramParticipant { + + public static final String NETWORK_DRAWING_NODE = "networkDrawingNode"; + + @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 AffineTransform transform; + + public NetworkDrawingParticipant(AffineTransform transform) { + this.transform = transform; + } + + @SGInit + public void initSG(G2DParentNode parent) { + node = parent.addNode(NETWORK_DRAWING_NODE, NetworkDrawingNode.class); + 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()); + List pickables = new ArrayList<>(); + pick.pick(diagram, req, pickables); + + List snap = diagram.getSnapshot(); + + boolean changed = false; + changed |= hoverNodes(snap, false, isConnectionTool, currentMousePos); + changed |= hoverNodes(pickables, true, isConnectionTool, currentMousePos); + return changed; + } + + private boolean hoverNodes(List 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 { + 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); + } + } + } + } + } + return changed; + } + + public boolean isHoveringOverNode(Point2D currentMousePos) { + PickRequest req = new PickRequest(currentMousePos).context(getContext()); + List pickables = new ArrayList(); + pick.pick(diagram, req, pickables); + for (IElement elem : pickables) { + Node node = elem.getHint(DistrictNetworkVertexElement.KEY_DN_VERTEX_NODE); + if (node instanceof DistrictNetworkVertexNode) { + return true; + } + } + return false; + } + + public AffineTransform getTransform() { + return transform; + } +}