1 /*******************************************************************************
\r
2 * Copyright (c) 2012 Association for Decentralized Information Management in
\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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.scenegraph;
\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
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
32 import com.kitfox.svg.SVGDiagram;
\r
33 import com.kitfox.svg.SVGException;
\r
34 import com.kitfox.svg.SVGUniverse;
\r
36 public class ScenegraphUtils {
\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
42 ThreadUtils.asyncExec(queue, new Runnable() {
\r
51 private static Class<?> getPropertyType(Method method) {
\r
52 return (Class<?>)method.getGenericParameterTypes()[0];
\r
55 private static Binding getPropertyBinding(Method method) {
\r
57 return Bindings.getBindingUnchecked(getPropertyType(method));
\r
58 } catch (Throwable t) {
\r
63 private static Binding getGenericPropertyBinding(Method method) {
\r
65 Binding specific = getPropertyBinding(method);
\r
66 return Bindings.getBinding(specific.type());
\r
67 } catch (Throwable t) {
\r
72 private static Method getSynchronizeMethod(Object node, String propertyName) {
\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
78 } catch (SecurityException e) {
\r
79 e.printStackTrace();
\r
84 public static Function1<Object, Boolean> getMethodPropertyFunction(final IThreadWorkQueue queue, final Object node, final String propertyName) {
\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
92 return new FunctionImpl1<Object, Boolean>() {
\r
95 public Boolean apply(final Object value) {
\r
97 dispatch(queue, new Runnable() {
\r
100 public void run() {
\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
112 Object instance = binding.createDefaultUnchecked();
\r
113 binding.readFrom(genericBinding, value, instance);
\r
114 synchronizeMethod.invoke(node, instance);
\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
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
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
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
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
159 * NOTE! This is not re-entrant
\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
173 private static Variant extractVariant(Object value) {
\r
174 if(value instanceof Variant) return (Variant)value;
\r
175 else return Variant.ofInstance(value);
\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