From 63adbfeaca69de231d77724366647ecea9d74bd8 Mon Sep 17 00:00:00 2001 From: Marko Luukkainen Date: Wed, 8 Jul 2020 12:42:56 +0300 Subject: [PATCH] ShapeNode with separate stroke and fill paints gitlab #574 Change-Id: I49c640f925a2933b9c5f36255fad38ac54e1ad67 (cherry picked from commit f1e832f8b1172fd6370ae37f34461823f03adaa8) --- .../simantics/g2d/image/impl/ShapeImage.java | 23 ++- .../scenegraph/g2d/nodes/ShapeNode2.java | 191 ++++++++++++++++++ 2 files changed, 205 insertions(+), 9 deletions(-) create mode 100644 bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ShapeNode2.java diff --git a/bundles/org.simantics.g2d/src/org/simantics/g2d/image/impl/ShapeImage.java b/bundles/org.simantics.g2d/src/org/simantics/g2d/image/impl/ShapeImage.java index 77c65cb6e..90ceaa12a 100644 --- a/bundles/org.simantics.g2d/src/org/simantics/g2d/image/impl/ShapeImage.java +++ b/bundles/org.simantics.g2d/src/org/simantics/g2d/image/impl/ShapeImage.java @@ -21,7 +21,7 @@ import java.util.EnumSet; import org.simantics.g2d.image.Image; import org.simantics.scenegraph.Node; import org.simantics.scenegraph.g2d.G2DParentNode; -import org.simantics.scenegraph.g2d.nodes.ShapeNode; +import org.simantics.scenegraph.g2d.nodes.ShapeNode2; /** * @author Tuukka Lehtonen @@ -31,7 +31,8 @@ public class ShapeImage extends AbstractImage implements Image { private static final EnumSet defaultFeats = VECTOR; Shape shape; - Paint paint; + Paint fillPaint; + Paint strokePaint; Stroke stroke; EnumSet feats; boolean scaleStroke = false; @@ -41,16 +42,20 @@ public class ShapeImage extends AbstractImage implements Image { } public ShapeImage(Shape shape, Paint fill, Stroke stroke, boolean scaleStroke) { - this(shape, fill, stroke, scaleStroke, defaultFeats); + this(shape, fill, stroke, fill, scaleStroke, defaultFeats); } public ShapeImage(Shape shape, Paint fill, Stroke stroke, EnumSet features) { - this(shape, fill, stroke, false, features); + this(shape, fill, stroke, fill, false, features); + } + public ShapeImage(Shape shape, Paint fill, Stroke stroke, Paint strokeColor, boolean scaleStroke) { + this(shape, fill, stroke, strokeColor, scaleStroke, defaultFeats); } - public ShapeImage(Shape shape, Paint fill, Stroke stroke, boolean scaleStroke, EnumSet features) { + public ShapeImage(Shape shape, Paint fill, Stroke stroke, Paint strokeColor, boolean scaleStroke, EnumSet features) { this.shape = shape; - this.paint = fill; + this.fillPaint = fill; + this.strokePaint = strokeColor; this.stroke = stroke; this.scaleStroke = scaleStroke; this.feats = features; @@ -73,11 +78,11 @@ public class ShapeImage extends AbstractImage implements Image { @Override public Node init(G2DParentNode parent) { - ShapeNode shapeNode = parent.getOrCreateNode("ShapeImage", ShapeNode.class); + ShapeNode2 shapeNode = parent.getOrCreateNode("ShapeImage", ShapeNode2.class); shapeNode.setShape(shape); shapeNode.setStroke(stroke); - shapeNode.setFill(paint != null); - shapeNode.setColor(paint != null ? paint : Color.BLACK); + shapeNode.setFillColor(fillPaint); + shapeNode.setStrokeColor(strokePaint != null ? strokePaint : Color.BLACK); shapeNode.setScaleStroke(scaleStroke); return shapeNode; } diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ShapeNode2.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ShapeNode2.java new file mode 100644 index 000000000..2a8b9599a --- /dev/null +++ b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/ShapeNode2.java @@ -0,0 +1,191 @@ +/******************************************************************************* + * 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 +"]"; + } + +} -- 2.43.2