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