]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SelectionNode.java
Customisable selection padding on diagrams
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / g2d / nodes / SelectionNode.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
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
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.scenegraph.g2d.nodes;
13
14 import java.awt.BasicStroke;
15 import java.awt.Color;
16 import java.awt.Graphics2D;
17 import java.awt.geom.AffineTransform;
18 import java.awt.geom.Rectangle2D;
19
20 import org.simantics.scenegraph.g2d.G2DNode;
21 import org.simantics.scenegraph.utils.GeometryUtils;
22
23 public class SelectionNode extends G2DNode implements Decoration {
24     /**
25      * 
26      */
27     private static final long serialVersionUID = -2879575230419873230L;
28
29     public transient static final BasicStroke SELECTION_STROKE = new BasicStroke(1.0f,
30             BasicStroke.CAP_SQUARE, BasicStroke.CAP_SQUARE, 10.0f,
31             new float[] { 5.0f, 5.0f }, 0.0f);
32
33     protected Rectangle2D bounds = null;
34     protected Color color = null;
35     protected transient Rectangle2D rect;
36     protected transient BasicStroke scaledStroke;
37     protected transient double previousScaleRecip = Double.NaN;
38     private boolean ignore = false;
39     private double paddingFactor = 5.0;
40
41     public void setIgnore(boolean value) {
42         ignore = value;
43     }
44     
45     public void setPaddingFactor(double factor) {
46         paddingFactor = factor;
47     }
48   
49     @SyncField({"transform", "bounds", "color"})
50     public void init(AffineTransform transform, Rectangle2D bounds, Color color) {
51         this.transform = transform;
52         this.bounds = bounds;
53         this.color = color;
54     }
55
56     @Override
57     public void render(Graphics2D g) {
58         if (bounds == null) return;
59         
60         if (ignore) return;
61
62         // Prevent exceptions during rendering.
63         if (transform.getDeterminant() == 0)
64             return;
65
66         AffineTransform ot = g.getTransform();
67
68         g.setColor(color);
69         g.transform(transform);
70
71         AffineTransform tx = g.getTransform();
72         //System.out.println("tx: " + tx);
73         double scale = GeometryUtils.getScale(tx);
74         //System.out.println("scale: " + scale);
75         double scaleRecip = 1.0 / scale;
76         //System.out.println("scale: " + scaleRecip);
77
78         // Prevent stroke reallocation while panning.
79         // Zooming will trigger reallocation.
80         if (scaledStroke == null || scaleRecip != previousScaleRecip) {
81             scaledStroke = GeometryUtils.scaleStroke( SELECTION_STROKE, (float) scaleRecip);
82             previousScaleRecip = scaleRecip;
83         }
84         g.setStroke(scaledStroke);
85
86         double padding = paddingFactor * scaleRecip;
87         double paddingX = padding;
88         double paddingY = padding;
89
90         if (rect == null)
91             rect = new Rectangle2D.Double();
92         rect.setFrame(bounds.getMinX() - paddingX, bounds.getMinY() - paddingY,
93                 bounds.getWidth() + 2.0*paddingX, bounds.getHeight() + 2.0*paddingY);
94         g.draw(rect);
95         
96         g.setTransform(ot);
97
98     }
99     
100     public Rectangle2D getRect() {
101         return transform.createTransformedShape(rect).getBounds2D();
102     }
103
104     @Override
105     public Rectangle2D getBoundsInLocal() {
106         return bounds;
107     }
108 }