]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/RouteTerminal.java
Round corners between non-axis-aligned connection lines properly
[simantics/platform.git] / bundles / org.simantics.diagram.connection / src / org / simantics / diagram / connection / RouteTerminal.java
index 2f3fc9f86ec7ce7668c0dc12e87f741a4ae4c74e..3d6bd182f664b9146c5686155ac8d4f541e6f8cf 100644 (file)
@@ -13,6 +13,7 @@ package org.simantics.diagram.connection;
 
 import gnu.trove.map.hash.THashMap;
 
+import java.awt.geom.AffineTransform;
 import java.awt.geom.Rectangle2D;
 import java.io.PrintStream;
 import java.io.Serializable;
@@ -39,13 +40,14 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable
     private ILineEndStyle style;
     private ILineEndStyle dynamicStyle;
     private boolean routeToBounds;
+    private RouteTerminalPosition dynamicPosition;
 
     RouteLine line;
 
-    RouteTerminal(double x, double y, double minX, double minY,
+    public RouteTerminal(double x, double y, double minX, double minY,
             double maxX, double maxY, int allowedDirections,
             boolean routeToBounds,
-            ILineEndStyle style) {
+            ILineEndStyle style, RouteTerminalPosition dynamicPosition) {
         super(x, y);
         this.minX = minX;
         this.minY = minY;
@@ -54,8 +56,9 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable
         this.allowedDirections = allowedDirections;
         this.routeToBounds = routeToBounds;
         this.style = style;
+        this.dynamicPosition = dynamicPosition;
     }
-    
+
     @Override
     public void setData(Object data) {
         this.data = data;
@@ -95,7 +98,7 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable
      * adding necessary transient route lines.
      * @param cache 
      */
-    void route(ArrayList<RouteLine> lines, IntervalCache cache, boolean boundingBoxesIntersect) {
+    protected void route(ArrayList<RouteLine> lines, IntervalCache cache, boolean boundingBoxesIntersect) {
         if(routeToBounds) {
             int lineDir;
             boolean routeLineDoesNotIntersectTerminal;
@@ -136,7 +139,8 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable
                 return;
             }
             else {
-                line.addPoint(this);
+               if (!line.getPoints().contains(this))
+                  line.addPoint(this);
                 Interval interval = cache.get(line);
                 if(line.isHorizontal) {
                     if(interval.min < minX)
@@ -160,18 +164,31 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable
             boolean routeLineDoesNotIntersectTerminal;
             double linePosition = line.position;
             if(line.isHorizontal) { 
+                if (linePosition == y) {
+                    // direct route to terminal
+                    line.addPoint(this);
+                    return;
+                }
                 lineDir = linePosition < y ? 3 : 1;
                 routeLineDoesNotIntersectTerminal = linePosition <= minY || linePosition >= maxY 
                         || boundingBoxesIntersect /* we ignore intersection in this case */;
             }
             else {
+                if (linePosition == x) {
+                    // direct route to terminal
+                    line.addPoint(this);
+                    return;
+                }
                 lineDir = linePosition < x ? 2 : 0;
                 routeLineDoesNotIntersectTerminal = linePosition <= minX || linePosition >= maxX
                         || boundingBoxesIntersect /* we ignore intersection in this case */;
             }
                     
             // We can route the connection directly to the right direction
-            if(routeLineDoesNotIntersectTerminal && 
+            if((routeLineDoesNotIntersectTerminal ||
+                    (line.isHorizontal && (x == minX || x == maxX)) || // already on the top/bottom edge
+                    (!line.isHorizontal && (y == minY || y == maxY)) // already on the left/right edge
+                    ) && 
                     Directions.isAllowed(allowedDirections, lineDir)) {           
                 RouteLine line0 = createLine0(lineDir);
                 new RouteLink(line0, line);
@@ -254,7 +271,7 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable
         }
     }
     
-    private RouteLine createLine0(int dir) {
+    protected RouteLine createLine0(int dir) {
         RouteLine line0 = (dir&1) == 0 
                 ? new RouteLine(true, y)
                 : new RouteLine(false, x)
@@ -374,11 +391,11 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable
         }
     }
 
-    RouteTerminal copy(THashMap<Object, Object> map) {
+    public RouteTerminal copy(THashMap<Object, Object> map) {
        RouteTerminal copy = (RouteTerminal)map.get(this);
        if(copy == null) {      
                copy = new RouteTerminal(x,  y, minX, minY, maxX, maxY, 
-                               allowedDirections, routeToBounds, style);
+                               allowedDirections, routeToBounds, style, dynamicPosition);
                copy.setDynamicStyle(dynamicStyle);
                map.put(this, copy);
                copy.data = data;
@@ -415,6 +432,10 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable
         return line;
     }
     
+    public void setLine(RouteLine line) {
+               this.line = line;
+       }
+    
     public void setMinX(double minX) {
                this.minX = minX;
        }
@@ -449,4 +470,27 @@ public class RouteTerminal extends RoutePoint implements RouteNode, Serializable
     public void setDynamicStyle(ILineEndStyle dynamicStyle) {
                this.dynamicStyle = dynamicStyle;
        }
+
+    public RouteTerminalPosition getDynamicPosition() {
+        return dynamicPosition;
+    }
+    
+    
+
+    public boolean updateDynamicPosition() {
+        boolean changed = false;
+        if (dynamicPosition != null) {
+            AffineTransform tr = dynamicPosition.getTransform();
+            if (tr != null) {
+                double nx = tr.getTranslateX();
+                changed |= x != nx;
+                x = nx;
+                double ny = tr.getTranslateY();
+                changed |= y != ny;
+                y = ny;
+            }
+        }
+        return changed;
+    }
+
 }