/******************************************************************************* * 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.BasicStroke; import java.awt.Color; import java.awt.Graphics2D; import java.awt.Paint; import java.awt.Shape; import java.awt.Stroke; import java.awt.geom.AffineTransform; import java.awt.geom.Rectangle2D; import org.simantics.scenegraph.g2d.G2DNode; import org.simantics.scenegraph.utils.GeometryUtils; import org.simantics.scenegraph.utils.InitValueSupport; /** * A scene graph node that renders a specified AWT {@link Shape} by optionally * filling or drawing it. * * This is similar to ShapeNode, but allows separate stroke and fill colors. * Due to API changes, I've done separate implementation. -MLuu * * * @author luukkainen * @author J-P Laine * @author Tuukka Lehtonen * */ public class ShapeNode2 extends G2DNode implements InitValueSupport { private static final long serialVersionUID = -5700299566608619380L; protected static final Stroke DEFAULT_STROKE = new BasicStroke(2); protected Shape shape = null; protected Stroke stroke = DEFAULT_STROKE; protected Paint strokeColor = Color.BLACK; protected Paint fillColor = null; protected boolean scaleStroke = false; protected boolean scaleShape = false; protected transient Shape dynamicShape = null; protected transient Stroke dynamicStroke = null; protected transient Paint dynamicStrokeColor = null; protected transient Paint dynamicFillColor = null; protected transient Boolean dynamicScaleStroke = null; protected transient Boolean dynamicScaleShape = null; @PropertySetter("shape") @SyncField("shape") public void setShape(Shape shape) { this.shape = shape; repaint(); } @PropertySetter("stroke") @SyncField("stroke") public void setStroke(Stroke stroke) { this.stroke = stroke; } @PropertySetter("strokeColor") @SyncField("strokeColor") public void setStrokeColor(Paint color) { this.strokeColor = color; } @PropertySetter("fillColor") @SyncField("fillColor") public void setFillColor(Paint color) { this.fillColor = color; } @SyncField("scaleStroke") public void setScaleStroke(boolean scaleStroke) { this.scaleStroke = scaleStroke; } @SyncField("scaleShape") public void setScaleShape(boolean scaleShape) { this.scaleShape = scaleShape; } @Override public void render(Graphics2D g2d) { Shape shape = dynamicShape != null ? dynamicShape : this.shape; if (shape == null) return; AffineTransform ot = setupRender(g2d); renderShape(g2d, shape); if (ot != null) g2d.setTransform(ot); } /** * @param g2d * @return current transform */ protected AffineTransform setupRender(Graphics2D g2d) { AffineTransform old = null; if (!transform.isIdentity()) { old = g2d.getTransform(); g2d.transform(transform); } boolean scaleShape = Boolean.TRUE.equals(dynamicScaleShape) ? true : this.scaleShape; if (scaleShape) { double xs = g2d.getTransform().getScaleX(); double ys = g2d.getTransform().getScaleY(); g2d.scale(1/xs, 1/ys); } return old; } protected void renderShape(Graphics2D g2d, Shape s) { Paint color = dynamicFillColor != null ? dynamicFillColor : this.fillColor; if (color != null) { g2d.setPaint(color); g2d.fill(s); } Stroke stroke = dynamicStroke != null ? dynamicStroke : this.stroke; if (stroke != null) { color = dynamicStrokeColor != null ? dynamicStrokeColor : this.strokeColor; if (color != null) g2d.setPaint(color); boolean scaleStroke = Boolean.TRUE.equals(dynamicScaleStroke) ? true : this.scaleStroke; if (scaleStroke && stroke instanceof BasicStroke) { BasicStroke bs = GeometryUtils.scaleStroke(stroke, (float) (1.0 / GeometryUtils.getScale(g2d.getTransform()))); g2d.setStroke(bs); } else { g2d.setStroke(stroke); } g2d.draw(s); } } @Override public Rectangle2D getBoundsInLocal() { if(shape == null) return null; return shape.getBounds2D(); } public void setValue(String key, Object value) { if ("shape".equals(key)) dynamicShape = (Shape) value; else if ("stroke".equals(key)) dynamicStroke = (Stroke) value; else if ("strokeColor".equals(key)) dynamicStrokeColor = (Paint) value; else if ("fillColor".equals(key)) dynamicFillColor = (Paint) value; else if ("scaleStroke".equals(key)) dynamicScaleStroke = (Boolean) value; else if ("scaleShape".equals(key)) dynamicScaleShape = (Boolean) value; // else super.setValue(key, value); } @Override public void initValues() { dynamicShape = null; dynamicStroke = null; dynamicStrokeColor = null; dynamicFillColor = null; dynamicScaleStroke = null; dynamicScaleShape = null; } @Override public String toString() { return super.toString() + " [shape=" + shape + ",color=" + strokeColor + ",fill=" + fillColor +"]"; } }