vmm.core
Class ThreadedAnimation

java.lang.Object
  extended by vmm.core.ThreadedAnimation
All Implemented Interfaces:
Animation
Direct Known Subclasses:
OsculatingCircleAnimation, ParallelCurveAnimation

public abstract class ThreadedAnimation
extends java.lang.Object
implements Animation

An animation that runs in its own thread, separate from the Swing user interface thread. Because Swing is not thread-safe and the animation runs in its own thread, it is not safe to call arbitrary Swing and Graphics2D methods. (If it is necessary to call them, the invokeAndWait or invokeLater methods from class javax.swing.SwingUtilities can be used.) However, calling repaint is OK. Since setting parameter values and adding or removing decorations generate calls to repaint, they are also safe. Note that an animation does not start running automatically, but only when its start() method is called.

To create a ThreadedAnimation, it is usually only necessary to create a subclass and implement runAnimation(), the single abstract method defined in this class. This method is a script for the animation, which is run from beginning to end. When this method returns, the animation ends; if the method never returns, then the animation must be canceled by some external agent that calls its cancel method.

The runAnimation method can call the pause(int) method to insert a pause into the animation. Behind the scenes, this method also checks to see whether the animation has been canceled. If so, it throws an exception that aborts the animation. To avoid delays between the time when the animation's cancel method is called and tha time when the animation actually stops, it is important that pause be called regularly. If no delay is desired, pause can be called with a parameter of zero.

Some animations will have some "clean-up" to do when the animation ends, whether it ends because the runAnimation method returns or because it has been canceled. to make sure that the clean-up is done in all cases, it is advisable to do the clean-up in a finally clause in the runAnimation method. For a simple example of this, see OsculatingCircleAnimation.runAnimation().

A ThreadedAnimation emits ChangeEvents when it is started and when it ends. A ChangeListener can tell which event generated the ChangeEvent by calling the isRunning method of the animation. Note that in some circumstances, an alternative method for doing set-up and clean-up for the animation is to install a ChangeListener that does the set-up/clean-up in response to ChangeEvents.


Nested Class Summary
protected  class ThreadedAnimation.AnimationCanceledException
          A trivial exception class that exists only to make it possible to cancel ThreadAnimations.
 
Constructor Summary
ThreadedAnimation()
           
 
Method Summary
 void addChangeListener(javax.swing.event.ChangeListener listener)
          Add a ChangeListener to this animation.
 void cancel()
          Cancels the animation.
protected  void fireAnimationChangeEvent()
          Sends a ChangeEvent to any registered ChangeListeners.
 java.lang.String getStatusText(boolean running)
          Returns null to indicate that the default text ("Animation Running" or "Animation Paused" in the English version) should be shown in the display's status bar.
 double getTimeDilation()
          Returns the time dilation factor that is currently set for this animation.
 boolean isPaused()
          Tests whether the animation is paused.
 boolean isRunning()
          Tests whether the animation is running.
protected  void pause(int milliseconds)
          Can be called in runAnimation to insert a delay into an animation.
 void removeChangeListener(javax.swing.event.ChangeListener listener)
          Remove a ChangeListener from the animation, if it is currently registered as a listener.
protected abstract  void runAnimation()
          The animation consists of running this method.
 void setPaused(boolean paused)
          Pauses or unpauses a running animation.
 void setTimeDilation(double dilationFactor)
          Slows down or speeds up the animation by multiplying all delay times (as specified in the parameter the pause method) by a time dilation factor.
 void start()
          This method must be called to start the animation running.
 boolean wasCanceled()
          Tests whether the animation has been canceled.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

ThreadedAnimation

public ThreadedAnimation()
Method Detail

runAnimation

protected abstract void runAnimation()
The animation consists of running this method. To create an animation, it is generally only necessary to implement this method. This method should call pause regularly. The animation ends when this method returns or the first time pause is called after the cancel method has been called; the pause method generates an ThreadedAnimation.AnimationCanceledException in this case. If there is clean-up that must be done when the animation ends, it is advisable to do it in a finally clause in this method.

(Note that if some error other than an AnimationCanceledException occurs during the animation, it will also abort the animation. Since this is presumably a programming error, a stack trace for the exception is printed to standard output.)

See Also:
pause(int), cancel()

pause

protected void pause(int milliseconds)
              throws ThreadedAnimation.AnimationCanceledException
Can be called in runAnimation to insert a delay into an animation. This method also checks whether the cancel method has been called. If so, it will throw an excpetion of type ThreadedAnimation.AnimationCanceledException. This method can be called with a parameter of zero to check for cancelation without inserting a delay (in this case, it calls Thread.yield to give other threads that are waiting for CPU time an opportunity to run. It is important that this method be called regularly during the course of an animation so that cancelations will take effect in a timely manner.

In addition to checking for cancellation, this method also checks to see whether the animation has been paused by calling its setPaused method. If so, this method will wait for the animtion to be unpaused before returning. Again, it is important for pause to be called regularly for setPaused to take effect in a timely way.

Parameters:
milliseconds - a delay equal to this many milliseconds, if the animation is running at normal speed, is inserted into the animation. If a time dilation factor other than 1 has been set, however, then this parameter is multiplied by the time dilation factor to give the actual number of milliseconds used in the delay. A delay of zero will cause Thread.yield to be called, which gives other threads a chance to run.
Throws:
ThreadedAnimation.AnimationCanceledException
See Also:
setTimeDilation(double), runAnimation(), cancel(), setPaused(boolean)

start

public void start()
This method must be called to start the animation running. An animation does not start automatically, but only when this method is called. If the animation is already running, this has no effect. If the animation has already run and ended, this will restart thea animation from the beginning. The animation will run until the runAnimation ends or until the animation is canceled.

Specified by:
start in interface Animation

setPaused

public void setPaused(boolean paused)
Pauses or unpauses a running animation. If the animation is not running, this has no effect.

Specified by:
setPaused in interface Animation
Parameters:
paused - if true, then the animation is paused; if false, then the animation is unpaused

isPaused

public boolean isPaused()
Tests whether the animation is paused. Only a running animation can be paused.

Specified by:
isPaused in interface Animation
Returns:
returns true if the animation is running but is in a paused state; returns false if it is not running or if it is running but is not paused.

cancel

public void cancel()
Cancels the animation. The animation will be stopped as soon as possible (that is, the next time the pause(int) method is called by runAnimation()). If the animation is not running, this has no effect.

Specified by:
cancel in interface Animation

isRunning

public boolean isRunning()
Tests whether the animation is running.

Specified by:
isRunning in interface Animation

wasCanceled

public boolean wasCanceled()
Tests whether the animation has been canceled. This can be called after the animation ends to determine whether the animation ended on its own or because it was canceled.


setTimeDilation

public void setTimeDilation(double dilationFactor)
Slows down or speeds up the animation by multiplying all delay times (as specified in the parameter the pause method) by a time dilation factor. Note that the dilation applies only to delay times, not to processing times, so the animation speed is only approximately multiplied by the dilation factor. In particular, only a limited amout of speed-up can be obtained, no matter how close to zero you make the dilation factor. The default value of the time dilation factor is 1, which corresponds to normal run speed.

Specified by:
setTimeDilation in interface Animation
Parameters:
dilationFactor - delay times for the pause method are multiplied by this factor to give the actual time delay. A dilationFactor less than zero is treated as zero.
See Also:
pause(int)

getTimeDilation

public double getTimeDilation()
Returns the time dilation factor that is currently set for this animation.

Specified by:
getTimeDilation in interface Animation
See Also:
setTimeDilation(double)

addChangeListener

public void addChangeListener(javax.swing.event.ChangeListener listener)
Add a ChangeListener to this animation. Change events are sent when the animation stops and when it stops for any reason. The ChangeListener can distinguish the two events by calling the isRunning method, which will retrun true if the animation is starting and false if the animation has ended.

Specified by:
addChangeListener in interface Animation
Parameters:
listener - a ChangeListener that is registered to receive change events from this animation.

removeChangeListener

public void removeChangeListener(javax.swing.event.ChangeListener listener)
Remove a ChangeListener from the animation, if it is currently registered as a listener.

Specified by:
removeChangeListener in interface Animation
Parameters:
listener - to be de-registered as a ChangeListener from this animation.

fireAnimationChangeEvent

protected void fireAnimationChangeEvent()
Sends a ChangeEvent to any registered ChangeListeners. This is not likely to be used in a subclass, unless the subclass wants to send additional change events besides those sent when the animation starts and stops.


getStatusText

public java.lang.String getStatusText(boolean running)
Returns null to indicate that the default text ("Animation Running" or "Animation Paused" in the English version) should be shown in the display's status bar. This can be overridden in a subclass to show a different status message.

Specified by:
getStatusText in interface Animation
Parameters:
running - tells whether the animation is currently running.
Returns:
the text to displayed, or null to use the default text "Animation Running" or "Animation Paused"