www.pudn.com > Bluegammon蓝牙的应用编程.rar > AnimationEngine.java
// Copyright (c) 2005 Sony Ericsson Mobile Communications AB // // This software is provided "AS IS," without a warranty of any kind. // ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, // INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A // PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. // // THIS SOFTWARE IS COMPLEMENTARY OF JAYWAY AB (www.jayway.se) package bluegammon.gui.animation; import java.util.Vector; import javax.microedition.lcdui.Graphics; /** * Animation engine, handles all animation logic. * Works together with an implementation of aRepaintRequestable* This animation engine uses a primitive mechanism when * deciding what interval to update all animations - it uses the minimum * interval value returned amongst all active animations in the engine. Hence, * all animations should return a common least denominator in their *getInterval(). * * @author Peter Andersson */ public class AnimationEngine implements Runnable { /** Thread running flag */ protected volatile boolean m_running = true; /** Vector with current animations, also used as lock for animations */ protected Vector m_animations = new Vector(); /** Time in millis between each animation update */ protected long m_animationInterval = Long.MAX_VALUE; /** The graphics context */ protected RepaintRequestable m_canvas; /** * Creates an animation engine for specified canvas. * @param canvas The canvas that will be animated upon. */ public AnimationEngine(RepaintRequestable canvas) { m_canvas = canvas; } /** * Updates all animations. Only updates animations * that has passed their interval time. * @return if a repaint is requested or not. */ protected boolean animate() { Animation a; boolean repaint = false; synchronized (m_animations) { long t = System.currentTimeMillis(); m_animationInterval = Long.MAX_VALUE; for (int i = m_animations.size() - 1; i >= 0; i--) { a = (Animation) m_animations.elementAt(i); long interval = a.getInterval(); if (t - a.getLastInvoke() >= interval) { a.callNext(t); repaint = true; } if (a.isFinished()) { a.onExit(); m_animations.removeElement(a); } else { if (interval < m_animationInterval) m_animationInterval = interval; } } } return repaint; } /** * Adds an animation. * @param a The animation to add */ public void addAnimation(Animation a) { synchronized (m_animations) { m_animations.insertElementAt(a, 0); if (m_animationInterval > a.getInterval()) { m_animationInterval = a.getInterval(); } m_animations.notifyAll(); a.onStart(); } m_canvas.repaint(); } /** * Removes an animation. * @param anim The animation to remove */ public void remove(Animation anim) { synchronized (m_animations) { m_animations.removeElement(anim); } } /** * Removes all animations */ public void removeAll() { synchronized (m_animations) { m_animations.removeAllElements(); } } /** * Shuts down the animation engine. */ public void shutdown() { m_running = false; } /** * Paints all animations on specified graphics context * @param g The graphics context */ public void paint(Graphics g) { synchronized (m_animations) { for (int i = m_animations.size() - 1; i >= 0; i--) { ((Animation) m_animations.elementAt(i)).paint(g); } } } // Runnable impl /** * Updates all animations in queue if needed, * and waits minimum amount of time as declared * by animations. */ public void run() { try { boolean repaintRequest = false; while (m_running) { repaintRequest = false; if (m_canvas.isShown() && !m_animations.isEmpty()) { repaintRequest = animate(); } else { synchronized (m_animations) { try { m_animations.wait(500); } catch (InterruptedException e1) {} } } if (m_canvas.isShown()) { if (repaintRequest) m_canvas.commitRepaint(); synchronized (m_animations) { try { m_animations.wait(Math.min(m_animationInterval, 500)); } catch (InterruptedException e) {} } } if (!m_running) { m_animations = null; } } } catch (Throwable t) { System.err.println("Error in anim thread"); t.printStackTrace(); } } }