1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\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.scenegraph.g2d.nodes;
\r
14 import java.awt.Color;
\r
15 import java.awt.Graphics2D;
\r
16 import java.awt.Shape;
\r
17 import java.awt.Stroke;
\r
18 import java.awt.geom.Line2D;
\r
19 import java.awt.geom.Rectangle2D;
\r
21 import org.simantics.scenegraph.g2d.G2DNode;
\r
22 import org.simantics.scenegraph.utils.GeometryUtils;
\r
24 public class RelationshipNode extends G2DNode {
\r
26 private static final long serialVersionUID = 3517235896431855937L;
\r
28 public static transient double PADDING = 1;
\r
30 protected Stroke boxStroke = null;
\r
31 protected Stroke lineStroke = null;
\r
32 protected Color boxColor = null;
\r
33 protected Color lineColor = null;
\r
34 protected Shape bounds1 = null;
\r
35 protected Shape bounds2 = null;
\r
37 private transient Rectangle2D boundsInLocal = null;
\r
38 private transient float phase = 0;
\r
40 @SyncField({"boxstroke", "linestroke", "boxcolor", "linecolor", "bounds1", "bounds2"})
\r
41 public void init(Stroke boxStroke, Stroke lineStroke, Color boxColor, Color lineColor, Shape bounds1, Shape bounds2) {
\r
42 this.boxStroke = boxStroke;
\r
43 this.lineStroke = lineStroke;
\r
44 this.boxColor = boxColor;
\r
45 this.lineColor = lineColor;
\r
46 this.bounds1 = bounds1;
\r
47 this.bounds2 = bounds2;
\r
48 this.boundsInLocal = calculateLocalBounds();
\r
52 public void render(Graphics2D g) {
\r
53 if (bounds1 == null || bounds2 == null)
\r
60 float scale = (float) (1.0 / GeometryUtils.getScale(g.getTransform()));
\r
61 float scaledPhase = scale * phase;
\r
63 Rectangle2D rect = bounds1.getBounds2D();
\r
65 if (boxStroke != null && boxColor != null) {
\r
66 g.setStroke(GeometryUtils.scaleAndOffsetStroke(boxStroke, scale, scaledPhase));
\r
67 g.setColor(boxColor);
\r
68 GeometryUtils.expandRectangle(rect, PADDING, PADDING, PADDING, PADDING);
\r
72 if (lineStroke != null && lineColor != null) {
\r
73 if (lineStroke != boxStroke)
\r
74 g.setStroke(GeometryUtils.scaleAndOffsetStroke(lineStroke, scale, scaledPhase));
\r
75 if (lineColor != boxColor)
\r
76 g.setColor(lineColor);
\r
77 Rectangle2D rect2 = bounds2.getBounds2D();
\r
78 g.draw(new Line2D.Double(rect.getCenterX(), rect.getCenterY(), rect2.getCenterX(), rect2.getCenterY()));
\r
83 public Rectangle2D getBoundsInLocal() {
\r
84 return boundsInLocal;
\r
87 private Rectangle2D calculateLocalBounds() {
\r
88 if (bounds1 == null || bounds2 == null)
\r
91 Rectangle2D rect = bounds1.getBounds2D();
\r
92 Rectangle2D rect2 = bounds2.getBounds2D();
\r
94 double x1 = rect.getCenterX();
\r
95 double x2 = rect2.getCenterX();
\r
96 double y1 = rect.getCenterY();
\r
97 double y2 = rect2.getCenterY();
\r
98 double minx = Math.min(x1, x2);
\r
99 double maxx = Math.max(x1, x2);
\r
100 double miny = Math.min(y1, y2);
\r
101 double maxy = Math.max(y1, y2);
\r
103 return new Rectangle2D.Double(minx, miny, maxx - minx, maxy - miny);
\r