1 /*******************************************************************************
2 * Copyright (c) 2011 Association for Decentralized Information Management in
4 * All rights reserved. This program and the accompanying materials
5 * are made available under the terms of the Eclipse Public License v1.0
6 * which accompanies this distribution, and is available at
7 * http://www.eclipse.org/legal/epl-v10.html
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.diagram.connection.rendering;
14 import java.awt.Color;
15 import java.awt.Graphics2D;
16 import java.awt.RenderingHints;
17 import java.awt.Stroke;
18 import java.awt.geom.AffineTransform;
19 import java.awt.geom.Ellipse2D;
20 import java.awt.geom.Line2D;
21 import java.awt.geom.Path2D;
22 import java.awt.geom.PathIterator;
23 import java.io.Serializable;
26 * @author Tuukka Lehtonen
28 public class BasicConnectionStyle implements ConnectionStyle, Serializable {
30 private static final long serialVersionUID = -5799681720482456895L;
32 // line thickness in millimeters.
33 final Color lineColor;
34 final Color branchPointColor;
35 final double branchPointRadius;
36 final Stroke lineStroke;
37 final Stroke routeLineStroke;
38 final double degenerateLineLength;
39 final double rounding;
41 transient Line2D line = new Line2D.Double();
42 transient Ellipse2D ellipse = new Ellipse2D.Double();
44 public BasicConnectionStyle(Color lineColor, Color branchPointColor, double branchPointRadius, Stroke lineStroke, Stroke routeLineStroke, double degenerateLineLength,
46 this.lineColor = lineColor;
47 this.branchPointColor = branchPointColor;
48 this.branchPointRadius = branchPointRadius;
49 this.lineStroke = lineStroke;
50 this.routeLineStroke = routeLineStroke;
51 this.degenerateLineLength = degenerateLineLength;
52 this.rounding = rounding;
55 public BasicConnectionStyle(Color lineColor, Color branchPointColor, double branchPointRadius, Stroke lineStroke, Stroke routeLineStroke, double degenerateLineLength) {
56 this(lineColor, branchPointColor, branchPointRadius, lineStroke, routeLineStroke, degenerateLineLength, 0.0);
59 public Color getLineColor() {
63 public Color getBranchPointColor() {
64 return branchPointColor;
67 public double getBranchPointRadius() {
68 return branchPointRadius;
71 public Stroke getLineStroke() {
75 public Stroke getRouteLineStroke() {
76 return routeLineStroke;
80 public void drawLine(Graphics2D g, double x1, double y1, double x2,
81 double y2, boolean isTransient) {
82 if (lineColor != null)
83 g.setColor(lineColor);
85 g.setStroke(lineStroke);
86 line.setLine(x1, y1, x2, y2);
89 g.setStroke(routeLineStroke);
90 line.setLine(x1, y1, x2, y2);
96 public void drawPath(Graphics2D g, Path2D path, boolean isTransient) {
97 if (lineColor != null)
98 g.setColor(lineColor);
99 if (lineStroke != null)
100 g.setStroke(lineStroke);
102 Object oldRenderingHint = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
103 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
105 g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldRenderingHint);
111 private Path2D round(Path2D path) {
112 Path2D newPath = new Path2D.Double();
113 PathIterator it = path.getPathIterator(new AffineTransform());
114 double[] coords = new double[6];
115 double newX=0.0, newY=0.0;
116 double curX=0.0, curY=0.0;
117 double oldX=0.0, oldY=0.0;
119 while(!it.isDone()) {
120 int type = it.currentSegment(coords);
121 if(type == PathIterator.SEG_LINETO) {
125 double dx1 = curX-oldX;
126 double dy1 = curY-oldY;
127 double dx2 = curX-newX;
128 double dy2 = curY-newY;
129 double r1 = Math.sqrt(dx1*dx1 + dy1*dy1);
130 double r2 = Math.sqrt(dx2*dx2 + dy2*dy2);
131 double maxRadius = 0.5 * Math.min(r1, r2);
132 double radius = Math.min(rounding, maxRadius);
133 double dx1Normalized = r1 > 0 ? dx1 / r1 : 0;
134 double dy1Normalized = r1 > 0 ? dy1 / r1 : 0;
135 double dx2Normalized = r2 > 0 ? dx2 / r2 : 0;
136 double dy2Normalized = r2 > 0 ? dy2 / r2 : 0;
137 newPath.lineTo(curX - radius*dx1Normalized, curY - radius*dy1Normalized);
138 newPath.curveTo(curX, curY,
140 curX - radius*dx2Normalized, curY - radius*dy2Normalized);
151 newPath.lineTo(curX, curY);
155 case PathIterator.SEG_MOVETO:
158 newPath.moveTo(curX, curY);
160 case PathIterator.SEG_QUADTO:
163 newPath.quadTo(coords[0], coords[1], coords[2], coords[3]);
165 case PathIterator.SEG_CUBICTO:
168 newPath.curveTo(coords[0], coords[1], coords[2], coords[3], coords[4], coords[5]);
170 case PathIterator.SEG_CLOSE:
178 newPath.lineTo(curX, curY);
183 public void drawBranchPoint(Graphics2D g, double x, double y) {
184 g.setColor(branchPointColor);
185 double r = branchPointRadius;
187 ellipse.setFrame(x-r, y-r, d, d);
192 public void drawDegeneratedLine(Graphics2D g, double x, double y,
193 boolean isHorizontal, boolean isTransient) {
194 double d = getDegeneratedLineLength()*0.5;
196 line.setLine(x-d, y, x+d, y);
199 line.setLine(x, y-d, x, y+d);
205 public double getDegeneratedLineLength() {
206 return degenerateLineLength;
210 public int hashCode() {
211 final int prime = 31;
213 result = prime * result + ((branchPointColor == null) ? 0 : branchPointColor.hashCode());
215 temp = Double.doubleToLongBits(branchPointRadius);
216 result = prime * result + (int) (temp ^ (temp >>> 32));
217 temp = Double.doubleToLongBits(degenerateLineLength);
218 result = prime * result + (int) (temp ^ (temp >>> 32));
219 result = prime * result + ((lineColor == null) ? 0 : lineColor.hashCode());
220 result = prime * result + ((lineStroke == null) ? 0 : lineStroke.hashCode());
221 result = prime * result + ((routeLineStroke == null) ? 0 : routeLineStroke.hashCode());
226 public boolean equals(Object obj) {
231 if (getClass() != obj.getClass())
233 BasicConnectionStyle other = (BasicConnectionStyle) obj;
234 if (branchPointColor == null) {
235 if (other.branchPointColor != null)
237 } else if (!branchPointColor.equals(other.branchPointColor))
239 if (Double.doubleToLongBits(branchPointRadius) != Double.doubleToLongBits(other.branchPointRadius))
241 if (Double.doubleToLongBits(degenerateLineLength) != Double.doubleToLongBits(other.degenerateLineLength))
243 if (lineColor == null) {
244 if (other.lineColor != null)
246 } else if (!lineColor.equals(other.lineColor))
248 if (lineStroke == null) {
249 if (other.lineStroke != null)
251 } else if (!lineStroke.equals(other.lineStroke))
253 if (routeLineStroke == null) {
254 if (other.routeLineStroke != null)
256 } else if (!routeLineStroke.equals(other.routeLineStroke))
261 public double getRounding() {