1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in 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
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.scenegraph.g2d.nodes;
\r
14 import java.awt.Graphics2D;
\r
15 import java.awt.geom.Rectangle2D;
\r
16 import java.io.ByteArrayInputStream;
\r
17 import java.io.IOException;
\r
18 import java.io.InputStream;
\r
19 import java.util.HashMap;
\r
20 import java.util.Map;
\r
21 import java.util.UUID;
\r
23 import javax.script.ScriptEngine;
\r
24 import javax.script.ScriptEngineManager;
\r
25 import javax.script.ScriptException;
\r
27 import org.simantics.scenegraph.utils.BufferedImage;
\r
28 import org.simantics.scenegraph.utils.G2DUtils;
\r
29 import org.simantics.scenegraph.utils.MipMapBufferedImage;
\r
30 import org.simantics.scenegraph.utils.MipMapVRamBufferedImage;
\r
31 import org.simantics.scenegraph.utils.VRamBufferedImage;
\r
33 import com.kitfox.svg.SVGCache;
\r
34 import com.kitfox.svg.SVGElement;
\r
35 import com.kitfox.svg.SVGException;
\r
36 import com.kitfox.svg.SVGUniverse;
\r
37 import com.kitfox.svg.xml.StyleAttribute;
\r
39 public class AnimatedSVGNode extends SVGNode {
\r
43 private static final long serialVersionUID = 8698435757824280001L;
\r
44 public Map<String, Object> valuezz = new HashMap<String, Object>();
\r
46 protected String script = null;
\r
48 @PropertySetter("VariableFilter")
\r
49 @SyncField("script")
\r
50 public void setScript(String script) {
\r
51 this.script = script;
\r
54 @SyncField("values")
\r
55 public void setValue(String key, Object value) {
\r
56 valuezz.put(key, value);
\r
60 @PropertySetter("valuezz")
\r
61 @SyncField("valuezz")
\r
62 public void setValuezz(Map<String, Object> val) {
\r
68 public void animate() {
\r
73 public void animate(final String script) {
\r
77 if (dataHash == null) {
\r
78 dataHash = parseSVG();
\r
80 if (diagramCache == null) {
\r
81 // Cannot execute script when SVGDiagram is not available
\r
85 // AnimationExecutor.getInstance().animate(new IAnimation() {
\r
87 // public void run() {
\r
90 ScriptEngineManager manager = new ScriptEngineManager();
\r
91 ScriptEngine engine = manager.getEngineByName("JavaScript");
\r
93 for(String key : valuezz.keySet()) {
\r
94 engine.put(key, valuezz.get(key));
\r
96 engine.put("time", System.currentTimeMillis());
\r
97 engine.put("svg", diagramCache);
\r
98 engine.put("t", AnimatedSVGNode.this);
\r
100 //System.out.println("ANIMATE(" + engine.get("time") + ")");
\r
101 engine.eval(script);
\r
103 diagramCache.updateTime(0);
\r
107 } catch (ScriptException e) {
\r
108 e.printStackTrace(); // Just report the error..
\r
109 } catch (Throwable t) {
\r
110 t.printStackTrace();
\r
117 protected Map<String, String> eventAnimations = new HashMap<String, String>();
\r
120 public void registerEventAnimation(String event, String animation) {
\r
121 eventAnimations.put(event, animation);
\r
125 public void animateEvent(String event) {
\r
126 if(eventAnimations.containsKey(event)) {
\r
127 animate(eventAnimations.get(event));
\r
135 protected String parseSVG() {
\r
139 dataHash = UUID.randomUUID().toString();
\r
140 // NOTE: hard-coded to assume all SVG data is encoded in UTF-8
\r
141 InputStream is = new ByteArrayInputStream(data.getBytes("UTF-8"));
\r
142 SVGUniverse univ = SVGCache.getSVGUniverse();
\r
143 if (diagramCache != null)
\r
144 univ.decRefCount(diagramCache.getXMLBase());
\r
145 diagramCache = univ.getDiagram(SVGCache.getSVGUniverse().loadSVG(is, dataHash), false);
\r
146 documentCache = data;
\r
148 setBounds((Rectangle2D) diagramCache.getRoot().getBoundingBox().clone());
\r
149 } catch (SVGException e) {
\r
150 setBounds((Rectangle2D) diagramCache.getViewRect().clone());
\r
152 univ.incRefCount(diagramCache.getXMLBase());
\r
153 } catch (IOException e) {
\r
154 diagramCache = null;
\r
160 @SuppressWarnings("unused")
\r
161 private void print(SVGElement e, int indent) {
\r
162 for(int i=0;i<indent;i++) System.err.print(" ");
\r
163 System.err.println(e);
\r
164 for(int i=0;i<e.getNumChildren();i++) {
\r
165 print(e.getChild(i), indent+2);
\r
167 for(Object o : e.getPresentationAttributes()) {
\r
168 for(int i=0;i<indent;i++) System.err.print(" ");
\r
169 System.err.print(" " + o);
\r
170 System.err.print("=");
\r
171 StyleAttribute sa = e.getPresAbsolute((String)o);
\r
172 System.err.println(sa.getStringValue());
\r
181 protected void initBuffer(Graphics2D g2d) {
\r
182 if (dataHash == null) {
\r
183 dataHash = parseSVG();
\r
186 if (diagramCache == null) {
\r
187 System.out.println("UNABLE TO PARSE ANIMATED SVG:\n" + data);
\r
191 diagramCache.setIgnoringClipHeuristic(true); // FIXME
\r
192 if (diagramCache.getViewRect().getWidth() == 0 || diagramCache.getViewRect().getHeight() == 0) {
\r
196 if (G2DUtils.isAccelerated(g2d)) {
\r
197 buffer = new MipMapVRamBufferedImage(diagramCache, bounds, targetSize);
\r
199 buffer = new MipMapBufferedImage(diagramCache, bounds, targetSize);
\r
202 // FIXME: for some reason, this code causes effects where the graphics, if rotated, will start to pixelate, translate and completely disappear in the end.
\r
203 // See issue #2396.
\r
204 if (G2DUtils.isAccelerated(g2d)) {
\r
205 buffer = new VRamBufferedImage(diagramCache, bounds, targetSize);
\r
207 buffer = new BufferedImage(diagramCache, bounds, targetSize);
\r
214 // public void handleEvent(AWTEvent event) {
\r
215 // if(event.getID() == KeyEvent.KEY_PRESSED) {
\r
216 // KeyEvent ke = (KeyEvent)event;
\r
217 // switch(ke.getKeyCode()) {
\r
218 // case KeyEvent.VK_LEFT:
\r
219 // animateEvent("LEFT");
\r
222 // case KeyEvent.VK_RIGHT:
\r
223 // animateEvent("RIGHT");
\r
226 // case KeyEvent.VK_UP:
\r
227 // animateEvent("UP");
\r
230 // case KeyEvent.VK_DOWN:
\r
231 // animateEvent("DOWN");
\r
238 // super.handleEvent(event);
\r