]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/g2d/nodes/SingleElementNode.java
G2DParentNode handles "undefined" child bounds separately
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / g2d / nodes / SingleElementNode.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.AlphaComposite;
15 import java.awt.Composite;
16 import java.awt.Graphics2D;
17 import java.awt.geom.Point2D;
18 import java.awt.geom.Rectangle2D;
19 import java.util.Map;
20
21 import org.simantics.scenegraph.INode;
22 import org.simantics.scenegraph.g2d.G2DRenderingHints;
23 import org.simantics.scenegraph.g2d.IG2DNode;
24 import org.simantics.scenegraph.g2d.events.EventTypes;
25 import org.simantics.scenegraph.g2d.events.MouseEvent;
26 import org.simantics.scenegraph.g2d.events.MouseEvent.MouseDragBegin;
27 import org.simantics.scenegraph.utils.InitValueSupport;
28 import org.simantics.scenegraph.utils.NodeUtil;
29
30 public class SingleElementNode extends TransformNode implements InitValueSupport {
31
32     private static final long serialVersionUID = -4982578347433716440L;
33
34     private TransferableProvider transferableProvider;
35     protected Composite composite;
36     protected Boolean visible = Boolean.TRUE;
37     protected Boolean hidden = Boolean.FALSE;
38     private transient Object key;
39     private transient String typeClass;
40     private transient Map<String, Object> parameters;
41
42     public void setKey(Object key) {
43         this.key = key;
44     }
45
46     public void setTypeClass(String typeClass) {
47         this.typeClass = typeClass;
48     }
49
50     public Object getKey() {
51         return key;
52     }
53
54     public String getTypeClass() {
55         return typeClass;
56     }
57
58     public void setParameters(Map<String,Object> parameters) {
59         this.parameters = parameters;
60     }
61
62     public <T> T getParameter(String key) {
63         if (parameters != null) {
64             @SuppressWarnings("unchecked")
65             T t = (T) parameters.get(key);
66             if(t != null) return t;
67         }
68         INode parent = NodeUtil.getNearestParentOfType(this, SingleElementNode.class);
69         if (parent instanceof SingleElementNode) {
70             return ((SingleElementNode)parent).getParameter(key);
71         }
72         return null;
73     }
74
75     public void setTransferableProvider(TransferableProvider transferableProvider) {
76         if (transferableProvider != this.transferableProvider) {
77             if (this.transferableProvider != null)
78                 removeEventHandler(this);
79             if (transferableProvider != null)
80                 addEventHandler(this);
81             this.transferableProvider = transferableProvider;
82         }
83     }
84
85     @Override
86     public boolean validate() {
87         return visible && !hidden;
88     }
89
90     @SyncField("composite")
91     public void setComposite(Composite composite) {
92         this.composite = composite;
93     }
94
95     @SyncField("visible")
96     public void setVisible(Boolean visible) {
97         this.visible = visible;
98     }
99
100     public boolean isVisible() {
101         return visible;
102     }
103
104     @SyncField("hidden")
105     public void setHidden(Boolean hidden) {
106         this.hidden = hidden;
107     }
108
109     public boolean isHidden() {
110         return hidden;
111     }
112
113     @Override
114     public void render(Graphics2D g) {
115         if (!visible || hidden)
116             return;
117
118         Composite oldComposite = null;
119         if(composite != null) {
120             oldComposite = g.getComposite();
121             g.setComposite(composite);
122         }
123         if(alphaComposite != null) {
124             if (oldComposite == null)
125                 oldComposite = g.getComposite();
126             g.setComposite(alphaComposite);
127         }
128
129         super.render(g);
130
131         if (oldComposite != null)
132             g.setComposite(oldComposite);
133     }
134
135     @Override
136     public String toString() {
137         StringBuilder sb = new StringBuilder();
138         sb.append(super.toString());
139         sb.append(" [");
140         if (composite != null) {
141             sb.append("composite=(");
142             AlphaComposite ac = (AlphaComposite) composite;
143             sb.append(ac.getRule());
144             sb.append(", ");
145             sb.append(ac.getAlpha());
146             sb.append("), ");
147         }
148         sb.append("visible=");
149         sb.append(visible);
150         sb.append("]");
151         return sb.toString();
152     }
153
154     protected Composite alphaComposite = null;
155
156     @PropertySetter("alpha")
157     @SyncField("alphaComposite")
158     public void setAlphaComposite(Composite alphaComposite) {
159         this.alphaComposite = alphaComposite;
160     }
161
162     @Override
163     public void initValues() {
164         alphaComposite = null;
165         for (IG2DNode node : getSortedNodes()) {
166             if (node instanceof InitValueSupport) {
167                 ((InitValueSupport) node).initValues();
168             }
169         }
170     }
171
172     @Override
173     public void cleanup() {
174         if (transferableProvider != null) {
175             removeEventHandler(this);
176             transferableProvider = null;
177         }
178         super.cleanup();
179     }
180
181     protected boolean isDragStartEvent(MouseEvent e) {
182         return e.isControlDown();
183     }
184
185     protected boolean hitTest(MouseEvent event) {
186         Rectangle2D bounds = super.getBoundsInLocal(true);
187         if (bounds == null)
188             return false;
189         Point2D localPos = NodeUtil.worldToLocal(this, event.controlPosition, new Point2D.Double());
190         double x = localPos.getX();
191         double y = localPos.getY();
192         boolean hit = bounds.contains(x, y);
193         return hit;
194     }
195
196     @Override
197     protected boolean mouseDragged(MouseDragBegin e) {
198         if (transferableProvider == null
199                 || !isDragStartEvent(e)
200                 || !hitTest(e))
201             return false;
202         e.transferable = transferableProvider.create();
203         return e.transferable != null;
204     }
205
206     @Override
207     public int getEventMask() {
208         return EventTypes.MouseDragBeginMask;
209     }
210
211     public void beforeRender(Graphics2D g) {
212         g.setRenderingHint(G2DRenderingHints.KEY_BEGIN_ELEMENT, "definedElement");
213     }
214
215     public void afterRender(Graphics2D g) {
216         g.setRenderingHint(G2DRenderingHints.KEY_END_ELEMENT, "definedElement");
217     }
218
219 }