001: /*
002: *
003: * Copyright (c) 2007, Sun Microsystems, Inc.
004: *
005: * All rights reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * * Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * * Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: * * Neither the name of Sun Microsystems nor the names of its contributors
017: * may be used to endorse or promote products derived from this software
018: * without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031: */
032: package com.sun.perseus.demo;
033:
034: import java.io.IOException;
035: import java.io.InputStream;
036:
037: import javax.microedition.lcdui.*;
038: import javax.microedition.m2g.SVGAnimator;
039: import javax.microedition.m2g.SVGEventListener;
040: import javax.microedition.m2g.SVGImage;
041: import javax.microedition.m2g.ScalableGraphics;
042: import javax.microedition.midlet.*;
043:
044: import org.w3c.dom.Document;
045: import org.w3c.dom.svg.SVGSVGElement;
046:
047: /**
048: * Simple demo which plays an SVG animation, using the JSR 226
049: * SVGAnimator class.
050: */
051: public class PlaySVGImageDemo extends MIDlet implements
052: CommandListener, SVGEventListener {
053: /**
054: * The SVG Namespace URI.
055: */
056: public static final String SVG_NAMESPACE_URI = "http://www.w3.org/2000/svg";
057:
058: /**
059: * The minimal amount of time to wait when a splash screen is displayed.
060: */
061: public static final long SPLASH_MIN_LENGTH = 2500; // 2.5s
062:
063: /**
064: * State constants. These are used to track the animator's state.
065: */
066: public static final int STATE_STOPPED = 0;
067: public static final int STATE_PAUSED = 1;
068: public static final int STATE_PLAYING = 2;
069:
070: // indicates an interruption while in the playing state (for example by an
071: // incomming call)
072: public static final int STATE_INTERRUPTED = 3;
073:
074: /**
075: * Key codes used to control the animator's state.
076: */
077: public static final int KEY_STOP = Canvas.KEY_NUM0;
078: public static final int KEY_PLAY = Canvas.KEY_NUM5;
079: public static final int KEY_PAUSE = Canvas.KEY_NUM8;
080: public static final int KEY_START_DEMO = Canvas.KEY_NUM1;
081: public static final int KEY_ROTATE = Canvas.KEY_NUM7;
082: public static final int KEY_HELP = Canvas.KEY_NUM4;
083:
084: /**
085: * Error message thrown when the SVG resource could not be loaded.
086: */
087: public static final String ERROR_COULD_NOT_LOAD_SVG = "Error: Could not load SVG resource referenced by MIDlet : ";
088:
089: /**
090: * The SVG image played by this MIDlet is stored along the MIDlet's code.
091: */
092: public final String svgImageName;
093:
094: /**
095: * The optional splash image to show while the resources for the MIDlet are
096: * loading.
097: */
098: public final String splashImageName;
099:
100: /**
101: * This MIDlet has a single exit command to bo back to the previous menu.
102: */
103: private final Command exitCommand = new Command("Exit",
104: Command.EXIT, 1);
105:
106: /**
107: * The Canvas, managed by the SVGAnimator, where the SVG animation is
108: * displayed.
109: * @see #SVGAnimator.getTargetComponent();
110: */
111: protected Canvas svgCanvas;
112:
113: /**
114: * The splash Canvas. May be null.
115: */
116: protected Canvas splashCanvas;
117:
118: /**
119: * The SVGAnimator built from the SVG resource.
120: */
121: protected SVGAnimator svgAnimator;
122:
123: /**
124: * The SVGImage associated with the SVGAnimator
125: */
126: protected SVGImage svgImage;
127:
128: /**
129: * The Document associated with the SVGAnimator
130: */
131: protected Document doc;
132:
133: /**
134: * The root svg element.
135: */
136: protected SVGSVGElement svg;
137:
138: /**
139: * One of STATE_STOPPED, STATE_PAUSED, STATE_PLAYING or STATE_INTERRUPTED
140: */
141: protected int state = STATE_STOPPED;
142:
143: /**
144: * Indicates if the animation should be started automatically.
145: */
146: private boolean autoStart;
147:
148: public PlaySVGImageDemo(String svgImage, String splashImage,
149: boolean autoStart) {
150: this .svgImageName = svgImage;
151: this .splashImageName = splashImage;
152: this .autoStart = autoStart;
153: }
154:
155: public void startApp() {
156: if (svgCanvas == null) {
157: // If there is a splash screen defined, show it immediately.
158: boolean hasSplash = ((splashImageName != null) && !""
159: .equals(splashImageName));
160:
161: if (hasSplash) {
162: InputStream splashStream = getClass()
163: .getResourceAsStream(splashImageName);
164:
165: try {
166: Image splashImage = Image.createImage(splashStream);
167: splashCanvas = new SplashCanvas(splashImage);
168: } catch (IOException ioe) {
169: ioe.printStackTrace();
170: hasSplash = false;
171: }
172:
173: if (splashCanvas != null) {
174: Display.getDisplay(this ).setCurrent(splashCanvas);
175: }
176: }
177:
178: long start = System.currentTimeMillis();
179:
180: // Get input stream to the SVG image stored in the MIDlet's jar.
181: InputStream svgDemoStream = getClass().getResourceAsStream(
182: svgImageName);
183:
184: // Build an SVGImage instance from the stream
185: svgImage = null;
186:
187: if (svgDemoStream != null) {
188: try {
189: svgImage = (SVGImage) SVGImage.createImage(
190: svgDemoStream, null);
191: } catch (IOException io) {
192: io.printStackTrace();
193: }
194: }
195:
196: if (svgImage == null) {
197: throw new Error(ERROR_COULD_NOT_LOAD_SVG + svgImageName);
198: }
199:
200: // Build an SVGAnimator from the SVGImage. The SVGAnimator will handle
201: // all the animation details and run the SVG animation in a
202: // Canvas instance.
203: svgAnimator = SVGAnimator.createAnimator(svgImage);
204:
205: // Set to 10 fps (frames per second)
206: svgAnimator.setTimeIncrement(0.01f);
207:
208: // Get the Canvas managed by the SVGAnimator and set the
209: // svgImage's size to the canvas display area.
210: svgCanvas = (Canvas) svgAnimator.getTargetComponent();
211: svgImage.setViewportWidth(svgCanvas.getWidth());
212: svgImage.setViewportHeight(svgCanvas.getHeight());
213:
214: // Hook the exit command so that we can exit the animation demo.
215: svgCanvas.addCommand(exitCommand);
216: svgCanvas.setCommandListener(this );
217:
218: // The SVG root element is used to reset the time on a stop operation.
219: doc = svgImage.getDocument();
220: svg = (SVGSVGElement) doc.getDocumentElement();
221:
222: // Hook-in key listeners to play, pause and stop the animation.
223: svgAnimator.setSVGEventListener(this );
224:
225: long end = System.currentTimeMillis();
226:
227: if (hasSplash) {
228: long waitMore = SPLASH_MIN_LENGTH - (end - start);
229:
230: if (waitMore > 0) {
231: try {
232: Thread.currentThread().sleep(waitMore);
233: } catch (InterruptedException ie) {
234: // Do nothing.
235: }
236: }
237: }
238:
239: if (autoStart) {
240: svgAnimator.play();
241: state = STATE_PLAYING;
242: System.err.println("PLAYING...");
243: }
244: }
245:
246: Display.getDisplay(this ).setCurrent(svgCanvas);
247: resumeAnimation();
248: }
249:
250: public void keyPressed(int keyCode) {
251: if ((keyCode == KEY_PLAY) && (state != STATE_PLAYING)) {
252: svgAnimator.play();
253: state = STATE_PLAYING;
254: System.err.println("PLAYING...");
255: }
256:
257: if ((keyCode == KEY_PAUSE) && (state == STATE_PLAYING)) {
258: svgAnimator.pause();
259: state = STATE_PAUSED;
260: System.err.println("PAUSED...");
261: }
262:
263: if ((keyCode == KEY_STOP) && (state != STATE_STOPPED)) {
264: svgAnimator.stop();
265: svg.setCurrentTime(0);
266: state = STATE_STOPPED;
267: System.err.println("STOPPED...");
268: }
269: }
270:
271: public void keyReleased(int keyCode) {
272: }
273:
274: public void pointerPressed(int x, int y) {
275: }
276:
277: public void pointerReleased(int x, int y) {
278: }
279:
280: public void hideNotify() {
281: }
282:
283: public void showNotify() {
284: }
285:
286: public void sizeChanged(int width, int height) {
287: }
288:
289: public void pauseApp() {
290: interruptAnimation();
291: }
292:
293: public void destroyApp(boolean unconditional) {
294: if (state != STATE_STOPPED) {
295: svgAnimator.stop();
296: state = STATE_STOPPED;
297: }
298:
299: svgAnimator = null;
300: svgCanvas = null;
301: System.gc();
302: }
303:
304: public void commandAction(Command c, Displayable d) {
305: if (c == exitCommand) {
306: destroyApp(false);
307: notifyDestroyed();
308: }
309: }
310:
311: /**
312: * Pauses the animation if it is being played.
313: */
314: private void interruptAnimation() {
315: if (state == STATE_PLAYING) {
316: svgAnimator.pause();
317: state = STATE_INTERRUPTED;
318: }
319:
320: // Otherwise, the animation is paused or stopped.
321: }
322:
323: /**
324: * Resumes the animation if it has been interrupted in its playing state.
325: */
326: private void resumeAnimation() {
327: if (state == STATE_INTERRUPTED) {
328: // resume the interrupted animation
329: svgAnimator.play();
330: state = STATE_PLAYING;
331: }
332: }
333: }
|