]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.diagram/src/org/simantics/diagram/elements/AnimatedSVGNode.java
Merge "Fixed Path2D creation to work with overlapping RoutePoints"
[simantics/platform.git] / bundles / org.simantics.diagram / src / org / simantics / diagram / elements / AnimatedSVGNode.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in 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.diagram.elements;
13
14 import java.awt.Graphics2D;
15 import java.awt.geom.Rectangle2D;
16 import java.io.ByteArrayInputStream;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.UUID;
22
23 import javax.script.ScriptEngine;
24 import javax.script.ScriptEngineManager;
25 import javax.script.ScriptException;
26
27 import org.simantics.g2d.elementclass.AnimatedNode;
28 import org.simantics.scenegraph.utils.BufferedImage;
29 import org.simantics.scenegraph.utils.G2DUtils;
30 import org.simantics.scenegraph.utils.MipMapBufferedImage;
31 import org.simantics.scenegraph.utils.MipMapVRamBufferedImage;
32 import org.simantics.scenegraph.utils.VRamBufferedImage;
33
34 import com.kitfox.svg.SVGCache;
35 import com.kitfox.svg.SVGElement;
36 import com.kitfox.svg.SVGException;
37 import com.kitfox.svg.SVGUniverse;
38 import com.kitfox.svg.xml.StyleAttribute;
39
40 public class AnimatedSVGNode extends SVGNode implements AnimatedNode {
41     /**
42      * 
43      */
44     private static final long serialVersionUID = 8698435757824280001L;
45     public Map<String, Object> valuezz = new HashMap<String, Object>();
46
47     protected String      script       = null;
48
49     @PropertySetter("VariableFilter")
50     @SyncField("script")
51     public void setScript(String script) {
52         this.script = script;
53     }
54
55     @SyncField("values")
56     public void setValue(String key, Object value) {
57         valuezz.put(key, value);
58         animate();
59     }
60     
61     @PropertySetter("valuezz")
62     @SyncField("valuezz")
63     public void setValuezz(Map<String, Object> val) {
64         valuezz = val;
65         animate();
66     }
67
68     @ClientSide
69     public void animate() {
70         animate(script);
71     }
72
73     @ClientSide
74     public void animate(final String script) {
75         if (script == null)
76             return;
77
78         if (dataHash == null) {
79             dataHash = parseSVG();
80         }
81         if (diagramCache == null) {
82             // Cannot execute script when SVGDiagram is not available
83             return;
84         }
85
86 //        AnimationExecutor.getInstance().animate(new IAnimation() {
87 //            @Override
88 //            public void run() {
89         try {
90
91             ScriptEngineManager manager = new ScriptEngineManager();
92             ScriptEngine engine = manager.getEngineByName("JavaScript");
93
94             for(String key : valuezz.keySet()) {
95                 engine.put(key, valuezz.get(key));
96             }
97             engine.put("time", System.currentTimeMillis());
98             engine.put("svg", diagramCache);
99             engine.put("t", AnimatedSVGNode.this);
100
101             //System.out.println("ANIMATE(" + engine.get("time") + ")");
102             engine.eval(script);
103
104             diagramCache.updateTime(0);
105
106             buffer = null;
107
108         } catch (ScriptException e) {
109             e.printStackTrace(); // Just report the error..
110         } catch (Throwable t) {
111             t.printStackTrace();
112         }
113
114 //            }
115 //        });
116     }
117
118     protected Map<String, String> eventAnimations = new HashMap<String, String>();
119
120     @ClientSide
121     public void registerEventAnimation(String event, String animation) {
122         eventAnimations.put(event, animation);
123     }
124
125     @ClientSide
126     public void animateEvent(String event) {
127         if(eventAnimations.containsKey(event)) {
128             animate(eventAnimations.get(event));
129         }
130     }
131
132     /**
133      * Use UUID hash
134      */
135     @Override
136     protected String parseSVG() {
137         if (data == null)
138             return null;
139         try {
140             dataHash = UUID.randomUUID().toString();
141             // NOTE: hard-coded to assume all SVG data is encoded in UTF-8
142             InputStream is = new ByteArrayInputStream(data.getBytes("UTF-8"));
143             SVGUniverse univ = SVGCache.getSVGUniverse();
144             if (diagramCache != null)
145                 univ.decRefCount(diagramCache.getXMLBase());
146             diagramCache = univ.getDiagram(SVGCache.getSVGUniverse().loadSVG(is, dataHash), false);
147             documentCache = data;
148             try {
149                 setBounds((Rectangle2D) diagramCache.getRoot().getBoundingBox().clone());
150             } catch (SVGException e) {
151                 setBounds((Rectangle2D) diagramCache.getViewRect().clone());
152             }
153             univ.incRefCount(diagramCache.getXMLBase());
154         } catch (IOException e) {
155             diagramCache = null;
156         }
157
158         return dataHash;
159     }
160
161     @SuppressWarnings("unused")
162     private void print(SVGElement e, int indent) {
163         for(int i=0;i<indent;i++) System.err.print(" ");
164         System.err.println(e);
165         for(int i=0;i<e.getNumChildren();i++) {
166             print(e.getChild(i), indent+2);
167         }
168         for(Object o : e.getPresentationAttributes()) {
169             for(int i=0;i<indent;i++) System.err.print(" ");
170             System.err.print("  " + o);
171             System.err.print("=");
172             StyleAttribute sa = e.getPresAbsolute((String)o);
173             System.err.println(sa.getStringValue());
174
175         }
176     }
177
178     /**
179      * ..skip buffering
180      */
181     @Override
182     protected void initBuffer(Graphics2D g2d) {
183         if (dataHash == null) {
184             dataHash = parseSVG();
185         }
186
187         if (diagramCache == null) {
188             System.out.println("UNABLE TO PARSE ANIMATED SVG:\n" + data);
189             return;
190         }
191
192         diagramCache.setIgnoringClipHeuristic(true); // FIXME
193         if (diagramCache.getViewRect().getWidth() == 0 || diagramCache.getViewRect().getHeight() == 0) {
194             buffer = null;
195         } else {
196             if(useMipMap) {
197                 if (G2DUtils.isAccelerated(g2d)) {
198                     buffer = new MipMapVRamBufferedImage(diagramCache, bounds, targetSize);
199                 } else {
200                     buffer = new MipMapBufferedImage(diagramCache, bounds, targetSize);
201                 }
202             } else {
203                 // FIXME: for some reason, this code causes effects where the graphics, if rotated, will start to pixelate, translate and completely disappear in the end.
204                 // See issue #2396.
205                 if (G2DUtils.isAccelerated(g2d)) {
206                     buffer = new VRamBufferedImage(diagramCache, bounds, targetSize);
207                 } else {
208                     buffer = new BufferedImage(diagramCache, bounds, targetSize);
209                 }
210             }
211         }
212     }
213
214 //    @Override
215 //    public void handleEvent(AWTEvent event) {
216 //        if(event.getID() == KeyEvent.KEY_PRESSED) {
217 //            KeyEvent ke = (KeyEvent)event;
218 //            switch(ke.getKeyCode()) {
219 //                case KeyEvent.VK_LEFT:
220 //                    animateEvent("LEFT");
221 //                    break;
222 //
223 //                case KeyEvent.VK_RIGHT:
224 //                    animateEvent("RIGHT");
225 //                    break;
226 //
227 //                case KeyEvent.VK_UP:
228 //                    animateEvent("UP");
229 //                    break;
230 //
231 //                case KeyEvent.VK_DOWN:
232 //                    animateEvent("DOWN");
233 //                    break;
234 //                default:
235 //                    break;
236 //            }
237 //        }
238 //
239 //        super.handleEvent(event);
240 //    }
241
242 }