/******************************************************************************* * Copyright (c) 2007, 2010 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.scenegraph.g2d.nodes; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Shape; import java.awt.Stroke; import java.awt.geom.Line2D; import java.awt.geom.Rectangle2D; import org.simantics.scenegraph.g2d.G2DNode; import org.simantics.scenegraph.utils.GeometryUtils; public class RelationshipNode extends G2DNode { private static final long serialVersionUID = 3517235896431855937L; public static transient double PADDING = 1; protected Stroke boxStroke = null; protected Stroke lineStroke = null; protected Color boxColor = null; protected Color lineColor = null; protected Shape bounds1 = null; protected Shape bounds2 = null; private transient Rectangle2D boundsInLocal = null; private transient float phase = 0; @SyncField({"boxstroke", "linestroke", "boxcolor", "linecolor", "bounds1", "bounds2"}) public void init(Stroke boxStroke, Stroke lineStroke, Color boxColor, Color lineColor, Shape bounds1, Shape bounds2) { this.boxStroke = boxStroke; this.lineStroke = lineStroke; this.boxColor = boxColor; this.lineColor = lineColor; this.bounds1 = bounds1; this.bounds2 = bounds2; this.boundsInLocal = calculateLocalBounds(); } @Override public void render(Graphics2D g) { if (bounds1 == null || bounds2 == null) return; phase += 0.2; if (phase > 10) phase -= 10; float scale = (float) (1.0 / GeometryUtils.getScale(g.getTransform())); float scaledPhase = scale * phase; Rectangle2D rect = bounds1.getBounds2D(); if (boxStroke != null && boxColor != null) { g.setStroke(GeometryUtils.scaleAndOffsetStroke(boxStroke, scale, scaledPhase)); g.setColor(boxColor); GeometryUtils.expandRectangle(rect, PADDING, PADDING, PADDING, PADDING); g.draw(rect); } if (lineStroke != null && lineColor != null) { if (lineStroke != boxStroke) g.setStroke(GeometryUtils.scaleAndOffsetStroke(lineStroke, scale, scaledPhase)); if (lineColor != boxColor) g.setColor(lineColor); Rectangle2D rect2 = bounds2.getBounds2D(); g.draw(new Line2D.Double(rect.getCenterX(), rect.getCenterY(), rect2.getCenterX(), rect2.getCenterY())); } } @Override public Rectangle2D getBoundsInLocal() { return boundsInLocal; } private Rectangle2D calculateLocalBounds() { if (bounds1 == null || bounds2 == null) return null; Rectangle2D rect = bounds1.getBounds2D(); Rectangle2D rect2 = bounds2.getBounds2D(); double x1 = rect.getCenterX(); double x2 = rect2.getCenterX(); double y1 = rect.getCenterY(); double y2 = rect2.getCenterY(); double minx = Math.min(x1, x2); double maxx = Math.max(x1, x2); double miny = Math.min(y1, y2); double maxy = Math.max(y1, y2); return new Rectangle2D.Double(minx, miny, maxx - minx, maxy - miny); } }