X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.diagram%2Fsrc%2Forg%2Fsimantics%2Fdiagram%2Fparticipant%2FConnectTool2.java;h=71a8d28290f9b7e020ef3bbb368ccc994287f8bc;hp=4aaa717d843109cb5d92e97e925fc3dd6dfab020;hb=bd5bc6e45f700e755b61bd112631796631330ecb;hpb=7684baeb8bc7963700676af20db6f4a860581e46 diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/ConnectTool2.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/ConnectTool2.java index 4aaa717d8..71a8d2829 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/ConnectTool2.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/ConnectTool2.java @@ -25,7 +25,6 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Deque; -import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -39,12 +38,15 @@ import org.simantics.db.common.utils.NameUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.diagram.connection.RouteGraph; import org.simantics.diagram.connection.RouteGraphConnectionClass; +import org.simantics.diagram.connection.RouteLine; import org.simantics.diagram.connection.RouteTerminal; +import org.simantics.diagram.connection.delta.RouteGraphDelta; import org.simantics.diagram.connection.rendering.arrows.PlainLineEndStyle; import org.simantics.diagram.content.ResourceTerminal; import org.simantics.diagram.stubs.DiagramResource; import org.simantics.diagram.synchronization.ISynchronizationContext; import org.simantics.diagram.synchronization.SynchronizationHints; +import org.simantics.diagram.synchronization.graph.RouteGraphConnection; import org.simantics.g2d.canvas.ICanvasContext; import org.simantics.g2d.canvas.impl.DependencyReflection.Dependency; import org.simantics.g2d.canvas.impl.DependencyReflection.Reference; @@ -54,6 +56,7 @@ import org.simantics.g2d.connection.IConnectionAdvisor; import org.simantics.g2d.diagram.DiagramHints; import org.simantics.g2d.diagram.DiagramUtils; import org.simantics.g2d.diagram.IDiagram; +import org.simantics.g2d.diagram.handler.PickContext; import org.simantics.g2d.diagram.handler.Topology.Terminal; import org.simantics.g2d.diagram.participant.ElementPainter; import org.simantics.g2d.diagram.participant.TerminalPainter; @@ -70,6 +73,7 @@ import org.simantics.g2d.element.IElementClassProvider; import org.simantics.g2d.element.handler.EdgeVisuals.EdgeEnd; import org.simantics.g2d.element.handler.SceneGraph; import org.simantics.g2d.element.handler.TerminalTopology; +import org.simantics.g2d.element.handler.impl.BranchPointTerminal; import org.simantics.g2d.element.impl.Element; import org.simantics.g2d.elementclass.BranchPoint; import org.simantics.g2d.elementclass.BranchPoint.Direction; @@ -77,8 +81,8 @@ import org.simantics.g2d.elementclass.FlagClass; import org.simantics.g2d.elementclass.FlagHandler; import org.simantics.g2d.participant.RenderingQualityInteractor; import org.simantics.g2d.participant.TransformUtil; +import org.simantics.g2d.utils.geom.DirectionSet; import org.simantics.modeling.ModelingResources; -import org.simantics.scenegraph.INode; import org.simantics.scenegraph.g2d.G2DParentNode; import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler; import org.simantics.scenegraph.g2d.events.KeyEvent; @@ -101,6 +105,8 @@ import org.simantics.utils.logging.TimeLogger; import org.simantics.utils.ui.ErrorLogger; import org.simantics.utils.ui.ExceptionUtils; +import gnu.trove.map.hash.THashMap; + /** * A basic tool for making connection on diagrams. * @@ -141,6 +147,9 @@ public class ConnectTool2 extends AbstractMode { @Dependency protected PointerInteractor pi; + @Dependency + protected PickContext pickContext; + /** * Start element terminal of the connection. null if connection * was started from a flag or a branch point. @@ -269,6 +278,8 @@ public class ConnectTool2 extends AbstractMode { protected G2DParentNode endFlagNode; + private RouteGraphTarget lastRouteGraphTarget; + /** * @param startTerminal * @param mouseId @@ -387,9 +398,9 @@ public class ConnectTool2 extends AbstractMode { ShapeNode pathNode = ghostNode.getOrCreateNode("path", ShapeNode.class); pathNode.setColor(new Color(160, 0, 0)); - pathNode.setStroke(new BasicStroke(2f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10, - new float[] { 5f, 2f }, 0)); - pathNode.setScaleStroke(true); + pathNode.setStroke(new BasicStroke(0.1f, BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 10, + new float[] { 0.5f, 0.2f }, 0)); + pathNode.setScaleStroke(false); pathNode.setZIndex(0); G2DParentNode points = ghostNode.getOrCreateNode("points", G2DParentNode.class); @@ -443,105 +454,18 @@ public class ConnectTool2 extends AbstractMode { ControlPoint begin = controlPoints.getFirst(); ControlPoint end = controlPoints.getLast(); - + RouteGraph routeGraph = new RouteGraph(); RouteTerminal a = addControlPoint(routeGraph, begin); RouteTerminal b = addControlPoint(routeGraph, end); routeGraph.link(a, b); - - // Route connection segments separately - /*Router2 router = ElementUtils.getHintOrDefault(diagram, DiagramHints.ROUTE_ALGORITHM, TrivialRouter2.INSTANCE); - final List segments = toSegments(controlPoints); - //System.out.println("controlpoints: " + controlPoints); - //System.out.println("segments: " + segments); - router.route(new IConnection() { - @Override - public Collection getSegments() { - return segments; - } - - @Override - public Connector getBegin(Object seg) { - return getConnector(((Segment) seg).begin); - } - - @Override - public Connector getEnd(Object seg) { - return getConnector(((Segment) seg).end); - } - - private Connector getConnector(ControlPoint cp) { - Connector c = new Connector(); - c.x = cp.getPosition().getX(); - c.y = cp.getPosition().getY(); - - TerminalInfo ti = cp.getAttachedTerminal(); - if (ti != null && (ti == startFlag || ti != endFlag)) { - //System.out.println("CP1: " + cp); - c.parentObstacle = DiagramUtils.getObstacleShape(ti.e); - ConnectionDirectionUtil.determineAllowedDirections(c); - } else { - //System.out.println("CP2: " + cp); - c.parentObstacle = GeometryUtils.transformRectangle(AffineTransform.getTranslateInstance(c.x, c.y), - BranchPointClass.DEFAULT_IMAGE2.getBounds()); - c.allowedDirections = toAllowedDirections(cp.getDirection()); - } - - return c; - } - @Override - public void setPath(Object seg, Path2D path) { - ((Segment) seg).path = (Path2D) path.clone(); - } - - private int toAllowedDirections(BranchPoint.Direction direction) { - switch (direction) { - case Any: - return 0xf; - case Horizontal: - return Constants.EAST_FLAG | Constants.WEST_FLAG; - case Vertical: - return Constants.NORTH_FLAG | Constants.SOUTH_FLAG; - default: - throw new IllegalArgumentException("unrecognized direction: " + direction); - } - } - }); - - // Combine the routed paths - Path2D path = new Path2D.Double(); - for (Segment seg : segments) { - //System.out.println("SEG: " + seg); - if (seg.path != null) - path.append(seg.path.getPathIterator(null), true); - }*/ - Path2D path = routeGraph.getPath2D(); // Create scene graph to visualize the connection. ShapeNode pathNode = ghostNode.getOrCreateNode("path", ShapeNode.class); pathNode.setShape(path); - G2DParentNode points = ghostNode.getOrCreateNode("points", G2DParentNode.class); - HashSet unusedChildren = new HashSet(points.getNodes()); - int i = 0; - for (ControlPoint cp : controlPoints) { - if (cp.isAttachedToTerminal()) - continue; - - String id = String.valueOf(i); - BranchPointNode bpn = points.getOrCreateNode(id, BranchPointNode.class); - bpn.setDegree(2); - bpn.setDirection((byte) cp.getDirection().ordinal()); - bpn.setTransform(AffineTransform.getTranslateInstance(cp.getPosition().getX(), cp.getPosition().getY())); - - ++i; - unusedChildren.remove(bpn); - } - for (INode unusedChild : unusedChildren) - points.removeNode(unusedChild); - setDirty(); } @@ -668,12 +592,48 @@ public class ConnectTool2 extends AbstractMode { // Make sure that we are ending with a flag if ALT is pressed // and no end terminal is defined. - endWithoutTerminal(lastMouseCanvasPos, shouldEndWithFlag(me)); - - updateSG(); + if (!endWithoutTerminal(lastMouseCanvasPos, shouldEndWithFlag(me))) + updateSG(); return false; } } + } else { + RouteGraphTarget cp = RouteGraphConnectTool.pickRouteGraphConnection( + diagram, + pi.getCanvasPickShape(me.controlPosition), + pi.getPickDistance()); + if (cp != null) { + // Remove branch point highlight from previously picked route graph. + if (lastRouteGraphTarget != null && cp.getNode() != lastRouteGraphTarget.getNode()) + cp.getNode().showBranchPoint(null); + lastRouteGraphTarget = cp; + + // Validate connection before visualizing connectability + Point2D isectPos = cp.getIntersectionPosition(); + TerminalInfo ti = TerminalInfo.create( + isectPos, + cp.getElement(), + BranchPointTerminal.existingTerminal( + isectPos, + DirectionSet.ANY, + BranchPointNode.SHAPE), + BranchPointNode.SHAPE); + Pair canConnect = canConnect(ti.e, ti.t); + if (canConnect != null) { + connectionJudgment = canConnect.first; + controlPoints.getLast().setPosition(ti.posDia).setAttachedToTerminal(ti); + endTerminal = ti; + cp.getNode().showBranchPoint(isectPos); + if (!endWithoutTerminal(lastMouseCanvasPos, shouldEndWithFlag(me))) + updateSG(); + return false; + } + } else { + if (lastRouteGraphTarget != null) { + lastRouteGraphTarget.getNode().showBranchPoint(null); + lastRouteGraphTarget = null; + } + } } connectionJudgment = null; @@ -705,9 +665,8 @@ public class ConnectTool2 extends AbstractMode { // Make sure that we are ending with a flag if ALT is pressed and no end // terminal is defined. - endWithoutTerminal(lastMouseCanvasPos, shouldEndWithFlag(me)); - - updateSG(); + if (!endWithoutTerminal(lastMouseCanvasPos, shouldEndWithFlag(me))) + updateSG(); return false; } @@ -729,8 +688,13 @@ public class ConnectTool2 extends AbstractMode { if (snapAdvisor != null) snapAdvisor.snap(mouseCanvasPos); - // Clicked on an allowed end terminal. End connection & end mode. - if (isEndTerminalDefined()) { + if (lastRouteGraphTarget != null) { + lastRouteGraphTarget.getNode().showBranchPoint(null); + attachToConnection(); + remove(); + return true; + } else if (isEndTerminalDefined()) { + // Clicked on an allowed end terminal. End connection & end mode. createConnection(); remove(); return true; @@ -772,6 +736,53 @@ public class ConnectTool2 extends AbstractMode { return false; } + private void attachToConnection() { + ConnectionJudgement judgment = this.connectionJudgment; + if (judgment == null) { + ErrorLogger.defaultLogError("Cannot attach to connection, no judgment available on connection validity", null); + return; + } + + ConnectionBuilder builder = new ConnectionBuilder(this.diagram); + RouteGraph before = lastRouteGraphTarget.getNode().getRouteGraph(); + THashMap copyMap = new THashMap<>(); + RouteGraph after = before.copy(copyMap); + + RouteLine attachTo = (RouteLine) copyMap.get(lastRouteGraphTarget.getLine()); + after.makePersistent(attachTo); + for (RouteLine line : after.getAllLines()) { + if (!line.isTransient() && line.isHorizontal() == attachTo.isHorizontal() + && line.getPosition() == attachTo.getPosition()) { + attachTo = line; + break; + } + } + RouteLine attachToLine = attachTo; + RouteGraphDelta delta = new RouteGraphDelta(before, after); + + Simantics.getSession().asyncRequest(new WriteRequest() { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + graph.markUndoPoint(); + Resource connection = ElementUtils.getObject(endTerminal.e); + if (!delta.isEmpty()) { + new RouteGraphConnection(graph, connection).synchronize(graph, before, after, delta); + } + Resource line = RouteGraphConnection.deserialize(graph, attachToLine.getData()); + Deque cps = new ArrayDeque<>(); + for (Iterator iterator = controlPoints.descendingIterator(); iterator.hasNext();) + cps.add(iterator.next()); + builder.attachToRouteGraph(graph, judgment, connection, line, cps, startTerminal, FlagClass.Type.In); + } + }, new Callback() { + @Override + public void run(DatabaseException parameter) { + if (parameter != null) + ExceptionUtils.logAndShowError(parameter); + } + }); + } + protected boolean cancelPreviousBend() { if (!routePointsAllowed()) return false; @@ -912,10 +923,16 @@ public class ConnectTool2 extends AbstractMode { return endFlag != null; } - protected void endWithoutTerminal(Point2D mousePos, boolean altDown) { + /** + * @param mousePos + * @param altDown + * @return true if updateSG was executed, false + * otherwise + */ + protected boolean endWithoutTerminal(Point2D mousePos, boolean altDown) { // Just go with branch points if flags are not allowed. if (!createFlags) - return; + return false; boolean endTerminalDefined = isEndTerminalDefined(); @@ -931,6 +948,7 @@ public class ConnectTool2 extends AbstractMode { setHint(TerminalPainter.TERMINAL_HOVER_STRATEGY, terminalHoverStrategy); updateSG(); + return true; } } else { if (isEndingInFlag()) { @@ -954,8 +972,10 @@ public class ConnectTool2 extends AbstractMode { setHint(TerminalPainter.TERMINAL_HOVER_STRATEGY, terminalHoverStrategy); updateSG(); + return true; } } + return false; } protected void createConnection() {