-/*******************************************************************************\r
- * Copyright (c) 2011 Association for Decentralized Information Management in\r
- * Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- * VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.diagram.connection.rendering;\r
-\r
-import java.awt.Color;\r
-import java.awt.Graphics2D;\r
-import java.awt.Stroke;\r
-import java.awt.geom.Ellipse2D;\r
-import java.awt.geom.Line2D;\r
-import java.awt.geom.Path2D;\r
-import java.io.Serializable;\r
-\r
-/**\r
- * @author Tuukka Lehtonen\r
- */\r
-public class BasicConnectionStyle implements ConnectionStyle, Serializable {\r
-\r
- private static final long serialVersionUID = -5799681720482456895L;\r
-\r
- // line thickness in millimeters.\r
- final Color lineColor;\r
- final Color branchPointColor;\r
- final double branchPointRadius;\r
- final Stroke lineStroke;\r
- final Stroke routeLineStroke;\r
- final double degenerateLineLength; \r
-\r
- transient Line2D line = new Line2D.Double();\r
- transient Ellipse2D ellipse = new Ellipse2D.Double();\r
-\r
- public BasicConnectionStyle(Color lineColor, Color branchPointColor, double branchPointRadius, Stroke lineStroke, Stroke routeLineStroke, double degenerateLineLength) {\r
- this.lineColor = lineColor;\r
- this.branchPointColor = branchPointColor;\r
- this.branchPointRadius = branchPointRadius;\r
- this.lineStroke = lineStroke;\r
- this.routeLineStroke = routeLineStroke;\r
- this.degenerateLineLength = degenerateLineLength;\r
- }\r
-\r
- public Color getLineColor() {\r
- return lineColor;\r
- }\r
- \r
- public Color getBranchPointColor() {\r
- return branchPointColor;\r
- }\r
- \r
- public double getBranchPointRadius() {\r
- return branchPointRadius;\r
- }\r
- \r
- public Stroke getLineStroke() {\r
- return lineStroke;\r
- }\r
- \r
- public Stroke getRouteLineStroke() {\r
- return routeLineStroke;\r
- }\r
-\r
- @Override\r
- public void drawLine(Graphics2D g, double x1, double y1, double x2,\r
- double y2, boolean isTransient) {\r
- if (lineColor != null)\r
- g.setColor(lineColor);\r
- if(isTransient) {\r
- g.setStroke(lineStroke);\r
- line.setLine(x1, y1, x2, y2);\r
- g.draw(line);\r
- } else {\r
- g.setStroke(routeLineStroke);\r
- line.setLine(x1, y1, x2, y2);\r
- g.draw(line);\r
- }\r
- }\r
-\r
- @Override\r
- public void drawPath(Graphics2D g, Path2D path, boolean isTransient) {\r
- if (lineColor != null)\r
- g.setColor(lineColor);\r
- if (lineStroke != null)\r
- g.setStroke(lineStroke);\r
- g.draw(path);\r
- }\r
-\r
- @Override\r
- public void drawBranchPoint(Graphics2D g, double x, double y) {\r
- g.setColor(branchPointColor);\r
- double r = branchPointRadius;\r
- double d = 2*r;\r
- ellipse.setFrame(x-r, y-r, d, d);\r
- g.fill(ellipse);\r
- }\r
-\r
- @Override\r
- public void drawDegeneratedLine(Graphics2D g, double x, double y,\r
- boolean isHorizontal, boolean isTransient) {\r
- double d = getDegeneratedLineLength()*0.5;\r
- if(isHorizontal) {\r
- line.setLine(x-d, y, x+d, y);\r
- g.draw(line);\r
- } else {\r
- line.setLine(x, y-d, x, y+d);\r
- g.draw(line);\r
- }\r
- }\r
-\r
- @Override\r
- public double getDegeneratedLineLength() {\r
- return degenerateLineLength;\r
- }\r
-\r
- @Override\r
- public int hashCode() {\r
- final int prime = 31;\r
- int result = 1;\r
- result = prime * result + ((branchPointColor == null) ? 0 : branchPointColor.hashCode());\r
- long temp;\r
- temp = Double.doubleToLongBits(branchPointRadius);\r
- result = prime * result + (int) (temp ^ (temp >>> 32));\r
- temp = Double.doubleToLongBits(degenerateLineLength);\r
- result = prime * result + (int) (temp ^ (temp >>> 32));\r
- result = prime * result + ((lineColor == null) ? 0 : lineColor.hashCode());\r
- result = prime * result + ((lineStroke == null) ? 0 : lineStroke.hashCode());\r
- result = prime * result + ((routeLineStroke == null) ? 0 : routeLineStroke.hashCode());\r
- return result;\r
- }\r
-\r
- @Override\r
- public boolean equals(Object obj) {\r
- if (this == obj)\r
- return true;\r
- if (obj == null)\r
- return false;\r
- if (getClass() != obj.getClass())\r
- return false;\r
- BasicConnectionStyle other = (BasicConnectionStyle) obj;\r
- if (branchPointColor == null) {\r
- if (other.branchPointColor != null)\r
- return false;\r
- } else if (!branchPointColor.equals(other.branchPointColor))\r
- return false;\r
- if (Double.doubleToLongBits(branchPointRadius) != Double.doubleToLongBits(other.branchPointRadius))\r
- return false;\r
- if (Double.doubleToLongBits(degenerateLineLength) != Double.doubleToLongBits(other.degenerateLineLength))\r
- return false;\r
- if (lineColor == null) {\r
- if (other.lineColor != null)\r
- return false;\r
- } else if (!lineColor.equals(other.lineColor))\r
- return false;\r
- if (lineStroke == null) {\r
- if (other.lineStroke != null)\r
- return false;\r
- } else if (!lineStroke.equals(other.lineStroke))\r
- return false;\r
- if (routeLineStroke == null) {\r
- if (other.routeLineStroke != null)\r
- return false;\r
- } else if (!routeLineStroke.equals(other.routeLineStroke))\r
- return false;\r
- return true;\r
- }\r
-\r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2011 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
+ *******************************************************************************/
+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;
+
+/**
+ * @author Tuukka Lehtonen
+ */
+public class BasicConnectionStyle implements ConnectionStyle, Serializable {
+
+ private static final long serialVersionUID = -5799681720482456895L;
+
+ // line thickness in millimeters.
+ final Color lineColor;
+ final Color branchPointColor;
+ final double branchPointRadius;
+ final Stroke lineStroke;
+ final Stroke routeLineStroke;
+ 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,
+ 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() {
+ return lineColor;
+ }
+
+ public Color getBranchPointColor() {
+ return branchPointColor;
+ }
+
+ public double getBranchPointRadius() {
+ return branchPointRadius;
+ }
+
+ public Stroke getLineStroke() {
+ return lineStroke;
+ }
+
+ public Stroke getRouteLineStroke() {
+ return routeLineStroke;
+ }
+
+ @Override
+ public void drawLine(Graphics2D g, double x1, double y1, double x2,
+ double y2, boolean isTransient) {
+ if (lineColor != null)
+ g.setColor(lineColor);
+ if(isTransient) {
+ g.setStroke(lineStroke);
+ line.setLine(x1, y1, x2, y2);
+ g.draw(line);
+ } else {
+ g.setStroke(routeLineStroke);
+ line.setLine(x1, y1, x2, y2);
+ g.draw(line);
+ }
+ }
+
+ @Override
+ public void drawPath(Graphics2D g, Path2D path, boolean isTransient) {
+ if (lineColor != null)
+ g.setColor(lineColor);
+ if (lineStroke != null)
+ g.setStroke(lineStroke);
+ 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
+ public void drawBranchPoint(Graphics2D g, double x, double y) {
+ g.setColor(branchPointColor);
+ double r = branchPointRadius;
+ double d = 2*r;
+ ellipse.setFrame(x-r, y-r, d, d);
+ g.fill(ellipse);
+ }
+
+ @Override
+ public void drawDegeneratedLine(Graphics2D g, double x, double y,
+ boolean isHorizontal, boolean isTransient) {
+ double d = getDegeneratedLineLength()*0.5;
+ if(isHorizontal) {
+ line.setLine(x-d, y, x+d, y);
+ g.draw(line);
+ } else {
+ line.setLine(x, y-d, x, y+d);
+ g.draw(line);
+ }
+ }
+
+ @Override
+ public double getDegeneratedLineLength() {
+ return degenerateLineLength;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((branchPointColor == null) ? 0 : branchPointColor.hashCode());
+ long temp;
+ temp = Double.doubleToLongBits(branchPointRadius);
+ result = prime * result + (int) (temp ^ (temp >>> 32));
+ temp = Double.doubleToLongBits(degenerateLineLength);
+ result = prime * result + (int) (temp ^ (temp >>> 32));
+ result = prime * result + ((lineColor == null) ? 0 : lineColor.hashCode());
+ result = prime * result + ((lineStroke == null) ? 0 : lineStroke.hashCode());
+ result = prime * result + ((routeLineStroke == null) ? 0 : routeLineStroke.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ BasicConnectionStyle other = (BasicConnectionStyle) obj;
+ if (branchPointColor == null) {
+ if (other.branchPointColor != null)
+ return false;
+ } else if (!branchPointColor.equals(other.branchPointColor))
+ return false;
+ if (Double.doubleToLongBits(branchPointRadius) != Double.doubleToLongBits(other.branchPointRadius))
+ return false;
+ if (Double.doubleToLongBits(degenerateLineLength) != Double.doubleToLongBits(other.degenerateLineLength))
+ return false;
+ if (lineColor == null) {
+ if (other.lineColor != null)
+ return false;
+ } else if (!lineColor.equals(other.lineColor))
+ return false;
+ if (lineStroke == null) {
+ if (other.lineStroke != null)
+ return false;
+ } else if (!lineStroke.equals(other.lineStroke))
+ return false;
+ if (routeLineStroke == null) {
+ if (other.routeLineStroke != null)
+ return false;
+ } else if (!routeLineStroke.equals(other.routeLineStroke))
+ return false;
+ return true;
+ }
+
+ public double getRounding() {
+ return rounding;
+ }
+
+}