/******************************************************************************* * 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.geom.AffineTransform; import java.awt.geom.Rectangle2D; import org.simantics.scenegraph.g2d.G2DNode; import org.simantics.scenegraph.utils.GeometryUtils; public class SelectionNode extends G2DNode implements Decoration { /** * */ private static final long serialVersionUID = -2879575230419873230L; public transient static final BasicStroke SELECTION_STROKE = new BasicStroke(1.0f, BasicStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE, 10.0f, new float[] { 5.0f, 5.0f }, 0.0f); protected Rectangle2D bounds = null; protected Color color = null; protected transient Rectangle2D rect; protected transient BasicStroke scaledStroke; protected transient double previousScaleRecip = Double.NaN; @SyncField({"transform", "bounds", "color"}) public void init(AffineTransform transform, Rectangle2D bounds, Color color) { this.transform = transform; this.bounds = bounds; this.color = color; } @Override public void render(Graphics2D g) { if (bounds == null) return; // Prevent exceptions during rendering. if (transform.getDeterminant() == 0) return; AffineTransform ot = g.getTransform(); g.setColor(color); g.transform(transform); AffineTransform tx = g.getTransform(); //System.out.println("tx: " + tx); double scale = GeometryUtils.getScale(tx); //System.out.println("scale: " + scale); double scaleRecip = 1.0 / scale; //System.out.println("scale: " + scaleRecip); // Prevent stroke reallocation while panning. // Zooming will trigger reallocation. if (scaledStroke == null || scaleRecip != previousScaleRecip) { scaledStroke = GeometryUtils.scaleStroke( SELECTION_STROKE, (float) scaleRecip); previousScaleRecip = scaleRecip; } g.setStroke(scaledStroke); double padding = 5.0 * scaleRecip; double paddingX = padding; double paddingY = padding; if (rect == null) rect = new Rectangle2D.Double(); rect.setFrame(bounds.getMinX() - paddingX, bounds.getMinY() - paddingY, bounds.getWidth() + 2.0*paddingX, bounds.getHeight() + 2.0*paddingY); g.draw(rect); g.setTransform(ot); } @Override public Rectangle2D getBoundsInLocal() { return bounds; } }