]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/ScenegraphUtils.java
G2DParentNode handles "undefined" child bounds separately
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / ScenegraphUtils.java
1 /*******************************************************************************
2  * Copyright (c) 2012 Association for Decentralized Information Management in
3  * 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;
13
14 import java.awt.geom.AffineTransform;
15 import java.awt.geom.Rectangle2D;
16 import java.io.StringReader;
17 import java.lang.reflect.Method;
18 import java.util.HashMap;
19 import java.util.Map;
20 import java.util.UUID;
21
22 import org.simantics.databoard.Bindings;
23 import org.simantics.databoard.binding.Binding;
24 import org.simantics.databoard.binding.error.BindingException;
25 import org.simantics.databoard.binding.mutable.Variant;
26 import org.simantics.scenegraph.utils.BufferedImage;
27 import org.simantics.scl.runtime.function.Function1;
28 import org.simantics.scl.runtime.function.FunctionImpl1;
29 import org.simantics.utils.threads.IThreadWorkQueue;
30 import org.simantics.utils.threads.ThreadUtils;
31
32 import com.kitfox.svg.SVGDiagram;
33 import com.kitfox.svg.SVGException;
34 import com.kitfox.svg.SVGUniverse;
35
36 public class ScenegraphUtils {
37         
38         final static protected void dispatch(IThreadWorkQueue queue, final Runnable runnable) {
39                 if(queue == null) runnable.run();
40                 else if(queue.currentThreadAccess()) runnable.run();
41                 else {
42                         ThreadUtils.asyncExec(queue, new Runnable() {
43                                 @Override
44                                 public void run() {
45                                         runnable.run();
46                                 }
47                         });
48                 }
49         }
50         
51         private static Class<?> getPropertyType(Method method) {
52                 return (Class<?>)method.getGenericParameterTypes()[0]; 
53         }
54         
55         private static Binding getPropertyBinding(Method method) {
56                 try {
57                         return Bindings.getBindingUnchecked(getPropertyType(method));
58                 } catch (Throwable t) {
59                         return null;
60                 }
61         }
62         
63         private static Binding getGenericPropertyBinding(Method method) {
64                 try {
65                         Binding specific = getPropertyBinding(method);
66                         return Bindings.getBinding(specific.type());
67                 } catch (Throwable t) {
68                         return null;
69                 }
70         }
71
72         private static Method getSynchronizeMethod(Object node, String propertyName) {
73                 try {
74                         String methodName = "synchronize" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1);
75                         for(Method method : node.getClass().getMethods()) {
76                                 if(method.getName().equals(methodName)) return method;
77                         }
78                 } catch (SecurityException e) {
79                         e.printStackTrace();
80                 }
81                 return null;
82         }
83         
84         public static Function1<Object, Boolean> getMethodPropertyFunction(final IThreadWorkQueue queue, final Object node, final String propertyName) {
85                 
86                 final Method synchronizeMethod = getSynchronizeMethod(node, propertyName);
87                 if(synchronizeMethod == null) throw new NodeException("Did not find synchronize method for property '" + propertyName + "'");
88                 final Class<?> type = getPropertyType(synchronizeMethod);
89                 final Binding binding = getPropertyBinding(synchronizeMethod);
90                 final Binding genericBinding = getGenericPropertyBinding(synchronizeMethod);
91
92                 return new FunctionImpl1<Object, Boolean>() {
93
94                         @Override
95                         public Boolean apply(final Object value) {
96                                 
97                                 dispatch(queue, new Runnable() {
98
99                                         @Override
100                                         public void run() {
101                                                 
102                                                 try {
103                                                         if(type.isPrimitive()) {
104                                                                 synchronizeMethod.invoke(node, value);
105                                                         } else if (value == null) {
106                                                                 synchronizeMethod.invoke(node, value);
107                                                         } else if(type.isInstance(value)) {
108                                                                 synchronizeMethod.invoke(node, value);
109                                                         } else if (type.isArray()) {
110                                                                 synchronizeMethod.invoke(node, value);
111                                                         } else {
112                                                                 Object instance = binding.createDefaultUnchecked();
113                                                                 binding.readFrom(genericBinding, value, instance);
114                                                                 synchronizeMethod.invoke(node, instance);
115                                                         }
116                                                 } catch (IllegalArgumentException e1) {
117                                                         e1.printStackTrace();
118                                                 } catch (IllegalAccessException e1) {
119                                                         e1.printStackTrace();
120                                                 } catch (BindingException e) {
121                                                         e.printStackTrace();
122                                                 } catch (Throwable t) {
123                                                         t.printStackTrace();
124                                                 }
125                                         }
126                                         
127                                 });
128                                 return false;
129                         }
130
131                 };
132                 
133         }
134
135         public static SVGDiagram loadSVGDiagram(SVGUniverse univ, String text) throws SVGException {
136                 SVGDiagram diagram = univ.getDiagram(univ.loadSVG(new StringReader(text), UUID.randomUUID().toString()), false);
137                 diagram.setIgnoringClipHeuristic(true);
138                 return diagram;
139         }
140
141         public static java.awt.image.BufferedImage loadSVG(SVGUniverse univ, String text, double scale) throws SVGException {
142                 SVGDiagram diagram = loadSVGDiagram(univ, text);
143                 return paintSVG(diagram, scale);
144         }
145
146         public static java.awt.image.BufferedImage paintSVG(SVGDiagram diagram, double scale) throws SVGException {
147                 BufferedImage bi = new BufferedImage(diagram);
148                 bi.paintToBuffer(AffineTransform.getScaleInstance(scale, scale), 0);
149                 return bi.getBuffer();
150         }
151
152         public static java.awt.image.BufferedImage paintSVG(SVGDiagram diagram, AffineTransform transform, float margin) throws SVGException {
153                 BufferedImage bi = new BufferedImage(diagram);
154                 bi.paintToBuffer(transform, margin);
155                 return bi.getBuffer();
156         }
157
158         /*
159          * NOTE! This is not re-entrant
160          */
161         public static synchronized java.awt.image.BufferedImage loadSVG(SVGUniverse univ, String text, int maxDimension) throws SVGException {
162                 SVGDiagram diagram = univ.getDiagram(univ.loadSVG(new StringReader(text), UUID.randomUUID().toString()), false);
163                 diagram.setIgnoringClipHeuristic(true);
164                 BufferedImage bi = new BufferedImage(diagram);
165                 Rectangle2D bounds = diagram.getViewRect();
166                 double xScale = (double)maxDimension / bounds.getWidth();
167                 double yScale = (double)maxDimension / bounds.getHeight();
168                 double scale = Math.min(xScale, yScale);
169                 bi.paintToBuffer(AffineTransform.getScaleInstance(scale, scale), 0);
170                 return bi.getBuffer();
171         }
172         
173         private static Variant extractVariant(Object value) {
174                 if(value instanceof Variant) return (Variant)value;
175                 else return Variant.ofInstance(value);
176         }
177         
178         public static Map<String, Variant> parameters(Object ... keyValuePairs) {
179                 assert keyValuePairs.length % 2 == 0;
180                 HashMap<String, Variant> result = new HashMap<String, Variant>();
181                 for(int i=0;i<keyValuePairs.length;i+=2) {
182                         String key = (String)keyValuePairs[i];
183                         Variant value = extractVariant(keyValuePairs[i+1]);
184                         result.put(key,  value);
185                 }
186                 return result;
187         }
188         
189 }