]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SVGHolderNode.java
Fix RouteGraphNode styling
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / g2d / nodes / SVGHolderNode.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.Shape;
18 import java.awt.geom.AffineTransform;
19 import java.awt.geom.Rectangle2D;
20 import org.simantics.scenegraph.g2d.G2DParentNode;
21 import org.simantics.scenegraph.g2d.IG2DNode;
22
23 /**
24  * 
25  * Holder node that scales content to fit (and scales SVG inside those bounds)
26  * 
27  * @author jplaine
28  *
29  */
30 public class SVGHolderNode extends G2DParentNode {
31     /**
32      * 
33      */
34     private static final long serialVersionUID = 8698435757824280001L;
35
36     protected Rectangle2D bounds = null;
37     protected Float       borderWidth = null;
38     
39     
40     @PropertySetter("VariableFilter")
41     public void setScript(String script) {
42         for(IG2DNode node : getSortedNodes()) // Pass value to children
43                 if(node instanceof AnimatedSVGNode) {
44                         ((AnimatedSVGNode)node).setScript(script);
45                 }
46     }
47     
48     @PropertySetter("SVG")
49     public void setData(String data) {
50         for(IG2DNode node : getSortedNodes()) // Pass value to children
51                 if(node instanceof AnimatedSVGNode) {
52                         ((AnimatedSVGNode)node).setData(data);
53                 }
54     }
55
56     @PropertySetter("Stroke Width")
57     @SyncField("border")
58     public void setBorderWidth(Float borderWidth) {
59         this.borderWidth = borderWidth;
60     }
61
62     @PropertySetter("Bounds")
63     @SyncField("bounds")
64     public void setBounds(Rectangle2D bounds) {
65         this.bounds = bounds;
66     }
67
68     @Override
69     public void render(Graphics2D g2d) {
70         Rectangle2D cb = getBoundsInLocal(false);
71         double scaleX = bounds.getWidth() / cb.getWidth();
72         double scaleY = bounds.getHeight() / cb.getHeight();
73         double scale = Math.min(scaleX, scaleY);
74
75         if(borderWidth != null && borderWidth > 0.0f && bounds != null) {
76             Graphics2D g2 = (Graphics2D)g2d.create();
77             g2.transform(transform);
78             g2.setStroke(new BasicStroke(this.borderWidth));
79             g2.setColor(Color.BLACK);
80             g2.draw(bounds);
81             g2.dispose();
82         }
83
84         @SuppressWarnings("unused")
85         int noBounds = 0;
86         @SuppressWarnings("unused")
87         int clipped = 0;
88         @SuppressWarnings("unused")
89         int rendered = 0;
90
91         AffineTransform ot = g2d.getTransform();
92         g2d.transform(transform);
93
94         g2d.translate(-cb.getMinX()*scale+bounds.getMinX(), -cb.getMinY()*scale+bounds.getMinY());
95         g2d.scale(scale, scale);
96
97         // Get transformed clip bounds
98         Shape clipShape = g2d.getClip();
99         Rectangle2D bounds = null;
100         if (clipShape instanceof Rectangle2D)
101             bounds = (Rectangle2D) clipShape;
102         else if (clipShape != null)
103             bounds = clipShape.getBounds2D();
104
105         boolean noClipBounds = bounds == null;
106
107         for(IG2DNode node : getSortedNodes()) {
108             Rectangle2D localBounds = node.getBoundsInLocal();
109             boolean hasNoBounds = localBounds == null;
110             boolean visible = false;
111             if (!noClipBounds && !hasNoBounds) {
112                 visible = node.intersects(bounds);
113             } else {
114                 ++noBounds;
115             }
116             if (noClipBounds || hasNoBounds || visible) {
117                 // TODO: consider removing this g2d.create ?
118                 // Will definitely current cause bugs to appear.
119                 if (node.validate()) {
120                     node.render(g2d);
121                 }
122                 ++rendered;
123             } else {
124                 ++clipped;
125             }
126         }
127
128         g2d.setTransform(ot);
129     }
130
131     @Override
132     public Rectangle2D getBoundsInLocal() {
133         return bounds; // FIXME: not sure if it's a good idea to return different value than the getBoundsInLocal(boolean nulls) returns..
134     }
135
136 }