1 /*******************************************************************************
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
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
10 * VTT Technical Research Centre of Finland - initial API and implementation
11 *******************************************************************************/
12 package org.simantics.scenegraph.g2d.nodes;
14 import java.awt.AlphaComposite;
15 import java.awt.BasicStroke;
16 import java.awt.Color;
17 import java.awt.Composite;
18 import java.awt.Graphics2D;
19 import java.awt.geom.AffineTransform;
20 import java.awt.geom.Rectangle2D;
22 import org.simantics.scenegraph.g2d.G2DNode;
23 import org.simantics.scenegraph.utils.GeometryUtils;
25 public class SelectionNode extends G2DNode implements Decoration {
29 private static final long serialVersionUID = -2879575230419873230L;
31 public transient static final BasicStroke SELECTION_STROKE = new BasicStroke(1.0f,
32 BasicStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE, 10.0f,
33 new float[] { 5.0f, 5.0f }, 0.0f);
35 protected Rectangle2D bounds = null;
36 protected Color color = null;
37 protected transient Rectangle2D rect;
38 protected transient BasicStroke scaledStroke;
39 protected transient double previousScaleRecip = Double.NaN;
40 protected boolean ignore = false;
41 protected double paddingFactor = 5.0;
42 protected int selectionId;
44 public int getSelectionId() {
48 public void setIgnore(boolean value) {
52 public void setPaddingFactor(double factor) {
53 paddingFactor = factor;
56 @SyncField({"transform", "bounds", "color"})
57 public void init(int selectionId, AffineTransform transform, Rectangle2D bounds, Color color) {
58 this.selectionId = selectionId;
59 this.transform = transform;
64 public void init(AffineTransform transform, Rectangle2D bounds, Color color) {
65 init(0, transform, bounds, color);
69 public void render(Graphics2D g) {
70 if (bounds == null) return;
74 // Prevent exceptions during rendering.
75 if (transform.getDeterminant() == 0)
78 AffineTransform ot = g.getTransform();
81 g.transform(transform);
83 AffineTransform tx = g.getTransform();
84 //System.out.println("tx: " + tx);
85 double scale = GeometryUtils.getScale(tx);
86 //System.out.println("scale: " + scale);
87 double scaleRecip = 1.0 / scale;
88 //System.out.println("scale: " + scaleRecip);
90 // Prevent stroke reallocation while panning.
91 // Zooming will trigger reallocation.
92 if (scaledStroke == null || scaleRecip != previousScaleRecip) {
93 scaledStroke = GeometryUtils.scaleStroke( SELECTION_STROKE, (float) scaleRecip);
94 previousScaleRecip = scaleRecip;
96 g.setStroke(scaledStroke);
98 double padding = paddingFactor * scaleRecip;
99 double paddingX = padding;
100 double paddingY = padding;
103 rect = new Rectangle2D.Double();
104 rect.setFrame(bounds.getMinX() - paddingX, bounds.getMinY() - paddingY,
105 bounds.getWidth() + 2.0*paddingX, bounds.getHeight() + 2.0*paddingY);
112 public Rectangle2D getRect() {
113 return transform.createTransformedShape(rect).getBounds2D();
117 public Rectangle2D getBoundsInLocal() {