X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.diagram%2Fsrc%2Forg%2Fsimantics%2Fdiagram%2Fparticipant%2FRouteGraphConnectTool.java;h=e39c73d809120b760110c3476d44368f76e78336;hb=a5a5b0f8e0d52f5e400e3857c12fe862dd2e2dd9;hp=57f5cd4900310263031a81d3227c99f355a25917;hpb=bd5bc6e45f700e755b61bd112631796631330ecb;p=simantics%2Fplatform.git
diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/RouteGraphConnectTool.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/RouteGraphConnectTool.java
index 57f5cd490..e39c73d80 100644
--- a/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/RouteGraphConnectTool.java
+++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/participant/RouteGraphConnectTool.java
@@ -1,905 +1,927 @@
-/*******************************************************************************
- * Copyright (c) 2007, 2016 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
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * VTT Technical Research Centre of Finland - initial API and implementation
- * Semantum Oy - Fixed bug #6364
- *******************************************************************************/
-package org.simantics.diagram.participant;
-
-import java.awt.AlphaComposite;
-import java.awt.Composite;
-import java.awt.Shape;
-import java.awt.geom.AffineTransform;
-import java.awt.geom.Point2D;
-import java.awt.geom.Rectangle2D;
-import java.util.ArrayDeque;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Deque;
-import java.util.HashSet;
-import java.util.Iterator;
-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.connection.RouteGraph;
-import org.simantics.diagram.connection.RouteGraphConnectionClass;
-import org.simantics.diagram.connection.RouteLine;
-import org.simantics.diagram.connection.RoutePoint;
-import org.simantics.diagram.connection.RouteTerminal;
-import org.simantics.diagram.connection.delta.RouteGraphDelta;
-import org.simantics.diagram.connection.rendering.IRouteGraphRenderer;
-import org.simantics.diagram.connection.rendering.arrows.ArrowLineEndStyle;
-import org.simantics.diagram.connection.rendering.arrows.ILineEndStyle;
-import org.simantics.diagram.connection.rendering.arrows.PlainLineEndStyle;
-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.SGNodeReflection.SGCleanup;
-import org.simantics.g2d.canvas.impl.SGNodeReflection.SGInit;
-import org.simantics.g2d.connection.ConnectionEntity;
-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.PickRequest;
-import org.simantics.g2d.diagram.handler.Topology.Connection;
-import org.simantics.g2d.diagram.handler.Topology.Terminal;
-import org.simantics.g2d.diagram.participant.ElementPainter;
-import org.simantics.g2d.diagram.participant.TerminalPainter;
-import org.simantics.g2d.diagram.participant.TerminalPainter.TerminalHoverStrategy;
-import org.simantics.g2d.diagram.participant.pointertool.AbstractMode;
-import org.simantics.g2d.diagram.participant.pointertool.PointerInteractor;
-import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil;
-import org.simantics.g2d.diagram.participant.pointertool.TerminalUtil.TerminalInfo;
-import org.simantics.g2d.element.ElementClass;
-import org.simantics.g2d.element.ElementClasses;
-import org.simantics.g2d.element.ElementHints;
-import org.simantics.g2d.element.ElementUtils;
-import org.simantics.g2d.element.IElement;
-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.FlagClass;
-import org.simantics.g2d.elementclass.FlagHandler;
-import org.simantics.g2d.participant.TransformUtil;
-import org.simantics.g2d.utils.geom.DirectionSet;
-import org.simantics.scenegraph.g2d.G2DParentNode;
-import org.simantics.scenegraph.g2d.events.EventHandlerReflection.EventHandler;
-import org.simantics.scenegraph.g2d.events.KeyEvent;
-import org.simantics.scenegraph.g2d.events.KeyEvent.KeyPressedEvent;
-import org.simantics.scenegraph.g2d.events.MouseEvent;
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonEvent;
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseButtonPressedEvent;
-import org.simantics.scenegraph.g2d.events.MouseEvent.MouseMovedEvent;
-import org.simantics.scenegraph.g2d.events.command.CommandEvent;
-import org.simantics.scenegraph.g2d.events.command.Commands;
-import org.simantics.scenegraph.g2d.nodes.BranchPointNode;
-import org.simantics.scenegraph.g2d.nodes.ConnectionNode;
-import org.simantics.scenegraph.g2d.nodes.connection.RouteGraphNode;
-import org.simantics.scenegraph.g2d.snap.ISnapAdvisor;
-import org.simantics.scenegraph.utils.GeometryUtils;
-import org.simantics.structural2.modelingRules.ConnectionJudgement;
-import org.simantics.utils.datastructures.Callback;
-import org.simantics.utils.datastructures.Pair;
-import org.simantics.utils.datastructures.Triple;
-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.
- *
- * This version defines the starting, ending and route points of a connection.
- * The routing itself is left up to the diagram router employed by
- * {@link DiagramUtils#validateAndFix(IDiagram, ICanvasContext)}.
- *
- * Manual:
- *
- * This tool is added to the diagram when a connection sequence is initiated by
- * another participant. PointerInteractor is one such participant which adds the
- * tool when a terminal or non-terminal-occupied canvas space is ALT+clicked
- * (see {@link PointerInteractor#checkInitiateConnectTool(MouseEvent, Point2D)}
- * ). The connection will be finished when another allowed terminal is clicked
- * upon or empty canvas space is ALT+clicked. Route points for the connection
- * can be created by clicking around on non-terminal-occupied canvas space while
- * connecting.
- *
- *
- * Connections can be started from and ended in flags by pressing ALT while
- * left-clicking.
- *
- * @author Tuukka Lehtonen
- */
-public class RouteGraphConnectTool extends AbstractMode {
-
- private static final String END_TERMINAL_DATA = "END";
-
- public static final int PAINT_PRIORITY = ElementPainter.ELEMENT_PAINT_PRIORITY + 5;
-
- @Dependency
- protected TransformUtil util;
-
- @Dependency
- protected ElementPainter diagramPainter;
-
- @Dependency
- protected PointerInteractor pi;
-
- /**
- * Starting point designation.
- *
- * The value is received by the constructor.
- */
- protected RouteGraphTarget startingPoint;
-
- protected TerminalInfo startTerminal = new TerminalInfo();
-
- /**
- * true if this tool should create connection continuation
- * flags, false otherwise.
- */
- protected boolean createFlags;
-
- /**
- *
- */
- protected IElementClassProvider elementClassProvider;
-
- /**
- *
- */
- protected Deque controlPoints = new ArrayDeque();
-
- /**
- * Element terminal of connection end element. null if
- * connection cannot be ended where it is currently being attempted to end.
- */
- protected TerminalInfo endTerminal;
-
- /**
- * The latest connectability judgment from the active
- * {@link IConnectionAdvisor} should the connection happen between
- * {@link #startTerminal} and {@link #endTerminal}.
- */
- protected ConnectionJudgement connectionJudgment;
-
- /**
- * A temporary variable for use with
- * {@link TerminalTopology#getTerminals(IElement, Collection)}.
- */
- protected Collection terminals = new ArrayList();
-
- /**
- * Previous mouse canvas position recorded by
- * {@link #processMouseMove(MouseMovedEvent)}.
- */
- protected Point2D lastMouseCanvasPos = new Point2D.Double();
-
- /**
- * Set to true once {@link #processMouseMove(MouseMovedEvent)} has been
- * invoked at least once. This is used to tell whether to allow creation of
- * branch points or finising the connection in thin air. It will not be
- * allowed if the mouse has not moved at all since starting the connection.
- */
- protected boolean mouseHasMoved = false;
-
- protected TerminalHoverStrategy originalStrategy = null;
-
- protected TerminalHoverStrategy terminalHoverStrategy = new TerminalHoverStrategy() {
- @Override
- public boolean highlightEnabled() {
- return !isEndingInFlag();
- }
-
- @Override
- public boolean highlight(TerminalInfo ti) {
- return canConnect(ti.e, ti.t) != null;
- }
- };
-
- protected final static Composite ALPHA_COMPOSITE = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.75f);
-
- /**
- * Root scene graph node for all visualization performed by this tool.
- */
- protected ConnectionNode ghostNode;
-
- protected RouteGraphNode rgNode;
-
- protected RouteGraph routeGraph;
- protected RouteTerminal endRouteTerminal;
- private ILineEndStyle endTerminalStyle;
-
- /**
- * Indicates whether the connection is about to be ended into a new
- * flag/branchpoint or not.
- */
- protected TerminalInfo endFlag;
-
- protected G2DParentNode endFlagNode;
-
- private RouteLine attachedToRouteLine;
-
- protected RouteGraph beforeRouteGraph;
-
- private IRouteGraphRenderer beforeRenderer;
-
- private boolean beforeEditable;
-
- protected RouteGraphDelta routeGraphDelta;
-
- private Set> alreadyConnected;
-
- /**
- * @param startElement
- * @param routeGraphConnection
- * @param mouseId
- * @param startCanvasPos
- */
- public RouteGraphConnectTool(RouteGraphTarget startingPoint, int mouseId) {
- super(mouseId);
-
- Point2D intersection = startingPoint.getIntersectionPosition();
-
- this.startingPoint = startingPoint;
- this.lastMouseCanvasPos.setLocation(intersection);
-
- BranchPointTerminal t = BranchPointTerminal.existingTerminal(
- AffineTransform.getTranslateInstance(intersection.getX(), intersection.getY()),
- DirectionSet.ANY,
- BranchPointNode.SHAPE);
-
- Point2D p = startingPoint.getIntersectionPosition();
- AffineTransform at = AffineTransform.getTranslateInstance(p.getX(), p.getY());
-
- startTerminal.e = startingPoint.getElement();
- startTerminal.t = t;
- startTerminal.posElem = at;
- startTerminal.posDia = at;
- startTerminal.shape = t.getShape();
-
- controlPoints.add( newControlPoint( startingPoint.getIntersectionPosition() ) );
- controlPoints.add( newControlPoint( startingPoint.getCanvasPosition() ) );
-
- alreadyConnected = new HashSet>();
- IElement connection = startingPoint.getElement();
- ConnectionEntity ce = connection.getHint(ElementHints.KEY_CONNECTION_ENTITY);
- Collection tcs = ce.getTerminalConnections(null);
- for (Connection tc : tcs)
- alreadyConnected.add(Pair.make(tc.node, tc.terminal));
- }
-
- @Override
- public void addedToContext(ICanvasContext ctx) {
- super.addedToContext(ctx);
-
- // Force terminals to always be highlighted without pressing certain
- // keys or key combinations.
- originalStrategy = getHint(TerminalPainter.TERMINAL_HOVER_STRATEGY);
- setHint(TerminalPainter.TERMINAL_HOVER_STRATEGY, terminalHoverStrategy);
- }
-
- @Override
- protected void onDiagramSet(IDiagram newDiagram, IDiagram oldDiagram) {
- if (newDiagram != null) {
- // Get IElementClassProvider
- ISynchronizationContext ctx = newDiagram.getHint(SynchronizationHints.CONTEXT);
- if (ctx != null) {
- this.elementClassProvider = ctx.get(SynchronizationHints.ELEMENT_CLASS_PROVIDER);
- }
-
- // See if flags should be created or not.
- this.createFlags = Boolean.TRUE.equals(newDiagram.getHint(DiagramHints.KEY_USE_CONNECTION_FLAGS));
- }
- }
-
- @Override
- public void removedFromContext(ICanvasContext ctx) {
- if (getHint(TerminalPainter.TERMINAL_HOVER_STRATEGY) == terminalHoverStrategy) {
- if (originalStrategy != null)
- setHint(TerminalPainter.TERMINAL_HOVER_STRATEGY, originalStrategy);
- else
- removeHint(TerminalPainter.TERMINAL_HOVER_STRATEGY);
- }
-
- super.removedFromContext(ctx);
- }
-
- int straightDirections(RouteLine line) {
- return line.isHorizontal()
- ? (RouteTerminal.DIR_DOWN | RouteTerminal.DIR_UP)
- : (RouteTerminal.DIR_LEFT | RouteTerminal.DIR_RIGHT);
- }
-
- private static RouteTerminal addTerminal(Object data, RouteGraph rg, double x, double y, Rectangle2D bounds, int allowedDirections, ILineEndStyle style) {
- RouteTerminal rt;
- if (bounds != null)
- rt = rg.addTerminal(x, y, bounds.getMinX(), bounds.getMinY(), bounds.getMaxX(), bounds.getMaxY(), allowedDirections, style);
- else
- rt = rg.addTerminal(x, y, x, y, x, y, allowedDirections, style);
- rt.setData( data );
- return rt;
- }
-
- private RouteTerminal setEndTerminal(double x, double y, Rectangle2D bounds, int allowedDirections) {
-
- // First add then remove to prevent deletion of route lines in case there are 2 only terminals
-
- RouteTerminal toRemove = endRouteTerminal;
-
- endRouteTerminal = addTerminal( END_TERMINAL_DATA, routeGraph, x, y, bounds, allowedDirections, endTerminalStyle );
- routeGraph.link( attachedToRouteLine, endRouteTerminal );
-
- if (toRemove != null)
- routeGraph.remove(toRemove);
-
- return endRouteTerminal;
-
- }
-
- protected void setEndTerminal(TerminalInfo ti) {
- Rectangle2D bounds = ElementUtils.getElementBoundsOnDiagram(ti.e, new Rectangle2D.Double());
- GeometryUtils.expandRectangle(bounds, 2);
- int dir = RouteGraphConnectionClass.shortestDirectionOutOfBounds(
- ti.posDia.getTranslateX(), ti.posDia.getTranslateY(), bounds);
- setEndTerminal(ti.posDia.getTranslateX(), ti.posDia.getTranslateY(), bounds, dir);
- }
-
- @SGInit
- public void initSG(G2DParentNode parent) {
- ghostNode = parent.addNode("branched connection", ConnectionNode.class);
- //ghostNode.setComposite(AlphaComposite.SrcOver.derive(0.5f));
- ghostNode.setZIndex(PAINT_PRIORITY);
-
- rgNode = ghostNode.addNode("branch", RouteGraphNode.class);
-
- double ex = startingPoint.getCanvasPosition().getX();
- double ey = startingPoint.getCanvasPosition().getY();
-
- beforeRouteGraph = startingPoint.getNode().getRouteGraph();
- beforeEditable = startingPoint.getNode().isEditable();
-
- RouteGraphNode beforeRgNode = startingPoint.getNode();
- beforeRenderer = beforeRgNode.getRenderer();
-
- rgNode.setRenderer(beforeRenderer);
- rgNode.setEditable(false);
-
- beforeRgNode.setEditable(beforeEditable);
- beforeRgNode.setRenderer(null);
-
- initRG(ex, ey);
-
- }
-
- public void initRG(double ex, double ey) {
-
- THashMap