]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/RelationshipNode.java
Configurable connection crossing styles
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / g2d / nodes / RelationshipNode.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.scenegraph.g2d.nodes;
13
14 import java.awt.Color;
15 import java.awt.Graphics2D;
16 import java.awt.Shape;
17 import java.awt.Stroke;
18 import java.awt.geom.Line2D;
19 import java.awt.geom.Rectangle2D;
20
21 import org.simantics.scenegraph.g2d.G2DNode;
22 import org.simantics.scenegraph.utils.GeometryUtils;
23
24 public class RelationshipNode extends G2DNode {
25
26     private static final long serialVersionUID = 3517235896431855937L;
27
28     public static transient double PADDING = 1;
29
30     protected Stroke boxStroke = null;
31     protected Stroke lineStroke = null;
32     protected Color boxColor = null;
33     protected Color lineColor = null;
34     protected Shape bounds1 = null;
35     protected Shape bounds2 = null;
36
37     private transient Rectangle2D boundsInLocal = null;
38     private transient float phase = 0;
39
40     @SyncField({"boxstroke", "linestroke", "boxcolor", "linecolor", "bounds1", "bounds2"})
41     public void init(Stroke boxStroke, Stroke lineStroke, Color boxColor, Color lineColor, Shape bounds1, Shape bounds2) {
42         this.boxStroke = boxStroke;
43         this.lineStroke = lineStroke;
44         this.boxColor = boxColor;
45         this.lineColor = lineColor;
46         this.bounds1 = bounds1;
47         this.bounds2 = bounds2;
48         this.boundsInLocal = calculateLocalBounds();
49     }
50
51     @Override
52     public void render(Graphics2D g) {
53         if (bounds1 == null || bounds2 == null)
54             return;
55
56         phase += 0.2;
57         if (phase > 10)
58             phase -= 10;
59
60         float scale = (float) (1.0 / GeometryUtils.getScale(g.getTransform()));
61         float scaledPhase = scale * phase;
62
63         Rectangle2D rect = bounds1.getBounds2D();
64
65         if (boxStroke != null && boxColor != null) {
66             g.setStroke(GeometryUtils.scaleAndOffsetStroke(boxStroke, scale, scaledPhase));
67             g.setColor(boxColor);
68             GeometryUtils.expandRectangle(rect, PADDING, PADDING, PADDING, PADDING);
69             g.draw(rect);
70         }
71
72         if (lineStroke != null && lineColor != null) {
73             if (lineStroke != boxStroke)
74                 g.setStroke(GeometryUtils.scaleAndOffsetStroke(lineStroke, scale, scaledPhase));
75             if (lineColor != boxColor)
76                 g.setColor(lineColor);
77             Rectangle2D rect2 = bounds2.getBounds2D();
78             g.draw(new Line2D.Double(rect.getCenterX(), rect.getCenterY(), rect2.getCenterX(), rect2.getCenterY()));
79         }
80     }
81
82     @Override
83     public Rectangle2D getBoundsInLocal() {
84         return boundsInLocal;
85     }
86
87     private Rectangle2D calculateLocalBounds() {
88         if (bounds1 == null || bounds2 == null)
89             return null;
90
91         Rectangle2D rect  = bounds1.getBounds2D();
92         Rectangle2D rect2 = bounds2.getBounds2D();
93
94         double x1 = rect.getCenterX();
95         double x2 = rect2.getCenterX();
96         double y1 = rect.getCenterY();
97         double y2 = rect2.getCenterY();
98         double minx = Math.min(x1, x2);
99         double maxx = Math.max(x1, x2);
100         double miny = Math.min(y1, y2);
101         double maxy = Math.max(y1, y2);
102
103         return new Rectangle2D.Double(minx, miny, maxx - minx, maxy - miny);
104     }
105
106 }