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