0001: /*
0002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
0003: *
0004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
0005: *
0006: * The contents of this file are subject to the terms of either the GNU
0007: * General Public License Version 2 only ("GPL") or the Common
0008: * Development and Distribution License("CDDL") (collectively, the
0009: * "License"). You may not use this file except in compliance with the
0010: * License. You can obtain a copy of the License at
0011: * http://www.netbeans.org/cddl-gplv2.html
0012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
0013: * specific language governing permissions and limitations under the
0014: * License. When distributing the software, include this License Header
0015: * Notice in each file and include the License file at
0016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
0017: * particular file as subject to the "Classpath" exception as provided
0018: * by Sun in the GPL Version 2 section of the License file that
0019: * accompanied this code. If applicable, add the following below the
0020: * License Header, with the fields enclosed by brackets [] replaced by
0021: * your own identifying information:
0022: * "Portions Copyrighted [year] [name of copyright owner]"
0023: *
0024: * Contributor(s):
0025: *
0026: * The Original Software is NetBeans. The Initial Developer of the Original
0027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
0028: * Microsystems, Inc. All Rights Reserved.
0029: *
0030: * If you wish your version of this file to be governed by only the CDDL
0031: * or only the GPL Version 2, indicate your decision by adding
0032: * "[Contributor] elects to include this software in this distribution
0033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
0034: * single choice of license, a recipient has the option to distribute
0035: * your version of this file under either the CDDL, the GPL Version 2 or
0036: * to extend the choice of license to its licensees as provided above.
0037: * However, if you add GPL Version 2 code and therefore, elected the GPL
0038: * Version 2 license, then the option applies only if the new code is
0039: * made subject to such option by the copyright holder.
0040: */
0041:
0042: /*
0043: * SVGPlayer.java
0044: *
0045: * Created on June 15, 2007
0046: *
0047: */
0048:
0049: package org.netbeans.microedition.svg;
0050:
0051: import javax.microedition.lcdui.Canvas;
0052: import javax.microedition.lcdui.Command;
0053: import javax.microedition.lcdui.CommandListener;
0054: import javax.microedition.lcdui.Display;
0055: import javax.microedition.lcdui.Displayable;
0056: import javax.microedition.lcdui.Graphics;
0057: import javax.microedition.lcdui.Ticker;
0058: import javax.microedition.m2g.SVGAnimator;
0059: import javax.microedition.m2g.SVGEventListener;
0060: import javax.microedition.m2g.SVGImage;
0061: import org.w3c.dom.Document;
0062: import org.w3c.dom.Element;
0063: import org.w3c.dom.svg.SVGAnimationElement;
0064: import org.w3c.dom.svg.SVGElement;
0065: import org.w3c.dom.svg.SVGLocatableElement;
0066: import org.w3c.dom.svg.SVGMatrix;
0067: import org.w3c.dom.svg.SVGRGBColor;
0068: import org.w3c.dom.svg.SVGRect;
0069: import org.w3c.dom.svg.SVGSVGElement;
0070:
0071: /**
0072: *
0073: *
0074: * This class encapsulates SVGAnimator and exposes some of its setters,
0075: * so it can be used as a component in NetBeans Visual Designer.
0076: * It also adds many utility methods which can be used
0077: * to easily manipulate the underlying document of the animated SVG image.
0078: *
0079: * <p>
0080: * Even though this class extends Canvas, the Canvas is utilized only
0081: * for forwarding command actions from Canvas created by SVGAnimator.
0082: * @author breh
0083: */
0084: public class SVGPlayer extends Canvas implements CommandListener { // need to use canvas, because of
0085: // forwarding command actions
0086:
0087: /**
0088: * Anchor point constants.
0089: */
0090: public static final int TOP_LEFT = 0, TOP = 1, TOP_RIGHT = 2,
0091: LEFT = 3, CENTER = 4, RIGHT = 5, BOTTOM_LEFT = 6,
0092: BOTTOM = 7, BOTTOM_RIGHT = 8;
0093:
0094: /**
0095: * Animator is stopped (i.e. when started again, the animation
0096: * will start from the beginning)
0097: */
0098: public static final int STOPPED = 0;
0099:
0100: /**
0101: * Animator is paused (i.e. when started again, the animation will
0102: * continue from the paused state)
0103: */
0104: public static final int PAUSED = 1;
0105:
0106: /**
0107: * Animator is running animation
0108: */
0109: public static final int PLAYING = 2;
0110:
0111: // svg image to be animated
0112: private final SVGImage svgImage;
0113: // the actual canvas created by the animator
0114: private final Canvas animatorCanvas;
0115: // SVG animator
0116: private final SVGAnimator animator;
0117: // display
0118: private final Display display;
0119:
0120: // command listener used for forwarding actions
0121: private CommandListener commandListener;
0122: // user's SVGEventListener
0123: private SVGEventListener userSvgEventListener;
0124: // a user's SVGEventListener to be called in the update thread.
0125: private SVGEventListener safeSvgEventListener;
0126:
0127: // boolean property for starting animation automatically
0128: private boolean startAnimation;
0129: // boolean property determing whether animation should be reset when stopped
0130: // (e.g. when the displayable with animation is dismissed)
0131: private boolean resetAnimationWhenStopped;
0132: // property hodling animator state
0133: private int animatorState = STOPPED;
0134: // flag determining whether animation needs reset before startinh again (used with compo
0135: private boolean animationNeedsReset;
0136:
0137: // current document update thread, if null, there is no update thread
0138: private Thread documentUpdateThread;
0139:
0140: // The associated document instance.
0141: private final Document doc;
0142:
0143: // The associated root svg element
0144: private final SVGSVGElement svg;
0145:
0146: // reset the animation runnable
0147: private Runnable resetAnimationRunnable = new Runnable() {
0148: public void run() {
0149: SVGSVGElement svg = (SVGSVGElement) getSVGImage()
0150: .getDocument().getDocumentElement();
0151: svg.setCurrentTime(0f);
0152: }
0153: };
0154:
0155: /**
0156: * Creates a new instance of SvgAnimatorHelper. It requires SVGImage to be animated
0157: * and display.
0158: *
0159: * <p/> Please note, supplied SVGImage shouldn't be reused in other SVGAnimator.
0160: */
0161: public SVGPlayer(SVGImage svgImage, Display display)
0162: throws IllegalArgumentException {
0163: if (svgImage == null) {
0164: throw new IllegalArgumentException(
0165: "svgImage parameter cannot be null");
0166: }
0167: if (display == null) {
0168: throw new IllegalArgumentException(
0169: "display parameter cannot be null");
0170: }
0171: this .animatorState = STOPPED;
0172: this .svgImage = svgImage;
0173: this .display = display;
0174: this .animator = SVGAnimator.createAnimator(svgImage);
0175: this .animatorCanvas = (Canvas) animator.getTargetComponent();
0176: // this sets the size of the image,but we should be somehow able
0177: // to track sizeChanged event !!! - this is not possible so far !!!!
0178: this .svgImage.setViewportWidth(this .animatorCanvas.getWidth());
0179: this .svgImage
0180: .setViewportHeight(this .animatorCanvas.getHeight());
0181: // sets the command listener to be this component
0182: this .animatorCanvas.setCommandListener(this );
0183: // set the svg listener
0184: this .animator
0185: .setSVGEventListener(new WrapperSvgEventListener());
0186: this .setStartAnimationImmediately(true);
0187: this .setResetAnimationWhenStopped(true);
0188:
0189: // get document and root svg element
0190: this .doc = svgImage.getDocument();
0191: this .svg = (SVGSVGElement) doc.getDocumentElement();
0192: }
0193:
0194: /**
0195: * Gets Canvas which was created by the SVGAnimator
0196: */
0197: public Canvas getSvgCanvas() {
0198: return animatorCanvas;
0199: }
0200:
0201: /**
0202: * Gets user's SVGEventListener
0203: * @return an instance of the user's SVGEventListener or null if there was no user SVGEvenetListener set.
0204: */
0205: public SVGEventListener getSVGEventListener() {
0206: return userSvgEventListener;
0207: }
0208:
0209: /**
0210: * Sets a user's SVGEventListener to the SVGAnimator
0211: * @param svgEventListener user SVGEventListener or null if no listener should be set
0212: */
0213: public void setSVGEventListener(SVGEventListener svgEventListener) {
0214: this .userSvgEventListener = svgEventListener;
0215: }
0216:
0217: /**
0218: * Gets user's "Safe" SVGEventListener which is being called in the
0219: * document update thread.
0220: * @return an instance of the user's SVGEventListener being called in the document update thread,
0221: * or null if there was no user SVGEvenetListener set.
0222: */
0223: public SVGEventListener getSafeSVGEventListener() {
0224: return userSvgEventListener;
0225: }
0226:
0227: /**
0228: * Sets a user's SVGEventListener to be called in the document update
0229: * thread.
0230: * @param safeSvgEventListener user SVGEventListener or null if no listener should be set
0231: */
0232: public void setSafeSVGEventListener(
0233: SVGEventListener safeSvgEventListener) {
0234: this .safeSvgEventListener = safeSvgEventListener;
0235: }
0236:
0237: /**
0238: * Sets time increment for the animation. Proxy call for
0239: * SVGAnimator.setTimeIncrement()
0240: * @param timeIncrement the minimal time that should ellapse between frame rendering. In seconds. Should be greater than zero.
0241: * @throws java.lang.IllegalArgumentException - if timeIncrement is less than or equal to zero.
0242: */
0243: public void setTimeIncrement(float timeIncrement) {
0244: animator.setTimeIncrement(timeIncrement);
0245: }
0246:
0247: /**
0248: * Gets time increment of the animation. Proxy call of SVGAnimator.getTimeIncrement().
0249: * @return time increment in seconds.
0250: */
0251: public float getTimeIncrement() {
0252: return animator.getTimeIncrement();
0253: }
0254:
0255: /**
0256: * Pauses the animation. Proxy call for SVGAnimator.pause()
0257: */
0258: public synchronized void pause() {
0259: getAnimator().pause();
0260: animatorState = PAUSED;
0261: }
0262:
0263: /**
0264: * Stops the animation. Proxy call for SVGAnimator.stop()
0265: */
0266: public synchronized void stop() {
0267: getAnimator().stop();
0268: documentUpdateThread = null;
0269: animatorState = STOPPED;
0270: }
0271:
0272: /**
0273: * Starts the animation. Proxy call for SVGAnimator.play()
0274: */
0275: public synchronized void play() {
0276: getAnimator().play();
0277: // get current document update thread
0278: try {
0279: getAnimator().invokeAndWait(new Runnable() {
0280: public void run() {
0281: documentUpdateThread = Thread.currentThread();
0282: }
0283: });
0284: } catch (InterruptedException ex) {
0285: // this should not happen
0286: }
0287: animatorState = PLAYING;
0288: }
0289:
0290: /**
0291: * reset the animation, so it starts again from the beginning. Can be used in
0292: * either when stopped/paused or playing state.
0293: */
0294: public void reset() {
0295: if (animatorState == STOPPED) {
0296: resetAnimationRunnable.run();
0297: } else {
0298: // if playing or paused the reset needs tobe running in update thread
0299: animator.invokeLater(resetAnimationRunnable);
0300: }
0301: }
0302:
0303: /**
0304: * Returns state of the animation
0305: * @return STOPPED for stopped state, PAUSED for paused state and PLAYING when
0306: * the animation is running.
0307: */
0308: public synchronized int getAnimatorState() {
0309: return animatorState;
0310: }
0311:
0312: /**
0313: * Proxy call for SVGAnimator.invokeAndWait() method.
0314: * @param runnable Runnable to be passed to SVGAnimator.invokeAndWait(runnable) method.
0315: * @throws java.lang.InterruptedException
0316: */
0317: public void invokeAndWait(Runnable runnable)
0318: throws InterruptedException {
0319: getAnimator().invokeAndWait(runnable);
0320: }
0321:
0322: /**
0323: * Proxy call for SVGAnimator.invokeLater() method.
0324: * @param runnable Runnable to be passed to SVGAnimator.invokeLater(runnable) method.
0325: */
0326: public void invokeLater(Runnable runnable) {
0327: getAnimator().invokeLater(runnable);
0328: }
0329:
0330: /**
0331: * Gets title from the animation canvas (not <i>this</i> canvas)
0332: * @return title string
0333: */
0334: public String getTitle() {
0335: return (animatorCanvas != null) ? animatorCanvas.getTitle()
0336: : null;
0337: }
0338:
0339: /**
0340: * Sets title to the animation canvas (not <i>this</i> canvas)
0341: * @param s title String
0342: */
0343: public void setTitle(String s) {
0344: animatorCanvas.setTitle(s);
0345: }
0346:
0347: /**
0348: * Adds command to the animation canvas (not <i>this</i> canvas)
0349: */
0350: public void addCommand(Command cmd) {
0351: animatorCanvas.addCommand(cmd);
0352: }
0353:
0354: /**
0355: * Removes command from the animation canvas (not <i>this</i> canvas)
0356: */
0357: public void removeCommand(Command cmd) {
0358: animatorCanvas.removeCommand(cmd);
0359: }
0360:
0361: /**
0362: * Gets ticker from the animation canvas (not <i>this</i> canvas)
0363: */
0364: public Ticker getTicker() {
0365: return (animatorCanvas != null) ? animatorCanvas.getTicker()
0366: : null;
0367: }
0368:
0369: /**
0370: * Sets ticker to the animation canvas (not <i>this</i> canvas)
0371: */
0372: public void setTicker(Ticker ticker) {
0373: animatorCanvas.setTicker(ticker);
0374: }
0375:
0376: /**
0377: * sets fullscreen mode the animation canvas (not <i>this</i> canvas)
0378: */
0379: public void setFullScreenMode(boolean mode) {
0380: animatorCanvas.setFullScreenMode(mode);
0381: // need to change also the size of the image !!!
0382: // this is now done in wrapperSvgEventListener
0383: // the listener in this case does not work - perhaps a bug ????
0384: this .svgImage.setViewportWidth(this .animatorCanvas.getWidth());
0385: this .svgImage
0386: .setViewportHeight(this .animatorCanvas.getHeight());
0387: }
0388:
0389: /**
0390: * When set to true, the animation starts immediatelly when
0391: * the canvas with animation displayed on the screen
0392: */
0393: public void setStartAnimationImmediately(boolean startAnimation) {
0394: this .startAnimation = startAnimation;
0395: }
0396:
0397: /**
0398: * Should be animation reset whhen stopped
0399: **/
0400: public boolean isResetAnimationWhenStopped() {
0401: return resetAnimationWhenStopped;
0402: }
0403:
0404: /**
0405: * Sets
0406: */
0407: public void setResetAnimationWhenStopped(boolean reset) {
0408: this .resetAnimationWhenStopped = reset;
0409: }
0410:
0411: /**
0412: * Gets command listener assigned to this displayable. Can be
0413: * used by children classes
0414: */
0415: protected final CommandListener getCommandListener() {
0416: return this .commandListener;
0417: }
0418:
0419: /**
0420: * Sets command listener to this displayable
0421: */
0422: public void setCommandListener(CommandListener commandListener) {
0423: //super.setCommandListener(this);
0424: this .commandListener = commandListener;
0425: }
0426:
0427: /**
0428: * Gets Display
0429: **/
0430: protected Display getDisplay() {
0431: return display;
0432: }
0433:
0434: /**
0435: * Gets SVGAnimator created in this player. Please use wisely :-)
0436: **/
0437: protected SVGAnimator getAnimator() {
0438: return animator;
0439: }
0440:
0441: /**
0442: * Gets SVGImage used to create this SVGPlayer.
0443: *
0444: * @return SVGImage used to create this object
0445: */
0446: public final SVGImage getSVGImage() {
0447: return svgImage;
0448: }
0449:
0450: /**
0451: * Gets SVGElement from the SVGImage used for this SVGPlayer.
0452: *
0453: * @param id an id of the svg element to be obtained
0454: * @return SVGElement corresponding to the given id, or null if there is
0455: * no such element or the element is not of SVGElement instance
0456: *
0457: * @throws IllegalArgumentException if the supplied id is null
0458: */
0459: public SVGElement getSVGElementById(String id)
0460: throws IllegalArgumentException {
0461: if (id == null) {
0462: throw new IllegalArgumentException(
0463: "id parameter cannot be null");
0464: }
0465: Element element = doc.getElementById(id);
0466: if (element instanceof SVGElement) {
0467: return (SVGElement) element;
0468: } else {
0469: return null;
0470: }
0471: }
0472:
0473: /**
0474: * Gets SVGLocatableElement from the SVGImage used for this SVGPlayer.
0475: *
0476: * @param id an id of the svg element to be obtained
0477: * @return SVGLocatableElement corresponding to the given id, or null if there is
0478: * no such element or the element is not of SVGLocatableElement instance
0479: *
0480: * @throws IllegalArgumentException if the supplied id is null
0481: */
0482: public SVGLocatableElement getSVGLocatableElementById(String id)
0483: throws IllegalArgumentException {
0484: if (id == null) {
0485: throw new IllegalArgumentException(
0486: "id parameter cannot be null");
0487: }
0488: Element element = doc.getElementById(id);
0489: if (element instanceof SVGLocatableElement) {
0490: return (SVGLocatableElement) element;
0491: } else {
0492: return null;
0493: }
0494: }
0495:
0496: /**
0497: * Gets SVGAnimationElement from the SVGImage used for this SVGPlayer.
0498: *
0499: * @param id an id of the animation element to be obtained
0500: * @return SVGAnimationElement corresponding to the given id, or null if there is
0501: * no such element or the element is not of SVGAnimationElement instance
0502: *
0503: * @throws IllegalArgumentException if the supplied id is null
0504: */
0505: public SVGAnimationElement getSVGAnimationElementById(String id)
0506: throws IllegalArgumentException {
0507: if (id == null) {
0508: throw new IllegalArgumentException(
0509: "id parameter cannot be null");
0510: }
0511: Element element = doc.getElementById(id);
0512: if (element instanceof SVGAnimationElement) {
0513: return (SVGAnimationElement) element;
0514: } else {
0515: return null;
0516: }
0517: }
0518:
0519: // checks whether the the current thread is a document update thread
0520: private boolean isRunningInUpdateThread() {
0521: return (Thread.currentThread() == documentUpdateThread);
0522: }
0523:
0524: /**
0525: * Schedule the input Runnable for execution in the update thread\
0526: * at a later time. In the case the animator is in stopped mode, the method
0527: * invokes the runnable in a separate thread.
0528: *
0529: * @param runnable a runnable scheduled for invokation in update thread
0530: */
0531: public synchronized void invokeLaterSafely(Runnable runnable) {
0532: if (runnable != null) {
0533: if (getAnimatorState() == STOPPED) {
0534: new Thread(runnable).start();
0535: } else {
0536: getAnimator().invokeLater(runnable);
0537: }
0538: }
0539: }
0540:
0541: /**
0542: * Invokes the input Runnable in the document update thread and returns after
0543: * the Runnable has completed. In the case SVGAnimator is in stopped mode or
0544: * if the method is being called directly from the document update thread,
0545: * the method invokes run() method on runnable directly.
0546: *
0547: * @param runnable a runnable scheduled for invokation in update thread
0548: */
0549: public synchronized void invokeAndWaitSafely(Runnable runnable) {
0550: if (runnable != null) {
0551: // if the method is already running in an update thread or animator is
0552: // stopped, the runnable is run direclty, otherwise it is run using
0553: // SVGAnimator.ivokeAndWait() method
0554: if (isRunningInUpdateThread()
0555: || (getAnimatorState() == STOPPED)) {
0556: runnable.run();
0557: } else {
0558: try {
0559: getAnimator().invokeAndWait(runnable);
0560: } catch (InterruptedException ex) {
0561: // ignore the interrupted exception
0562: }
0563: }
0564: }
0565: }
0566:
0567: // setting and manipulation utility methods
0568:
0569: /**
0570: * Sets the desired trait on the element with the specified identifier. If the
0571: * element with given ID is not an instance of SVGElement, the operation is
0572: * not performed.
0573: * <p>
0574: * This method uses "safe" approach - i.e. when it runs in document
0575: * update thread it runs directly in the thread, otherwise it is
0576: * scheduled using SVGAnimator.invokeAndWait method.
0577: *
0578: * @param id the id of the element whose trait value should be changed.
0579: * @param traitName the name of the trait to change, e.g, "display"
0580: * @param traitValue the value of the trait to set, e.g., "none"
0581: */
0582: public void setTraitSafely(final String id, final String traitName,
0583: final String traitValue) {
0584: invokeAndWaitSafely(new Runnable() {
0585: public void run() {
0586: setTrait(id, traitName, traitValue);
0587: }
0588: });
0589: }
0590:
0591: /**
0592: * Sets the desired trait on the element with the specified identifier. If the
0593: * element with given ID is not an instance of SVGElement, the operation is
0594: * not performed.
0595: * <p><em>Note:</em>This method needs to be called from the document update thread.</p>
0596: * @param id the id of the element whose trait value should be changed.
0597: * @param traitName the name of the trait to change, e.g, "display"
0598: * @param traitValue the value of the trait to set, e.g., "none"
0599: */
0600: public void setTrait(final String id, final String traitName,
0601: final String traitValue) {
0602: SVGElement elt = getSVGElementById(id);
0603: if (elt != null) {
0604: elt.setTrait(traitName, traitValue);
0605: }
0606: }
0607:
0608: /**
0609: * Sets the desired trait on the element with the specified identifier. If the
0610: * element with given ID is not an instance of SVGElement, the operation is
0611: * not performed.
0612: *
0613: * <p>
0614: * This method uses "safe" approach - i.e. when it runs in document
0615: * update thread it runs directly in the thread, otherwise it is
0616: * scheduled using SVGAnimator.invokeAndWait method.
0617: *
0618: * @param id the id of the element whose trait value should be changed.
0619: * @param traitName the name of the trait to change, e.g, "display"
0620: * @param traitValue the value of the trait to set, e.g., "none"
0621: */
0622: public void setFloatTraitSafely(final String id,
0623: final String traitName, final float traitValue) {
0624: invokeAndWaitSafely(new Runnable() {
0625: public void run() {
0626: setFloatTrait(id, traitName, traitValue);
0627: }
0628: });
0629: }
0630:
0631: /**
0632: * Sets the desired trait on the element with the specified identifier. If the
0633: * element with given ID is not an instance of SVGElement, the operation is
0634: * not performed.
0635: *
0636: * @param id the id of the element whose trait value should be changed.
0637: * @param traitName the name of the trait to change, e.g, "display"
0638: * @param traitValue the value of the trait to set, e.g., "none"
0639: */
0640: public void setFloatTrait(final String id, final String traitName,
0641: final float traitValue) {
0642: SVGElement elt = getSVGElementById(id);
0643:
0644: if (elt != null) {
0645: elt.setFloatTrait(traitName, traitValue);
0646: }
0647: }
0648:
0649: /**
0650: * Sets the desired RGB value on the element with the specified identifier. If the
0651: * element with given ID is not an instance of SVGElement, the operation is
0652: * not performed.
0653: *
0654: * <p>
0655: * This method uses "safe" approach - i.e. when it runs in document
0656: * update thread it runs directly in the thread, otherwise it is
0657: * scheduled using SVGAnimator.invokeAndWait method.
0658: *
0659: * @param id the id of the element whose trait value should be changed.
0660: * @param traitName the name of the trait to change, e.g, "stroke" or "fill"
0661: * @param rgb the color value as an int in the following format 0xXXRRGGBB.
0662: * The high order byte is ignored. For example, 0xFFFF0000 specifies
0663: * red.
0664: */
0665: public void setRGBTraitSafely(final String id,
0666: final String traitName, final int rgb) {
0667: invokeAndWaitSafely(new Runnable() {
0668: public void run() {
0669: setRGBTrait(id, traitName, rgb);
0670: }
0671: });
0672: }
0673:
0674: /**
0675: * Sets the desired RGB value on the element with the specified identifier. If the
0676: * element with given ID is not an instance of SVGElement, the operation is
0677: * not performed.
0678: *
0679: * @param id the id of the element whose trait value should be changed.
0680: * @param traitName the name of the trait to change, e.g, "stroke" or "fill"
0681: * @param rgb the color value as an int in the following format 0xXXRRGGBB.
0682: * The high order byte is ignored. For example, 0xFFFF0000 specifies
0683: * red.
0684: */
0685: public void setRGBTrait(final String id, final String traitName,
0686: final int rgb) {
0687: SVGElement elt = getSVGElementById(id);
0688:
0689: if (elt != null) {
0690: int r = (rgb >> 16) & 0xFF;
0691: int g = (rgb >> 8) & 0xFF;
0692: int b = (rgb) & 0xFF;
0693:
0694: SVGRGBColor svgRGB = svg.createSVGRGBColor(r, g, b);
0695: elt.setRGBColorTrait(traitName, svgRGB);
0696: }
0697: }
0698:
0699: /**
0700: * Sets the desired RGB value on the element with the specified identifier. If the
0701: * element with given ID is not an instance of SVGElement, the operation is
0702: * not performed.
0703: *
0704: * <p>
0705: * This method uses "safe" approach - i.e. when it runs in document
0706: * update thread it runs directly in the thread, otherwise it is
0707: * scheduled using SVGAnimator.invokeAndWait method.
0708: *
0709: * @param id the id of the element whose trait value should be changed.
0710: * @param traitName the name of the trait to change, e.g, "fill"
0711: * @param r the desired red component value, in the 0-255 interval
0712: * @param g the desired green component value, in the 0-255 interval
0713: * @param b the desired blue component value, in the 0-255 interval
0714: */
0715: public void setRGBTraitSafely(final String id,
0716: final String traitName, final int r, final int g,
0717: final int b) {
0718: invokeAndWaitSafely(new Runnable() {
0719: public void run() {
0720: setRGBTrait(id, traitName, r, g, b);
0721: }
0722: });
0723: }
0724:
0725: /**
0726: * Sets the desired RGB value on the element with the specified identifier. If the
0727: * element with given ID is not an instance of SVGElement, the operation is
0728: * not performed.
0729: *
0730: * @param id the id of the element whose trait value should be changed.
0731: * @param traitName the name of the trait to change, e.g, "fill"
0732: * @param r the desired red component value, in the 0-255 interval
0733: * @param g the desired green component value, in the 0-255 interval
0734: * @param b the desired blue component value, in the 0-255 interval
0735: */
0736: public void setRGBTrait(final String id, final String traitName,
0737: final int r, final int g, final int b) {
0738: SVGElement elt = getSVGElementById(id);
0739:
0740: if (elt != null) {
0741: SVGRGBColor rgb = svg.createSVGRGBColor(r, g, b);
0742: elt.setRGBColorTrait(traitName, rgb);
0743: }
0744: }
0745:
0746: /**
0747: * Translates the element with the specified id by the given amount, in
0748: * user space. If the
0749: * element with given ID is not an instance of SVGElement, the operation is
0750: * not performed.
0751: *
0752: * <p>
0753: * This method uses "safe" approach - i.e. when it runs in document
0754: * update thread it runs directly in the thread, otherwise it is
0755: * scheduled using SVGAnimator.invokeAndWait method.
0756: *
0757: * @param id the id of the element whose trait value should be changed.
0758: * @param tx the desired translation along the x-axis
0759: * @param ty the desired translation along the y-axis
0760: */
0761: public void translateSafely(final String id, final float tx,
0762: final float ty) {
0763: invokeAndWaitSafely(new Runnable() {
0764: public void run() {
0765: translate(id, tx, ty);
0766: }
0767: });
0768: }
0769:
0770: /**
0771: * Translates the element with the specified id by the given amount, in
0772: * user space. If the
0773: * element with given ID is not an instance of SVGElement, the operation is
0774: * not performed.
0775: *
0776: * @param id the id of the element whose trait value should be changed.
0777: * @param tx the desired translation along the x-axis
0778: * @param ty the desired translation along the y-axis
0779: */
0780: public void translate(final String id, final float tx,
0781: final float ty) {
0782: translate(getSVGElementById(id), tx, ty);
0783: }
0784:
0785: /**
0786: * Translates the element with the specified id by the given amount, in
0787: * user space.
0788: *
0789: * @param svgElement the element whose trait value should be changed. If null,
0790: * the operation is not performed.
0791: * @param tx the desired translation along the x-axis
0792: * @param ty the desired translation along the y-axis
0793: */
0794: public void translate(final SVGElement svgElement, final float tx,
0795: final float ty) {
0796: if (svgElement != null) {
0797: SVGMatrix txf = svgElement.getMatrixTrait("transform");
0798: if (txf == null) {
0799: txf = svg.createSVGMatrixComponents(1, 0, 0, 1, 0, 0);
0800: }
0801: txf.mTranslate(tx, ty);
0802: svgElement.setMatrixTrait("transform", txf);
0803: }
0804: }
0805:
0806: /**
0807: * Translates the element with the specified id by the given amount, in
0808: * the screen coordinate space. If the
0809: * element with given ID is not an instance of SVGLocatableElement, the operation is
0810: * not performed.
0811: *
0812: * <p>
0813: * This method uses "safe" approach - i.e. when it runs in document
0814: * update thread it runs directly in the thread, otherwise it is
0815: * scheduled using SVGAnimator.invokeAndWait method.
0816: *
0817: * @param id the id of the element whose trait value should be changed.
0818: * @param tx the desired translation along the x-axis
0819: * @param ty the desired translation along the y-axis
0820: */
0821: public void screenTranslateSafely(final String id, final float tx,
0822: final float ty) {
0823: invokeAndWaitSafely(new Runnable() {
0824: public void run() {
0825: screenTranslate(id, tx, ty);
0826: }
0827: });
0828: }
0829:
0830: /**
0831: * Translates the element with the specified id by the given amount, in
0832: * the screen coordinate space. If the
0833: * element with given ID is not an instance of SVGLocatableElement, the operation is
0834: * not performed.
0835: *
0836: * @param id the id of the element whose trait value should be changed.
0837: * @param tx the desired translation along the x-axis
0838: * @param ty the desired translation along the y-axis
0839: */
0840: public void screenTranslate(final String id, final float tx,
0841: final float ty) {
0842: screenTranslate(getSVGLocatableElementById(id), tx, ty);
0843: }
0844:
0845: /**
0846: * Translates the element with the specified id by the given amount, in
0847: * the screen coordinate space.
0848: *
0849: * @param svgLocatableElement the element whose trait value should be changed.
0850: * If null, the operation is not performed.
0851: * @param tx the desired translation along the x-axis
0852: * @param ty the desired translation along the y-axis
0853: */
0854: public void screenTranslate(
0855: final SVGLocatableElement svgLocatableElement,
0856: final float tx, final float ty) {
0857: if (svgLocatableElement != null) {
0858: SVGMatrix txf = svgLocatableElement
0859: .getMatrixTrait("transform");
0860: if (txf == null) {
0861: txf = svg.createSVGMatrixComponents(1, 0, 0, 1, 0, 0);
0862: }
0863:
0864: // user space -> screen
0865: SVGMatrix screenTxf = svgLocatableElement.getScreenCTM();
0866:
0867: // screen -> user space
0868: SVGMatrix screenTxfInv = screenTxf.inverse();
0869:
0870: txf = txf.mMultiply(screenTxfInv);
0871:
0872: // Now, txf brings us to the screen coordinate system.
0873: // We concatenate the tranlation in that space.
0874: txf.mTranslate(tx, ty);
0875:
0876: // Now, concatenate the transform back to the user space.
0877: txf.mMultiply(screenTxf);
0878:
0879: svgLocatableElement.setMatrixTrait("transform", txf);
0880: }
0881: }
0882:
0883: /**
0884: * Returns the screen bounding box for the desired element.
0885: *
0886: * @param id the id of the element whose bounding box is retrieved.
0887: * @return found screen bounding box or null if the the element with given
0888: * was not found or does not correspond to an instance SVGLocatableElement.
0889: */
0890: public SVGRect getScreenBBox(final String id) {
0891: SVGLocatableElement elt = getSVGLocatableElementById(id);
0892: if (elt != null) {
0893: return elt.getScreenBBox();
0894: }
0895: return null;
0896: }
0897:
0898: /**
0899: * Scales the element with the specified id by the given factor along the
0900: * x and y axis. If the
0901: * element with given ID is not an instance of SVGElement, the operation is
0902: * not performed.
0903: *
0904: * <p>
0905: * This method uses "safe" approach - i.e. when it runs in document
0906: * update thread it runs directly in the thread, otherwise it is
0907: * scheduled using SVGAnimator.invokeAndWait method.
0908: *
0909: * @param id the id of the element whose trait value should be changed.
0910: * @param sx the desired scale factor along the x-axis
0911: * @param sy the desired scale factor along the y-axis
0912: */
0913: public void scaleSafely(final String id, final float sx,
0914: final float sy) {
0915: invokeAndWaitSafely(new Runnable() {
0916: public void run() {
0917: scale(id, sx, sy);
0918: }
0919: });
0920: }
0921:
0922: /**
0923: * Scales the element with the specified id by the given factor along the
0924: * x and y axis. If the
0925: * element with given ID is not an instance of SVGElement, the operation is
0926: * not performed.
0927: *
0928: *
0929: * @param id the id of the element whose trait value should be changed.
0930: * @param sx the desired scale factor along the x-axis
0931: * @param sy the desired scale factor along the y-axis
0932: */
0933: public void scale(final String id, final float sx, final float sy) {
0934: scale(getSVGElementById(id), sx, sy);
0935: }
0936:
0937: /**
0938: * Scales the element with the specified id by the given factor along the
0939: * x and y axis.
0940: *
0941: * @param svgElement element whose trait value should be changed. If null, the
0942: * operation is not performed.
0943: * @param sx the desired scale factor along the x-axis
0944: * @param sy the desired scale factor along the y-axis
0945: */
0946: public void scale(final SVGElement svgElement, final float sx,
0947: final float sy) {
0948: if (svgElement != null) {
0949: SVGMatrix txf = svgElement.getMatrixTrait("transform");
0950: if (txf == null) {
0951: txf = svg.createSVGMatrixComponents(1, 0, 0, 1, 0, 0);
0952: }
0953:
0954: SVGMatrix scale = svg.createSVGMatrixComponents(sx, 0, 0,
0955: sy, 0, 0);
0956: txf.mMultiply(scale);
0957: svgElement.setMatrixTrait("transform", txf);
0958: }
0959: }
0960:
0961: /**
0962: * Scales the element with the given id about the desired anchor point.
0963: * If the
0964: * element with given ID is not an instance of SVGLocatableElement, the operation is
0965: * not performed.
0966: * <p>
0967: * This method uses "safe" approach - i.e. when it runs in document
0968: * update thread it runs directly in the thread, otherwise it is
0969: * scheduled using SVGAnimator.invokeAndWait method.
0970: *
0971: * @param id the id of the element whose trait value should be changed.
0972: * @param sx the desired scale factor along the x-axis
0973: * @param sy the desired scale factor along the y-axis
0974: * @param anchor one of TOP_LEFT, TOP, TOP_RIGHT, LEFT, CENTER, RIGHT,
0975: * BOTTOM_LEFT, BOTTOM, BOTTOM_RIGHT.
0976: */
0977: public void scaleAboutSafely(final String id, final float sx,
0978: final float sy, final int anchor) {
0979: invokeAndWaitSafely(new Runnable() {
0980: public void run() {
0981: scaleAbout(id, sx, sy, anchor);
0982: }
0983: });
0984: }
0985:
0986: /**
0987: * Scales the element with the given id about the desired anchor point.
0988: * If the
0989: * element with given ID is not an instance of SVGLocatableElement, the operation is
0990: * not performed.
0991: *
0992: * @param id the id of the element whose trait value should be changed.
0993: * @param sx the desired scale factor along the x-axis
0994: * @param sy the desired scale factor along the y-axis
0995: * @param anchor one of TOP_LEFT, TOP, TOP_RIGHT, LEFT, CENTER, RIGHT,
0996: * BOTTOM_LEFT, BOTTOM, BOTTOM_RIGHT.
0997: */
0998: public void scaleAbout(final String id, final float sx,
0999: final float sy, final int anchor) {
1000: scaleAbout(getSVGLocatableElementById(id), sx, sy, anchor);
1001: }
1002:
1003: /**
1004: * Scales the element with the given id about the desired anchor point.
1005: *
1006: * @param svgLocatableElement element whose trait value should be changed. If null
1007: * the operation is not performed.
1008: * @param sx the desired scale factor along the x-axis
1009: * @param sy the desired scale factor along the y-axis
1010: * @param anchor one of TOP_LEFT, TOP, TOP_RIGHT, LEFT, CENTER, RIGHT,
1011: * BOTTOM_LEFT, BOTTOM, BOTTOM_RIGHT.
1012: */
1013: public void scaleAbout(
1014: final SVGLocatableElement svgLocatableElement,
1015: final float sx, final float sy, final int anchor) {
1016:
1017: if (svgLocatableElement != null) {
1018: SVGMatrix txf = svgLocatableElement
1019: .getMatrixTrait("transform");
1020: if (txf == null) {
1021: txf = svg.createSVGMatrixComponents(1, 0, 0, 1, 0, 0);
1022: }
1023:
1024: // Get the element's bounding box to compute the anchor
1025: // point translation.
1026: SVGRect bbox = svgLocatableElement.getBBox();
1027: float[] translate = computeAnchorTranslate(bbox, anchor);
1028:
1029: SVGMatrix scale = svg.createSVGMatrixComponents(sx, 0, 0,
1030: sy, 0, 0);
1031: txf.mTranslate(-translate[0], -translate[1]);
1032: txf.mMultiply(scale);
1033: txf.mTranslate(translate[0], translate[1]);
1034: svgLocatableElement.setMatrixTrait("transform", txf);
1035: }
1036: }
1037:
1038: /**
1039: * Rotates the element with the given id by the given angle.
1040: *
1041: * If the
1042: * element with given ID is not an instance of SVGElement, the operation is
1043: * not performed.
1044: *
1045: * <p>
1046: * This method uses "safe" approach - i.e. when it runs in document
1047: * update thread it runs directly in the thread, otherwise it is
1048: * scheduled using SVGAnimator.invokeAndWait method.
1049: *
1050: * @param id the id of the element which should be rotated.
1051: * @param angle the rotation angle, in degrees
1052: */
1053: public void rotateSafely(final String id, final float angle) {
1054: invokeAndWaitSafely(new Runnable() {
1055: public void run() {
1056: rotate(id, angle);
1057: }
1058: });
1059: }
1060:
1061: /**
1062: * Rotates the element with the given id by the given angle.
1063: *
1064: * If the
1065: * element with given ID is not an instance of SVGElement, the operation is
1066: * not performed.
1067: *
1068: * @param id the id of the element which should be rotated.
1069: * @param angle the rotation angle, in degrees
1070: */
1071: public void rotate(final String id, final float angle) {
1072: rotate(getSVGElementById(id), angle);
1073: }
1074:
1075: /**
1076: * Rotates the element with the given id by the given angle.
1077: *
1078: * @param svgElement the element which should be rotated. If null, the
1079: * operation is not performed.
1080: * @param angle the rotation angle, in degrees
1081: */
1082: public void rotate(final SVGElement svgElement, final float angle) {
1083: if (svgElement != null) {
1084: SVGMatrix txf = svgElement.getMatrixTrait("transform");
1085: if (txf == null) {
1086: txf = svg.createSVGMatrixComponents(1, 0, 0, 1, 0, 0);
1087: }
1088:
1089: txf.mRotate(angle);
1090: svgElement.setMatrixTrait("transform", txf);
1091: }
1092: }
1093:
1094: /**
1095: * Rotates the element with the given id by the given angle about
1096: * the desired anchor point.
1097: *
1098: * If the
1099: * element with given ID is not an instance of SVGLocatableElement, the operation is
1100: * not performed.
1101: *
1102: * <p>
1103: * This method uses "safe" approach - i.e. when it runs in document
1104: * update thread it runs directly in the thread, otherwise it is
1105: * scheduled using SVGAnimator.invokeAndWait method.
1106: *
1107: *
1108: * @param id the id of the element which should be rotated.
1109: * @param angle the rotation angle, in degrees
1110: * @param anchor the reference point about which to rotate the element.
1111: */
1112: public void rotateAboutSafely(final String id, final float angle,
1113: final int anchor) {
1114: invokeAndWaitSafely(new Runnable() {
1115: public void run() {
1116: rotateAbout(id, angle, anchor);
1117: }
1118: });
1119: }
1120:
1121: /**
1122: * Rotates the element with the given id by the given angle about
1123: * the desired anchor point.
1124: *
1125: * If the
1126: * element with given ID is not an instance of SVGLocatableElement, the operation is
1127: * not performed.
1128: *
1129: * @param id the id of the element which should be rotated.
1130: * @param angle the rotation angle, in degrees
1131: * @param anchor the reference point about which to rotate the element.
1132: */
1133: public void rotateAbout(final String id, final float angle,
1134: final int anchor) {
1135: rotateAbout(getSVGLocatableElementById(id), angle, anchor);
1136: }
1137:
1138: /**
1139: * Rotates the element with the given id by the given angle about
1140: * the desired anchor point.
1141: *
1142: * @param svgLocatableElement the element which should be rotated. If null the
1143: * operation is not performed.
1144: * @param angle the rotation angle, in degrees
1145: * @param anchor the reference point about which to rotate the element.
1146: */
1147: public void rotateAbout(
1148: final SVGLocatableElement svgLocatableElement,
1149: final float angle, final int anchor) {
1150:
1151: if (svgLocatableElement != null) {
1152: SVGMatrix txf = svgLocatableElement
1153: .getMatrixTrait("transform");
1154: if (txf == null) {
1155: txf = svg.createSVGMatrixComponents(1, 0, 0, 1, 0, 0);
1156: }
1157:
1158: // Get the element's bounding box to compute the anchor
1159: // point translation.
1160: SVGRect bbox = svgLocatableElement.getBBox();
1161: float[] translate = computeAnchorTranslate(bbox, anchor);
1162:
1163: txf.mTranslate(-translate[0], -translate[1]);
1164: txf.mRotate(angle);
1165: txf.mTranslate(translate[0], translate[1]);
1166:
1167: svgLocatableElement.setMatrixTrait("transform", txf);
1168: }
1169: }
1170:
1171: /**
1172: * Computes the translation needed to center the given rectangle about the
1173: * desired anchor position.
1174: *
1175: * @param bbox the object's bounding box, used to compute the translation.
1176: * @param anchor the desired anchor position for the translation. For example,
1177: * if anchor is "BOTTOM_RIGHT", the returned translation will move the
1178: * bottom right of the bounding box to the coordinate system's origin.
1179: *
1180: * @return the translation. A float array of size two, with the x-axis translation
1181: * at index 0 and the y-axis translation at index 1.
1182: */
1183: protected float[] computeAnchorTranslate(SVGRect bbox, int anchor) {
1184: float[] translate = { 0, 0 };
1185: switch (anchor) {
1186: case TOP_LEFT:
1187: case LEFT:
1188: case BOTTOM_LEFT:
1189: translate[0] = -bbox.getX();
1190: break;
1191: case TOP:
1192: case CENTER:
1193: case BOTTOM:
1194: translate[0] = -bbox.getX() - bbox.getWidth() / 2;
1195: break;
1196: case TOP_RIGHT:
1197: case RIGHT:
1198: case BOTTOM_RIGHT:
1199: default:
1200: translate[0] = -bbox.getX() - bbox.getWidth();
1201: break;
1202: }
1203:
1204: switch (anchor) {
1205: case TOP_LEFT:
1206: case TOP:
1207: case TOP_RIGHT:
1208: translate[1] = -bbox.getY();
1209: break;
1210: case LEFT:
1211: case CENTER:
1212: case RIGHT:
1213: translate[1] = -bbox.getY() - bbox.getHeight() / 2;
1214: break;
1215: case BOTTOM_LEFT:
1216: case BOTTOM:
1217: case BOTTOM_RIGHT:
1218: default:
1219: translate[1] = -bbox.getY() - bbox.getHeight();
1220: break;
1221: }
1222:
1223: return translate;
1224: }
1225:
1226: /// animation utility methods
1227:
1228: /**
1229: * Starts immediately animation on the given animation element. If the given
1230: * id does not correspond to a valid animation element, the operation is
1231: * not performed.
1232: *
1233: * <p>
1234: * This method uses "safe" approach - i.e. when it runs in document
1235: * update thread it runs directly in the thread, otherwise it is
1236: * scheduled using SVGAnimator.invokeAndWait method.
1237: *
1238: * @param elementId id of the animation element on which the animation should be started
1239: *
1240: */
1241: public void startAnimationSafely(final String elementId) {
1242: invokeAndWaitSafely(new Runnable() {
1243: public void run() {
1244: startAnimation(elementId);
1245: }
1246: });
1247: }
1248:
1249: /**
1250: * Starts immediately animation on the given animation element. If the given
1251: * id does not correspond to a valid animation element, the operation is
1252: * not performed.
1253: *
1254: * @param elementId id of the animation element on which the animation should be started
1255: *
1256: * @throws IllegalArgumentException if the elementID does not correspond to a valid SVGAnimationElement
1257: */
1258: public void startAnimation(String elementId) {
1259: startAnimation(elementId, 0f);
1260: }
1261:
1262: /**
1263: * Starts immediately animation on the given animation element. If the given
1264: * id does not correspond to a valid animation element, the operation is
1265: * not performed.
1266: *
1267: * @param elementId id of the animation element on which the animation should be started
1268: * @param delay offset in seconds at which the animation should be started
1269: *
1270: */
1271: public void startAnimation(String elementId, float delay) {
1272: SVGAnimationElement animationElement = getSVGAnimationElementById(elementId);
1273: if (animationElement != null) {
1274: animationElement.beginElementAt(delay);
1275: }
1276: }
1277:
1278: /**
1279: * Stops animation on the given animation element. If the given
1280: * id does not correspond to a valid animation element, the operation is
1281: * not performed.
1282: *
1283: * <p>
1284: * This method uses "safe" approach - i.e. when it runs in document
1285: * update thread it runs directly in the thread, otherwise it is
1286: * scheduled using SVGAnimator.invokeAndWait method.
1287: *
1288: * @param elementId id of the animation element on which the animation should be stopped
1289: */
1290: public void stopAnimationSafely(final String elementId) {
1291: invokeLaterSafely(new Runnable() {
1292: public void run() {
1293: stopAnimationSafely(elementId);
1294: }
1295: });
1296: }
1297:
1298: /**
1299: * Stops animation on the given animation element. If the given
1300: * id does not correspond to a valid animation element, the operation is
1301: * not performed.
1302: *
1303: * @param elementId id of the animation element on which the animation should be stopped
1304:
1305: */
1306: public void stopAnimation(String elementId) {
1307: stopAnimation(elementId, 0f);
1308: }
1309:
1310: /**
1311: * Stops animation on the given animation element, with given delay.
1312: * Stops animation on the given animation element. If the given
1313: * id does not correspond to a valid animation element, the operation is
1314: * not performed.
1315: *
1316: * @param elementId id of the animation element on which the animation should be stopped
1317: * @param delay offset in seconds at which the animation should be stopped
1318: *
1319: */
1320: public void stopAnimation(String elementId, float delay) {
1321: SVGAnimationElement animationElement = getSVGAnimationElementById(elementId);
1322: if (animationElement != null) {
1323: animationElement.endElementAt(delay);
1324: }
1325: }
1326:
1327: /**
1328: * Dummy paint method - does nothing, because all the rendering is done
1329: * by the canvas obtained from SVGAnimator
1330: */
1331: protected void paint(Graphics graphics) {
1332: // dummy - should never be called
1333: }
1334:
1335: /*
1336: protected void showNotify() {
1337: //System.out.println("Current display:"+display.getCurrent());
1338: getDisplay().callSerially(new Runnable() {
1339: public void run() {
1340: getDisplay().setCurrent(animatorCanvas);
1341: }
1342: });
1343: }*/
1344:
1345: /**
1346: * Implementation of CommandListener.commandAction() which forwards
1347: * command action from Canvas created by SVGAnimator
1348: * to the CommandListener assigned to this component
1349: */
1350: public void commandAction(Command command, Displayable displayable) {
1351: if ((displayable == animatorCanvas)
1352: && (commandListener != null)) {
1353: commandListener.commandAction(command, this );
1354: }
1355: }
1356:
1357: /**
1358: * Wrapper for SvgEventListener - allows also userSvgEventListener to listen here
1359: */
1360: private class WrapperSvgEventListener implements SVGEventListener {
1361:
1362: public void keyPressed(final int i) {
1363: if (userSvgEventListener != null) {
1364: userSvgEventListener.keyPressed(i);
1365: }
1366: if (safeSvgEventListener != null) {
1367: invokeAndWaitSafely(new Runnable() {
1368: public void run() {
1369: safeSvgEventListener.keyPressed(i);
1370: }
1371: });
1372: }
1373: }
1374:
1375: public void keyReleased(final int i) {
1376: if (userSvgEventListener != null) {
1377: userSvgEventListener.keyReleased(i);
1378: }
1379: if (safeSvgEventListener != null) {
1380: invokeAndWaitSafely(new Runnable() {
1381: public void run() {
1382: safeSvgEventListener.keyReleased(i);
1383: }
1384: });
1385: }
1386: }
1387:
1388: public void pointerPressed(final int x, final int y) {
1389: if (userSvgEventListener != null) {
1390: userSvgEventListener.pointerPressed(x, y);
1391: }
1392: if (safeSvgEventListener != null) {
1393: invokeAndWaitSafely(new Runnable() {
1394: public void run() {
1395: safeSvgEventListener.pointerPressed(x, y);
1396: }
1397: });
1398: }
1399: }
1400:
1401: public void pointerReleased(final int x, final int y) {
1402: if (userSvgEventListener != null) {
1403: userSvgEventListener.pointerReleased(x, y);
1404: }
1405: if (safeSvgEventListener != null) {
1406: invokeAndWaitSafely(new Runnable() {
1407: public void run() {
1408: safeSvgEventListener.pointerPressed(x, y);
1409: }
1410: });
1411: }
1412: }
1413:
1414: public void hideNotify() {
1415: // should schedule animation reset !!!
1416: animationNeedsReset = true;
1417: // stop the animmation if necessary
1418: if (animatorState != STOPPED) {
1419: // need to call play serially - otherwise this might cause a deadlock on the device
1420: /*getDisplay().callSerially(new Runnable() {
1421: public void run() {
1422: **/
1423: stop();
1424: /* }
1425: });*/
1426: }
1427: // call the user's listener'
1428: if (userSvgEventListener != null) {
1429: userSvgEventListener.hideNotify();
1430: }
1431: if (safeSvgEventListener != null) {
1432: invokeAndWaitSafely(new Runnable() {
1433: public void run() {
1434: safeSvgEventListener.hideNotify();
1435: }
1436: });
1437: }
1438: }
1439:
1440: public void showNotify() {
1441: // stop the animmation if necessary
1442: if (resetAnimationWhenStopped && animationNeedsReset) {
1443: reset();
1444: }
1445: if ((startAnimation) && (animatorState != PLAYING)) {
1446: // need to call play serially - otherwise this might cause a deadlock on the device
1447: getDisplay().callSerially(new Runnable() {
1448: public void run() {
1449: play();
1450: }
1451: });
1452: }
1453: // call the user's listeners
1454: if (userSvgEventListener != null) {
1455: userSvgEventListener.showNotify();
1456: }
1457:
1458: if (safeSvgEventListener != null) {
1459: invokeAndWaitSafely(new Runnable() {
1460: public void run() {
1461: safeSvgEventListener.showNotify();
1462: }
1463: });
1464: }
1465:
1466: }
1467:
1468: public void sizeChanged(final int x, final int y) {
1469: // resize the image automatically? only when the user does not supply its own listener
1470: svgImage.setViewportWidth(x);
1471: svgImage.setViewportHeight(y);
1472: if (userSvgEventListener != null) {
1473: userSvgEventListener.sizeChanged(x, y);
1474: }
1475:
1476: if (safeSvgEventListener != null) {
1477: invokeAndWaitSafely(new Runnable() {
1478: public void run() {
1479: safeSvgEventListener.sizeChanged(x, y);
1480: }
1481: });
1482: }
1483: }
1484:
1485: }
1486:
1487: }
|