001: /*
002: * Copyright (c) 2001-2006 JGoodies Karsten Lentzsch. All Rights Reserved.
003: *
004: * Redistribution and use in source and binary forms, with or without
005: * modification, are permitted provided that the following conditions are met:
006: *
007: * o Redistributions of source code must retain the above copyright notice,
008: * this list of conditions and the following disclaimer.
009: *
010: * o Redistributions in binary form must reproduce the above copyright notice,
011: * this list of conditions and the following disclaimer in the documentation
012: * and/or other materials provided with the distribution.
013: *
014: * o Neither the name of JGoodies Karsten Lentzsch nor the names of
015: * its contributors may be used to endorse or promote products derived
016: * from this software without specific prior written permission.
017: *
018: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
019: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
020: * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
021: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
022: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
023: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
024: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
025: * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
026: * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
027: * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
028: * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
029: */
030:
031: package com.jgoodies.animation;
032:
033: import java.awt.event.ActionEvent;
034: import java.awt.event.ActionListener;
035:
036: import javax.swing.Timer;
037:
038: /**
039: * Starts and stops an animation and triggers
040: * the animation at a given frame rate.
041: *
042: * @author Karsten Lentzsch
043: * @version $Revision: 1.1 $
044: */
045: public final class Animator implements ActionListener {
046:
047: private final Animation animation;
048: private final Timer timer;
049: private final int framesPerSecond;
050:
051: private long startTime;
052: private long elapsedTime = 0;
053:
054: // Instance Creation *****************************************************
055:
056: /**
057: * Constructs an Animator for the given animation and frame rate.
058: *
059: * @param animation the animation to animate
060: * @param framesPerSecond the desired frame rate
061: * @throws NullPointerException if the animation is <code>null</code>
062: * @throws IllegalArgumentException if the frame rate is non-positive
063: */
064: public Animator(Animation animation, int framesPerSecond) {
065: if (animation == null)
066: throw new NullPointerException(
067: "The animation must not be null.");
068:
069: if (framesPerSecond <= 0)
070: throw new IllegalArgumentException(
071: "The frame rate must be positive.");
072:
073: this .animation = animation;
074: this .framesPerSecond = framesPerSecond;
075: this .timer = createTimer(framesPerSecond);
076: }
077:
078: // ************************************************************************
079:
080: /**
081: * Returns the animator's animation.
082: *
083: * @return the animator's animation
084: */
085: public Animation animation() {
086: return animation;
087: }
088:
089: /**
090: * Returns the desired frame rate.
091: *
092: * @return the desired frame rate per second
093: */
094: public int framesPerSecond() {
095: return framesPerSecond;
096: }
097:
098: /**
099: * Returns the elapsed time since animation start.
100: *
101: * @return time elapsed since the animation start
102: */
103: public long elapsedTime() {
104: if (!timer.isRunning())
105: return elapsedTime;
106: long now = System.currentTimeMillis();
107: if (startTime == -1) {
108: startTime = now;
109: }
110: return now - startTime + elapsedTime;
111: }
112:
113: /**
114: * Starts the animator and in turn the animation.
115: */
116: public void start() {
117: if (!timer.isRunning()) {
118: registerStopListener();
119: startTime = -1;
120: timer.start();
121: }
122: }
123:
124: /**
125: * Stops the animator.
126: */
127: public void stop() {
128: if (timer.isRunning()) {
129: elapsedTime = elapsedTime();
130: timer.stop();
131: }
132: }
133:
134: /**
135: * Implements the ActionListener interface used by the Timer.
136: *
137: * @param e the action event
138: */
139: public void actionPerformed(ActionEvent e) {
140: // System.out.println("t=" + elapsedTime());
141: animation.animate(elapsedTime());
142: }
143:
144: /**
145: * Returns a string representation for the animator.
146: *
147: * @return a string representation for the animator
148: */
149: public String toString() {
150: return "elapsedTime=" + elapsedTime() + "; fps="
151: + framesPerSecond;
152: }
153:
154: // Helper Code ************************************************************
155:
156: /**
157: * Creates and configures a <code>Timer</code> object.
158: *
159: * @param fps the frames per second
160: * @return a <code>Timer</code> with the specified frame rate
161: */
162: private Timer createTimer(int fps) {
163: int delay = 1000 / fps;
164:
165: Timer aTimer = new Timer(delay, this );
166: aTimer.setInitialDelay(0);
167: aTimer.setCoalesce(true);
168: return aTimer;
169: }
170:
171: /**
172: * Registers a listener that stops the animator if the animation stopped.
173: */
174: private void registerStopListener() {
175: animation.addAnimationListener(new AnimationAdapter() {
176: public void animationStopped(AnimationEvent e) {
177: //System.out.println("All animations stopped.");
178: stop();
179: //animation.animate(animation.duration());
180: }
181: });
182: }
183:
184: }
|