1 /*******************************************************************************
\r
2 * Copyright (c) 2011 Association for Decentralized Information Management in
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.diagram.connection.rendering.arrows;
\r
14 import java.awt.Color;
\r
15 import java.awt.Graphics2D;
\r
16 import java.awt.geom.AffineTransform;
\r
17 import java.awt.geom.Path2D;
\r
18 import java.io.Serializable;
\r
19 import java.util.StringTokenizer;
\r
23 * @author Tuukka Lehtonen
\r
25 public class ArrowLineEndStyle implements ILineEndStyle, Serializable {
\r
27 private static final long serialVersionUID = -346653685430483245L;
\r
29 public static enum ArrowType { None, Stroke, Fill }
\r
31 public static final double DEFAULT_LENGTH = 8.0;
\r
32 public static final double DEFAULT_WIDTH = 4.0;
\r
33 public static final double DEFAULT_SPACE = 0.0;
\r
35 protected ArrowType type;
\r
36 protected double lineEndLength;
\r
37 protected double length;
\r
38 protected double width;
\r
39 protected double space;
\r
40 protected Color color;
\r
42 protected transient Path2D path;
\r
44 public ArrowLineEndStyle() {
\r
45 this(DEFAULT_LENGTH, DEFAULT_WIDTH, DEFAULT_SPACE, null);
\r
48 public ArrowLineEndStyle(double length, double width, double space) {
\r
49 this(length, width, space, null);
\r
52 public ArrowLineEndStyle(double length, double width, double space, Color color) {
\r
53 this.type = ArrowType.Fill;
\r
54 this.length = length;
\r
58 this.path = arrow(length, width, space);
\r
61 public ArrowLineEndStyle(String desc) {
\r
62 this.type = ArrowType.None;
\r
63 this.lineEndLength = 0.0;
\r
65 double l = DEFAULT_LENGTH;
\r
66 double w = DEFAULT_WIDTH;
\r
67 double s = DEFAULT_SPACE;
\r
69 StringTokenizer tokenizer = new StringTokenizer(desc);
\r
70 if (tokenizer.hasMoreTokens()) {
\r
71 String type = tokenizer.nextToken();
\r
72 this.type = parseType(type);
\r
74 if (tokenizer.hasMoreTokens()) {
\r
75 String ls = tokenizer.nextToken();
\r
76 l = parseSize(ls, length);
\r
78 if (tokenizer.hasMoreTokens()) {
\r
79 String ws = tokenizer.nextToken();
\r
80 w = parseSize(ws, width);
\r
82 if (tokenizer.hasMoreTokens()) {
\r
83 String ss = tokenizer.nextToken();
\r
84 s = parseSize(ss, space);
\r
88 if (this.type != ArrowType.None) {
\r
89 this.path = arrow(l, w, s);
\r
90 lineEndLength = l+s;
\r
100 public void render(Graphics2D g, double x, double y, int dir) {
\r
101 if (type == ArrowType.None || path == null)
\r
104 AffineTransform old = g.getTransform();
\r
106 g.rotate(dir*Math.PI*0.5);
\r
119 g.setTransform(old);
\r
123 public double getLineEndLength(int direction) {
\r
124 return lineEndLength;
\r
127 private static Path2D arrow(double length, double width, double space) {
\r
128 Path2D.Double path = new Path2D.Double();
\r
129 path.moveTo(-space, 0);
\r
130 path.lineTo(-length-space, -width);
\r
131 path.lineTo(-length-space, +width);
\r
136 private static double parseSize(String size, double defaultValue) {
\r
138 return Double.parseDouble(size);
\r
139 } catch (NumberFormatException e) {
\r
140 return defaultValue;
\r
144 private static ArrowType parseType(String type) {
\r
145 String lower = type.toLowerCase();
\r
146 if ("none".equals(lower))
\r
147 return ArrowType.None;
\r
148 if ("stroke".equals(lower))
\r
149 return ArrowType.Stroke;
\r
150 if ("fill".equals(lower))
\r
151 return ArrowType.Fill;
\r
152 throw new IllegalArgumentException("unrecognized arrow type: " + type);
\r
156 public String toString() {
\r
157 return getClass().getSimpleName() + "@" + System.identityHashCode(this) + "[" + type + ", w=" + width + ", l=" + length + ", s=" + space + ", lel=" + lineEndLength + "]";
\r
161 public int hashCode() {
\r
162 final int prime = 31;
\r
165 temp = Double.doubleToLongBits(length);
\r
166 result = prime * result + (int) (temp ^ (temp >>> 32));
\r
167 temp = Double.doubleToLongBits(lineEndLength);
\r
168 result = prime * result + (int) (temp ^ (temp >>> 32));
\r
169 temp = Double.doubleToLongBits(space);
\r
170 result = prime * result + (int) (temp ^ (temp >>> 32));
\r
171 result = prime * result + ((type == null) ? 0 : type.hashCode());
\r
172 temp = Double.doubleToLongBits(width);
\r
173 result = prime * result + (int) (temp ^ (temp >>> 32));
\r
178 public boolean equals(Object obj) {
\r
183 if (getClass() != obj.getClass())
\r
185 ArrowLineEndStyle other = (ArrowLineEndStyle) obj;
\r
186 if (Double.doubleToLongBits(length) != Double.doubleToLongBits(other.length))
\r
188 if (Double.doubleToLongBits(lineEndLength) != Double.doubleToLongBits(other.lineEndLength))
\r
190 if (Double.doubleToLongBits(space) != Double.doubleToLongBits(other.space))
\r
192 if (type != other.type)
\r
194 if (Double.doubleToLongBits(width) != Double.doubleToLongBits(other.width))
\r