]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.diagram.connection/src/org/simantics/diagram/connection/rendering/BasicConnectionStyle.java
(refs #7177) Rounded connections
[simantics/platform.git] / bundles / org.simantics.diagram.connection / src / org / simantics / diagram / connection / rendering / BasicConnectionStyle.java
index a8661d324755eb2d99e374088aabe69cd6ec8727..b2895fb342d60fc1571b7f9b1fe4424c07144203 100644 (file)
@@ -13,10 +13,13 @@ package org.simantics.diagram.connection.rendering;
 
 import java.awt.Color;
 import java.awt.Graphics2D;
+import java.awt.RenderingHints;
 import java.awt.Stroke;
+import java.awt.geom.AffineTransform;
 import java.awt.geom.Ellipse2D;
 import java.awt.geom.Line2D;
 import java.awt.geom.Path2D;
+import java.awt.geom.PathIterator;
 import java.io.Serializable;
 
 /**
@@ -32,18 +35,25 @@ public class BasicConnectionStyle implements ConnectionStyle, Serializable {
     final double                    branchPointRadius;
     final Stroke                    lineStroke;
     final Stroke                    routeLineStroke;
-    final double                    degenerateLineLength; 
+    final double                    degenerateLineLength;
+    final double                    rounding;
 
     transient Line2D          line             = new Line2D.Double();
     transient Ellipse2D       ellipse          = new Ellipse2D.Double();
 
-    public BasicConnectionStyle(Color lineColor, Color branchPointColor, double branchPointRadius, Stroke lineStroke, Stroke routeLineStroke, double degenerateLineLength) {
+    public BasicConnectionStyle(Color lineColor, Color branchPointColor, double branchPointRadius, Stroke lineStroke, Stroke routeLineStroke, double degenerateLineLength,
+            double rounding) {
         this.lineColor = lineColor;
         this.branchPointColor = branchPointColor;
         this.branchPointRadius = branchPointRadius;
         this.lineStroke = lineStroke;
         this.routeLineStroke = routeLineStroke;
         this.degenerateLineLength = degenerateLineLength;
+        this.rounding = rounding;
+    }
+    
+    public BasicConnectionStyle(Color lineColor, Color branchPointColor, double branchPointRadius, Stroke lineStroke, Stroke routeLineStroke, double degenerateLineLength) {
+        this(lineColor, branchPointColor, branchPointRadius, lineStroke, routeLineStroke, degenerateLineLength, 0.0);
     }
 
     public Color getLineColor() {
@@ -88,7 +98,83 @@ public class BasicConnectionStyle implements ConnectionStyle, Serializable {
             g.setColor(lineColor);
         if (lineStroke != null)
             g.setStroke(lineStroke);
-        g.draw(path);
+        if(rounding > 0.0) {
+            Object oldRenderingHint = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
+            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
+            g.draw(round(path));
+            g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldRenderingHint);
+        }
+        else
+            g.draw(path);
+    }
+    
+    private Path2D round(Path2D path) {
+        Path2D newPath = new Path2D.Double();
+        PathIterator it = path.getPathIterator(new AffineTransform());
+        double[] coords = new double[6];
+        double newX=0.0, newY=0.0;
+        double curX=0.0, curY=0.0;
+        double oldX=0.0, oldY=0.0;
+        int state = 0;
+        while(!it.isDone()) {
+            int type = it.currentSegment(coords);
+            if(type == PathIterator.SEG_LINETO) {
+                newX = coords[0];
+                newY = coords[1];
+                if(state == 1) {
+                    double dx1 = curX-oldX;
+                    double dy1 = curY-oldY;
+                    double dx2 = curX-newX;
+                    double dy2 = curY-newY;
+                    double maxRadius = 0.5 * Math.min(Math.sqrt(dx1*dx1 + dy1*dy1), Math.sqrt(dx2*dx2 + dy2*dy2));
+                    double radius = Math.min(rounding, maxRadius);
+                    newPath.lineTo(curX + radius*Math.signum(oldX-curX), curY + radius*Math.signum(oldY-curY));
+                    newPath.curveTo(curX, curY,
+                                    curX, curY,
+                                    curX + radius*Math.signum(newX-curX), curY + radius*Math.signum(newY-curY));
+
+                    //newPath.lineTo(curX + round*Math.signum(oldX-curX), curY + round*Math.signum(oldY-curY));
+                    //newPath.lineTo(curX + round*Math.signum(newX-curX), curY + round*Math.signum(newY-curY));
+                    //newPath.lineTo(curX, curY);
+                }
+                else
+                    ++state;
+                oldX = curX;
+                oldY = curY;
+                curX = newX;
+                curY = newY;   
+            }
+            else {
+                if(state > 0) {
+                    newPath.lineTo(curX, curY);
+                    state = 0;
+                }
+                switch(type) {
+                case PathIterator.SEG_MOVETO:
+                    curX = coords[0];
+                    curY = coords[1];
+                    newPath.moveTo(curX, curY);
+                    break;
+                case PathIterator.SEG_QUADTO:
+                    curX = coords[2];
+                    curY = coords[3];
+                    newPath.quadTo(coords[0], coords[1], coords[2], coords[3]);
+                    break;
+                case PathIterator.SEG_CUBICTO:
+                    curX = coords[4];
+                    curY = coords[5];
+                    newPath.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
+                    break;
+                case PathIterator.SEG_CLOSE:
+                    newPath.closePath();
+                    break;
+                }
+            }
+            it.next();
+        }
+        if(state > 0)
+            newPath.lineTo(curX, curY);
+        return newPath;
     }
 
     @Override
@@ -170,4 +256,8 @@ public class BasicConnectionStyle implements ConnectionStyle, Serializable {
         return true;
     }
 
+    public double getRounding() {
+        return rounding;
+    }
+
 }