timingframework_1.0.orig/0002755000175000017500000000000011500061723014341 5ustar tonytonytimingframework_1.0.orig/org/0002755000175000017500000000000010624714514015141 5ustar tonytonytimingframework_1.0.orig/org/jdesktop/0002755000175000017500000000000010624714514016764 5ustar tonytonytimingframework_1.0.orig/org/jdesktop/animation/0002755000175000017500000000000010624714514020743 5ustar tonytonytimingframework_1.0.orig/org/jdesktop/animation/timing/0002755000175000017500000000000010663117072022231 5ustar tonytonytimingframework_1.0.orig/org/jdesktop/animation/timing/TimingSource.java0000644000175000017500000001261310603300120025463 0ustar tonytony/** * Copyright (c) 2007, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing; import java.util.ArrayList; /** * This class provides a generic wrapper for arbitrary * Timers that may be used with the Timing Framework. * Animator creates its own internal TimingSource by default, * but an Animator can be directed to use a different * TimingSource by calling {@link Animator#setTimer(TimingSource)}. * * The implementation details of any specific timer may * vary widely, but any timer should be able to expose * the basic capabilities used in this interface. Animator * depends on these capabilities for starting, stopping, * and running any TimingSource. * * The usage of an external TimingSource object for sending in timing * events to an Animator is to implement this interface appropriately, * pass in that object to {@link Animator#setTimer(TimingSource)}, * which adds the Animator as a listener to the TimingSource object, * and then send in any later timing events from the object to the * protected method {@link #timingEvent()}, which will send these timing * events to all listeners. * * @author Chet */ public abstract class TimingSource { // listeners that will receive timing events private ArrayList listeners = new ArrayList(); /** * Starts the TimingSource */ public abstract void start(); /** * Stops the TimingSource */ public abstract void stop(); /** * Sets the delay between callback events. This * will be called by Animator if its * {@link Animator#setResolution(int) setResolution(int)} * method is called. Note that the actual resolution may vary, * according to the resolution of the timer used by the framework as well * as system load and configuration; this value should be seen more as a * minimum resolution than a guaranteed resolution. * @param resolution delay, in milliseconds, between * each timing event callback. * @throws IllegalArgumentException resolution must be >= 0 * @see Animator#setResolution(int) */ public abstract void setResolution(int resolution); /** * Sets delay which should be observed by the * TimingSource after a call to {@link #start()}. Some timers may not be * able to adhere to specific resolution requests * @param delay delay, in milliseconds, to pause before * starting timing events. * @throws IllegalArgumentException resolution must be >= 0 * @see Animator#setStartDelay(int) */ public abstract void setStartDelay(int delay); /** * Adds a TimingEventListener to the set of listeners that * receive timing events from this TimingSource. * @param listener the listener to be added. */ public final void addEventListener(TimingEventListener listener) { synchronized(listeners) { if (!listeners.contains(listener)) { listeners.add(listener); } } } /** * Removes a TimingEventListener from the set of listeners that * receive timing events from this TimingSource. * @param listener the listener to be removed. */ public final void removeEventListener(TimingEventListener listener) { synchronized(listeners) { listeners.remove(listener); } } /** * Subclasses call this method to post timing events to this * object's {@link TimingEventListener} objects. */ protected final void timingEvent() { synchronized(listeners) { for (TimingEventListener listener : listeners) { listener.timingSourceEvent(this); } } } } timingframework_1.0.orig/org/jdesktop/animation/timing/TimingTargetAdapter.java0000644000175000017500000000661710520152566027002 0ustar tonytony/** * Copyright (c) 2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing; /** * Implements the {@link TimingTarget} interface, providing stubs for all * TimingTarget methods. Subclasses may extend this adapter rather than * implementing the TimingTarget interface if they only care about a * subset of the events that TimingTarget provides. For example, * sequencing animations may only require monitoring the * {@link TimingTarget#end} method, so subclasses of this adapter * may ignore the other methods such as timingEvent. * * @author Chet */ public class TimingTargetAdapter implements TimingTarget { /** * This method will receive all of the timing events from an Animator * during an animation. The fraction is the percent elapsed (0 to 1) * of the current animation cycle. * @param fraction the fraction of completion between the start and * end of the current cycle. Note that on reversing cycles * ({@link Animator.Direction#BACKWARD}) the fraction decreases * from 1.0 to 0 on backwards-running cycles. Note also that animations * with a duration of {@link Animator#INFINITE INFINITE} will call * timingEvent with an undefined value for fraction, since there is * no fraction that makes sense if the animation has no defined length. * @see Animator.Direction */ public void timingEvent(float fraction) {} /** * Called when the Animator's animation begins. This provides a chance * for targets to perform any setup required at animation start time. */ public void begin() {} /** * Called when the Animator's animation ends */ public void end() {} /** * Called when the Animator repeats the animation cycle */ public void repeat() {} } timingframework_1.0.orig/org/jdesktop/animation/timing/TimingTarget.java0000644000175000017500000000646010515772530025500 0ustar tonytony/** * Copyright (c) 2005-2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing; /** * This interface provides the methods which * are called by Animator during the course of a timing * sequence. Applications * that wish to receive timing events will either create a subclass * of TimingTargetAdapter and override or they can create or use * an implementation of TimingTarget. A TimingTarget can be passed * into the constructor of Animator or set later with the * {@link Animator#addTarget(TimingTarget)} * method. Any Animator may have multiple TimingTargets. */ public interface TimingTarget { /** * This method will receive all of the timing events from an Animator * during an animation. The fraction is the percent elapsed (0 to 1) * of the current animation cycle. * @param fraction the fraction of completion between the start and * end of the current cycle. Note that on reversing cycles * ({@link Animator.Direction#BACKWARD}) the fraction decreases * from 1.0 to 0 on backwards-running cycles. Note also that animations * with a duration of {@link Animator#INFINITE INFINITE} will call * timingEvent with an undefined value for fraction, since there is * no fraction that makes sense if the animation has no defined length. * @see Animator.Direction */ public void timingEvent(float fraction); /** * Called when the Animator's animation begins. This provides a chance * for targets to perform any setup required at animation start time. */ public void begin(); /** * Called when the Animator's animation ends */ public void end(); /** * Called when the Animator repeats the animation cycle */ public void repeat(); } timingframework_1.0.orig/org/jdesktop/animation/timing/Animator.java0000644000175000017500000012062510645706000024645 0ustar tonytony/** * Copyright (c) 2005-2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing; import javax.swing.Timer; import java.awt.event.*; import java.util.ArrayList; import org.jdesktop.animation.timing.interpolation.Interpolator; import org.jdesktop.animation.timing.interpolation.LinearInterpolator; /** * This class controls animations. Its constructors and various * set methods control the parameters under which animations are run, * and the other methods support starting and stopping the animation. * The parameters of this class use the concepts of a "cycle" (the base * animation) and an "envelope" that controls how the cycle is started, * ended, and repeated. *

* Most of the methods here are simle getters/setters for the properties * used by Animator. Typical animations will simply use one of the * two constructors (depending on whether you are constructing a repeating * animation), optionally call any of the set* methods to alter * any of the other parameters, and then call start() to run the animation. * For example, this animation will run for 1 second, calling your * {@link TimingTarget} with timing events when the animation is started, * running, and stopped: *

 *  Animator animator = new Animator(1000, myTarget);
 *  animator.start();
 * 
* The following variation will run a half-second animation 4 times, * reversing direction each time: *
 *  Animator animator = new Animator(500, 4, RepeatBehavior.REVERSE, myTarget);
 *  animator.start();
 * 
* More complex animations can be created through using the properties * in Animator, such as {@link Animator#setAcceleration acceleration} and {@link * Animator#setDeceleration}. More automated animations can be created and run * using the {@link org.jdesktop.animation.timing.triggers triggers} * package to control animations through events and {@link * org.jdesktop.animation.timing.interpolation.PropertySetter} to * handle animating object properties. */ public final class Animator { private TimingSource timer; // Currently uses Swing timer. This could change // in the future to use a more general mechanism // (and one of better timing resolution). An // important advantage to the Swing timer is that // it ensures that we receive and send our timing // events on the Event Dispatch Thread, which makes // it easier to use the framework for GUI // animations. private TimingSource swingTimer; private TimingSourceTarget timingSourceTarget; private ArrayList targets = new ArrayList(); // Animators may have // multiple targets private long startTime; // Tracks original Animator start time private long currentStartTime; // Tracks start time of current cycle private int currentCycle = 0; // Tracks number of cycles so far private boolean intRepeatCount = true; // for typical cases // of repeated cycles private boolean timeToStop = false; // This gets triggered during // fraction calculation private boolean hasBegun = false; private long pauseBeginTime = 0; // Used for pause/resume private boolean running = false; // Used for isRunning() // Private variables to hold the internal "envelope" values that control // how the cycle is started, ended, and repeated. private double repeatCount = 1.0; private int startDelay; private RepeatBehavior repeatBehavior = RepeatBehavior.REVERSE; private EndBehavior endBehavior = EndBehavior.HOLD; // Private variables to hold the internal values of the base // animation (the cycle) private int duration; private int resolution = 20; private float acceleration = 0; private float deceleration = 0.0f; private float startFraction = 0.0f; private Direction direction = Direction.FORWARD; // Direction of each cycle private Interpolator interpolator = LinearInterpolator.getInstance(); /** * EndBehavior determines what happens at the end of the animation. * @see #setEndBehavior */ public static enum EndBehavior { /** Timing sequence will maintain its final value at the end */ HOLD, /** Timing sequence should reset to the initial value at the end */ RESET, }; /** * Direction is used to set the initial direction in which the * animation starts. * * @see #setStartDirection */ public static enum Direction { /** * cycle proceeds forward */ FORWARD, /** cycle proceeds backward */ BACKWARD, }; /** * RepeatBehavior determines how each successive cycle will flow. * @see #setRepeatBehavior */ public static enum RepeatBehavior { /** * Each repeated cycle proceeds in the same direction as the * previous one */ LOOP, /** * Each cycle proceeds in the opposite direction as the * previous one */ REVERSE }; /** * Used to specify unending duration or repeatCount * @see #setDuration * @see #setRepeatCount * */ public static final int INFINITE = -1; private void validateRepeatCount(double repeatCount) { if (repeatCount < 1 && repeatCount != INFINITE) { throw new IllegalArgumentException("repeatCount (" + repeatCount + ") cannot be <= 0"); } } /** * Constructor: this is a utility constructor * for a simple timing sequence that will run for * duration length of time. This variant takes no * TimingTarget, and is equivalent to calling {@link #Animator(int, * TimingTarget)} with a TimingTarget of null. * * @param duration The length of time that this will run, in milliseconds. */ public Animator(int duration) { this(duration, null); } /** * Constructor: this is a utility constructor * for a simple timing sequence that will run for * duration length of time. * * @param duration The length of time that this will run, in milliseconds. * @param target TimingTarget object that will be called with * all timing events. Null is acceptable, but no timingEvents will be * sent to any targets without future calls to {@link #addTarget}. */ public Animator(int duration, TimingTarget target) { this.duration = duration; addTarget(target); /** * hack workaround for starting the Toolkit thread before any Timer stuff * javax.swing.Timer uses the Event Dispatch Thread, which is not * created until the Toolkit thread starts up. Using the Swing * Timer before starting this stuff starts up may get unexpected * results (such as taking a long time before the first timer * event). */ java.awt.Toolkit tk = java.awt.Toolkit.getDefaultToolkit(); // Create internal Timer object swingTimer = new SwingTimingSource(); timer = swingTimer; } /** * Constructor that sets the most common properties of a * repeating animation. * @param duration the length of each animation cycle, in milliseconds. * This value can also be {@link #INFINITE} for animations that have no * end. Note that fractions sent out with such unending animations will * be undefined since there is no fraction of an infinitely long cycle. * @param repeatCount the number of times the animation cycle will repeat. * This is a positive value, which allows a non-integral number * of repetitions (allowing an animation to stop mid-cycle, for example). * This value can also be {@link #INFINITE}, indicating that the animation * will continue repeating forever, or until manually stopped. * @param repeatBehavior {@link RepeatBehavior} of each successive * cycle. A value of null is equivalent to RepeatBehavior.REVERSE. * @param target TimingTarget object that will be called with * all timing events. Null is acceptable, but no timingEvents will be * sent to any targets without future calls to {@link #addTarget}. * @throws IllegalArgumentException if any parameters have invalid * values * @see Animator#INFINITE * @see Direction * @see EndBehavior */ public Animator(int duration, double repeatCount, RepeatBehavior repeatBehavior, TimingTarget target) { this(duration, target); // First, check for bad parameters validateRepeatCount(repeatCount); this.repeatCount = repeatCount; this.repeatBehavior = (repeatBehavior != null) ? repeatBehavior : RepeatBehavior.REVERSE; // Set convenience variable: do we have an integer number of cycles? intRepeatCount = (Math.rint(repeatCount) == repeatCount); } /** * Returns the initial direction for the animation. * @return direction that the initial animation cycle will be moving */ public Direction getStartDirection() { return direction; } /** * Sets the startDirection for the initial animation cycle. The default * startDirection is {@link Direction#FORWARD FORWARD}. * * @param startDirection initial animation cycle direction * @see #isRunning() * @throws IllegalStateException if animation is already running; this * parameter may only be changed prior to starting the animation or * after the animation has ended */ public void setStartDirection(Direction startDirection) { throwExceptionIfRunning(); this.direction = startDirection; } /** * Returns the interpolator for the animation. * @return interpolator that the initial animation cycle uses */ public Interpolator getInterpolator() { return interpolator; } /** * Sets the interpolator for the animation cycle. The default * interpolator is {@link LinearInterpolator}. * @param interpolator the interpolation to use each animation cycle * @throws IllegalStateException if animation is already running; this * parameter may only be changed prior to starting the animation or * after the animation has ended * @see #isRunning() */ public void setInterpolator(Interpolator interpolator) { throwExceptionIfRunning(); this.interpolator = interpolator; } /** * Sets the fraction of the timing cycle that will be spent accelerating * at the beginning. The default acceleration value is 0 (no acceleration). * @param acceleration value from 0 to 1 * @throws IllegalArgumentException acceleration value must be between 0 and * 1, inclusive. * @throws IllegalArgumentException acceleration cannot be greater than * (1 - deceleration) * @throws IllegalStateException if animation is already running; this * parameter may only be changed prior to starting the animation or * after the animation has ended * @see #isRunning() * @see #setDeceleration(float) */ public void setAcceleration(float acceleration) { throwExceptionIfRunning(); if (acceleration < 0 || acceleration > 1.0f) { throw new IllegalArgumentException("Acceleration value cannot lie" + " outside [0,1] range"); } if (acceleration > (1.0f - deceleration)) { throw new IllegalArgumentException("Acceleration value cannot be" + " greater than (1 - deceleration)"); } this.acceleration = acceleration; } /** * Sets the fraction of the timing cycle that will be spent decelerating * at the end. The default deceleration value is 0 (no deceleration). * @param deceleration value from 0 to 1 * @throws IllegalArgumentException deceleration value must be between 0 and * 1, inclusive. * @throws IllegalArgumentException deceleration cannot be greater than * (1 - acceleration) * @throws IllegalStateException if animation is already running; this * parameter may only be changed prior to starting the animation or * after the animation has ended * @see #isRunning() * @see #setAcceleration(float) */ public void setDeceleration(float deceleration) { throwExceptionIfRunning(); if (deceleration < 0 || deceleration > 1.0f) { throw new IllegalArgumentException("Deceleration value cannot lie" + " outside [0,1] range"); } if (deceleration > (1.0f - acceleration)) { throw new IllegalArgumentException("Deceleration value cannot be" + " greater than (1 - acceleration)"); } this.deceleration = deceleration; } /** * Returns the current value of acceleration property * @return acceleration value */ public float getAcceleration() { return acceleration; } /** * Returns the current value of deceleration property * @return deceleration value */ public float getDeceleration() { return deceleration; } /** * Adds a TimingTarget to the list of targets that get notified of each * timingEvent. This can be done at any time before, during, or after the * animation has started or completed; the new target will begin * having its TimingTarget methods called as soon as it is added. * If target is already on the list of targets in this Animator, it * is not added again (there will be only one instance of any given * target in any Animator's list of targets). * @param target TimingTarget to be added to the list of targets that * get notified by this Animator of all timing events. Target cannot * be null. */ public void addTarget(TimingTarget target) { if (target != null) { synchronized (targets) { if (!targets.contains(target)) { targets.add(target); } } } } /** * Removes the specified TimingTarget from the list of targets that get * notified of each timingEvent. This can be done at any time before, * during, or after the animation has started or completed; the * target will cease having its TimingTarget methods called as soon * as it is removed. * @param target TimingTarget to be removed from the list of targets that * get notified by this Animator of all timing events. */ public void removeTarget(TimingTarget target) { synchronized (targets) { targets.remove(target); } } /** * Private utility to throw an exception if the animation is running. This * is used by all of the property-setting methods to ensure that the * properties are not being changed mid-stream. */ private void throwExceptionIfRunning() { if (isRunning()) { throw new IllegalStateException("Cannot perform this operation " + "while Animator is running"); } } /** * Returns the current resolution of the animation. This helps * determine the maximum frame rate at which the animation will run. * @return the resolution, in milliseconds, of the timer */ public int getResolution() { return resolution; } /** * Sets the resolution of the animation * @param resolution the amount of time between timing events of the * animation, in milliseconds. Note that the actual resolution may vary, * according to the resolution of the timer used by the framework as well * as system load and configuration; this value should be seen more as a * minimum resolution than a guaranteed resolution. * @throws IllegalArgumentException resolution must be >= 0 * @throws IllegalStateException if animation is already running; this * parameter may only be changed prior to starting the animation or * after the animation has ended * @see #isRunning() */ public void setResolution(int resolution) { if (resolution < 0) { throw new IllegalArgumentException("resolution must be >= 0"); } throwExceptionIfRunning(); this.resolution = resolution; timer.setResolution(resolution); } /** * Returns the duration of the animation. * @return the length of the animation, in milliseconds. A * return value of -1 indicates an {@link #INFINITE} duration. */ public int getDuration() { return duration; } /** * Sets the duration for the animation * @param duration the length of the animation, in milliseconds. This * value can also be {@link #INFINITE}, meaning the animation will run * until manually stopped. * @throws IllegalStateException if animation is already running; this * parameter may only be changed prior to starting the animation or * after the animation has ended * @see #isRunning() * @see #stop() */ public void setDuration(int duration) { throwExceptionIfRunning(); this.duration = duration; } /** * Returns the number of times the animation cycle will repeat. * @return the number of times the animation cycle will repeat. */ public double getRepeatCount() { return repeatCount; } /** * Sets the number of times the animation cycle will repeat. The default * value is 1. * @param repeatCount Number of times the animation cycle will repeat. * This value may be >= 1 or {@link #INFINITE} for animations that repeat * indefinitely. The value may be fractional if the animation should * stop at some fractional point. * @throws IllegalArgumentException if repeatCount is not >=1 or * INFINITE. * @throws IllegalStateException if animation is already running; this * parameter may only be changed prior to starting the animation or * after the animation has ended * @see #isRunning() */ public void setRepeatCount(double repeatCount) { validateRepeatCount(repeatCount); throwExceptionIfRunning(); this.repeatCount = repeatCount; } /** * Returns the amount of delay prior to starting the first animation * cycle after the call to {@link #start}. * @return the duration, in milliseconds, between the call * to start the animation and the first animation cycle actually * starting. * @see #start */ public int getStartDelay() { return startDelay; } /** * Sets the duration of the initial delay between calling {@link #start} * and the start of the first animation cycle. The default value is 0 (no * delay). * @param startDelay the duration, in milliseconds, between the call * to start the animation and the first animation cycle actually * starting. This value must be >= 0. * @throws IllegalArgumentException if startDelay is < 0 * @throws IllegalStateException if animation is already running; this * parameter may only be changed prior to starting the animation or * after the animation has ended * @see #isRunning() */ public void setStartDelay(int startDelay) { if (startDelay < 0) { throw new IllegalArgumentException("startDelay (" + startDelay + ") cannot be < 0"); } throwExceptionIfRunning(); this.startDelay = startDelay; timer.setStartDelay(startDelay); } /** * Returns the {@link RepeatBehavior} of the animation. The default * behavior is REVERSE, meaning that the animation will reverse direction * at the end of each cycle. * @return whether the animation will repeat in the same * direction or will reverse direction each time. */ public RepeatBehavior getRepeatBehavior() { return repeatBehavior; } /** * Sets the {@link RepeatBehavior} of the animation. * @param repeatBehavior the behavior for each successive cycle in the * animation. A null behavior is equivalent to specifying the default: * REVERSE. The default behaviors is HOLD. * @throws IllegalStateException if animation is already running; this * parameter may only be changed prior to starting the animation or * after the animation has ended * @see #isRunning() */ public void setRepeatBehavior(RepeatBehavior repeatBehavior) { throwExceptionIfRunning(); this.repeatBehavior = (repeatBehavior != null) ? repeatBehavior : RepeatBehavior.REVERSE; } /** * Returns the {@link EndBehavior} of the animation, either HOLD to * retain the final value or RESET to take on the initial value. The * default behavior is HOLD. * @return the behavior at the end of the animation */ public EndBehavior getEndBehavior() { return endBehavior; } /** * Sets the behavior at the end of the animation. * @param endBehavior the behavior at the end of the animation, either * HOLD or RESET. A null value is equivalent to the default value of * HOLD. * @throws IllegalStateException if animation is already running; this * parameter may only be changed prior to starting the animation or * after the animation has ended * @see #isRunning */ public void setEndBehavior(EndBehavior endBehavior) { throwExceptionIfRunning(); this.endBehavior = endBehavior; } /** * Returns the fraction that the first cycle will start at. * @return fraction between 0 and 1 at which the first cycle will start. */ public float getStartFraction() { return startFraction; } /** * Sets the initial fraction at which the first animation cycle will * begin. The default value is 0. * @param startFraction * @see #isRunning() * @throws IllegalArgumentException if startFraction is less than 0 * or greater than 1 * @throws IllegalStateException if animation is already running; this * parameter may only be changed prior to starting the animation or * after the animation has ended */ public void setStartFraction(float startFraction) { if (startFraction < 0 || startFraction > 1.0f) { throw new IllegalArgumentException("initialFraction must be " + "between 0 and 1"); } throwExceptionIfRunning(); this.startFraction = startFraction; } /** * Starts the animation * @throws IllegalStateException if animation is already running; this * command may only be run prior to starting the animation or * after the animation has ended */ public void start() { throwExceptionIfRunning(); hasBegun = false; running = true; // Initialize start time variables to current time startTime = (System.nanoTime() / 1000000) + getStartDelay(); if (duration != INFINITE && ((direction == Direction.FORWARD && startFraction > 0.0f) || (direction == Direction.BACKWARD && startFraction < 1.0f))) { float offsetFraction = (direction == Direction.FORWARD) ? startFraction : (1.0f - startFraction); long startDelta = (long)(duration * offsetFraction); startTime -= startDelta; } currentStartTime = startTime; timer.start(); } /** * Returns whether this Animator object is currently running */ public boolean isRunning() { return running; } /** * This method is optional; animations will always stop on their own * if Animator is provided with appropriate values for * duration and repeatCount in the constructor. But if the application * wants to stop the timer mid-stream, this is the method to call. * This call will result in calls to the end() method * of all TimingTargets of this Animator. * @see #cancel() */ public void stop() { timer.stop(); end(); timeToStop = false; running = false; pauseBeginTime = 0; } /** * This method is like the {@link #stop} method, only this one will * not result in a calls to the end() method in all * TimingTargets of this Animation; it simply cancels the Animator * immediately. * @see #stop() */ public void cancel() { timer.stop(); timeToStop = false; running = false; pauseBeginTime = 0; } /** * This method pauses a running animation. No further events are sent to * TimingTargets. A paused animation may be d again by calling the * {@link #resume} method. Pausing a non-running animation has no effect. * * @see #resume() * @see #isRunning() */ public void pause() { if (isRunning()) { pauseBeginTime = System.nanoTime(); running = false; timer.stop(); } } /** * This method resumes a paused animation. Resuming an animation that * is not paused has no effect. * * @see #pause() */ public void resume() { if (pauseBeginTime > 0) { long pauseDelta = (System.nanoTime() - pauseBeginTime) / 1000000; startTime += pauseDelta; currentStartTime += pauseDelta; timer.start(); pauseBeginTime = 0; running = true; } } // // TimingTarget implementations // Note that Animator does not actually implement TimingTarget directly; // it does not want to make public methods of these events. But it uses // the same methods internally to propagate the events to all of the // Animator's targets. // /** * Internal timingEvent method that sends out the event to all targets */ private void timingEvent(float fraction) { synchronized (targets) { for (int i = 0; i < targets.size(); ++i) { TimingTarget target = targets.get(i); target.timingEvent(fraction); } } if (timeToStop) { stop(); } } /** * Internal begin event that sends out the event to all targets */ private void begin() { synchronized (targets) { for (int i = 0; i < targets.size(); ++i) { TimingTarget target = targets.get(i); target.begin(); } } } /** * Internal end event that sends out the event to all targets */ private void end() { synchronized (targets) { for (int i = 0; i < targets.size(); ++i) { TimingTarget target = targets.get(i); target.end(); } } } /** * Internal repeat event that sends out the event to all targets */ private void repeat() { synchronized (targets) { for (int i = 0; i < targets.size(); ++i) { TimingTarget target = targets.get(i); target.repeat(); } } } /** * This method calculates a new fraction value based on the * acceleration and deceleration settings of Animator. It then * passes this value through the interpolator (by default, * a LinearInterpolator) before returning it to the caller (who * will then call the timingEvent() methods in the TimingTargets * with this fraction). */ private float timingEventPreprocessor(float fraction) { // First, take care of acceleration/deceleration factors if (acceleration != 0 || deceleration != 0.0f) { // See the SMIL 2.0 specification for details on this // calculation float oldFraction = fraction; float runRate = 1.0f / (1.0f - acceleration/2.0f - deceleration/2.0f); if (fraction < acceleration) { float averageRunRate = runRate * (fraction / acceleration) / 2; fraction *= averageRunRate; } else if (fraction > (1.0f - deceleration)) { // time spent in deceleration portion float tdec = fraction - (1.0f - deceleration); // proportion of tdec to total deceleration time float pdec = tdec / deceleration; fraction = runRate * (1.0f - ( acceleration / 2) - deceleration + tdec * (2 - pdec) / 2); } else { fraction = runRate * (fraction - (acceleration / 2)); } // clamp fraction to [0,1] since above calculations may // cause rounding errors if (fraction < 0) { fraction = 0; } else if (fraction > 1.0f) { fraction = 1.0f; } } // run the result through the current interpolator return interpolator.interpolate(fraction); } /** * Returns the total elapsed time for the current animation. * @param currentTime value of current time to use in calculating * elapsed time. * @return the total time elapsed between the time * the Animator started and the supplied currentTime. */ public long getTotalElapsedTime(long currentTime) { return (currentTime - startTime); } /** * Returns the total elapsed time for the current animation. Calculates * current time. * @return the total time elapsed between the time * the Animator started and the current time. */ public long getTotalElapsedTime() { long currentTime = System.nanoTime() / 1000000; return getTotalElapsedTime(currentTime); } /** * Returns the elapsed time for the current animation cycle. * @param currentTime value of current time to use in calculating * elapsed time. * @return the time elapsed between the time * this cycle started and the supplied currentTime. */ public long getCycleElapsedTime(long currentTime) { return (currentTime - currentStartTime); } /** * Returns the elapsed time for the current animation cycle. Calculates * current time. * @return the time elapsed between the time * this cycle started and the current time. */ public long getCycleElapsedTime() { long currentTime = System.nanoTime() / 1000000; return getCycleElapsedTime(currentTime); } /** * This method calculates and returns the fraction elapsed of the current * cycle based on the current time * @return fraction elapsed of the current animation cycle */ public float getTimingFraction() { long currentTime = System.nanoTime() / 1000000; long cycleElapsedTime = getCycleElapsedTime(currentTime); long totalElapsedTime = getTotalElapsedTime(currentTime); double currentCycle = (double)totalElapsedTime / duration; float fraction; if (!hasBegun) { // Call begin() first time after calling start() begin(); hasBegun = true; } if ((duration != INFINITE) && (repeatCount != INFINITE) && (currentCycle >= repeatCount)) { // Envelope done: stop based on end behavior switch (endBehavior) { case HOLD: // Make sure we send a final end value if (intRepeatCount) { // If supposed to run integer number of cycles, hold // on integer boundary if (direction == Direction.BACKWARD) { // If we were traveling backward, hold on 0 fraction = 0.0f; } else { fraction = 1.0f; } } else { // hold on final value instead fraction = Math.min(1.0f, ((float)cycleElapsedTime / duration)); } break; case RESET: // RESET requires setting the final value to the start value fraction = 0.0f; break; default: fraction = 0.0f; // should not reach here break; } timeToStop = true; } else if ((duration != INFINITE) && (cycleElapsedTime > duration)) { // Cycle end: Time to stop or change the behavior of the timer long actualCycleTime = cycleElapsedTime % duration; fraction = (float)actualCycleTime / duration; // Set new start time for this cycle currentStartTime = currentTime - actualCycleTime; if (repeatBehavior == RepeatBehavior.REVERSE) { boolean oddCycles = ((int)(cycleElapsedTime / duration) % 2) > 0; if (oddCycles) { // reverse the direction direction = (direction == Direction.FORWARD) ? Direction.BACKWARD : Direction.FORWARD; } if (direction == Direction.BACKWARD) { fraction = 1.0f - fraction; } } repeat(); } else { // mid-stream: calculate fraction of animation between // start and end times and send fraction to target fraction = 0.0f; if (duration != INFINITE) { // Only limited duration animations need a fraction fraction = (float)cycleElapsedTime / duration; if (direction == Direction.BACKWARD) { // If this is a reversing cycle, want to know inverse // fraction; how much from start to finish, not // finish to start fraction = (1.0f - fraction); } // Clamp fraction in case timing mechanism caused out of // bounds value fraction = Math.min(fraction, 1.0f); fraction = Math.max(fraction, 0.0f); } } return timingEventPreprocessor(fraction); } /** * Sets a new TimingSource that will supply the timing * events to this Animator. Animator uses an internal * TimingSource by default and most developers will probably not * need to change this default behavior. But for those wishing to * supply their own timer, this method can be called to * tell Animator to use a different TimingSource instead. Setting a * new TimingSource implicitly removes this Animator as a listener * to any previously-set TimingSource object. * * @param timer the object that will provide the * timing events to Animator. A value of null is * equivalent to telling Animator to use its default internal * TimingSource object. * @throws IllegalStateException if animation is already running; this * parameter may only be changed prior to starting the animation or * after the animation has ended. */ public synchronized void setTimer(TimingSource timer) { throwExceptionIfRunning(); if (this.timer != swingTimer) { // Remove this Animator from any previously-set external timer this.timer.removeEventListener(timingSourceTarget); } if (timer == null) { this.timer = swingTimer; } else { this.timer = timer; if (timingSourceTarget == null) { timingSourceTarget = new TimingSourceTarget(); } timer.addEventListener(timingSourceTarget); } // sync this new timer with existing timer properties this.timer.setResolution(resolution); this.timer.setStartDelay(startDelay); } /** * This package-private class will be called by TimingSource.timingEvent() * when a timer sends in timing events to this Animator. */ class TimingSourceTarget implements TimingEventListener { public void timingSourceEvent(TimingSource timingSource) { // Make sure that we are being called by the current timer // and that the animation is actually running if ((timer == timingSource) && running) { timingEvent(getTimingFraction()); } } } /** * Implementation of internal timer, which uses the Swing Timer class. * Note that we do not bother going through the TimingSource.timingEvent() * class with our timing events; they go through the TimerTarget * ActionListener implementation and then directly to timingEvent(fraction). */ private class SwingTimingSource extends TimingSource { Timer timer; // Swing timer public SwingTimingSource() { timer = new Timer(resolution, new TimerTarget()); timer.setInitialDelay(0); } public void start() { timer.start(); } public void stop() { timer.stop(); } public void setResolution(int resolution) { timer.setDelay(resolution); } public void setStartDelay(int delay) { timer.setInitialDelay(delay); } } /** * Internal implementation detail: we happen to use javax.swing.Timer * currently, which sends its timing events to an ActionListener. * This internal private class is our ActionListener that traps * these calls and forwards them to the Animator.timingEvent(fraction) * method. */ private class TimerTarget implements ActionListener { public void actionPerformed(ActionEvent e) { timingEvent(getTimingFraction()); } } } timingframework_1.0.orig/org/jdesktop/animation/timing/package.html0000644000175000017500000000142110515740762024512 0ustar tonytony Core classes of the Timing Framework; these classes provide the base functionality that all animations will use.

This package provides the fundamental capabilities of the Timing Framework. The core class of the entire framework is Animator, which is responsible for setting up and running animations. The other elements of this package are TimingTarget, which is the interface used by Animator to report timing events during the animation, and TimingTargetAdapter, which is a utility class that users may subclass to pick and choose the TimingTarget events they are interested in receiving.

timingframework_1.0.orig/org/jdesktop/animation/timing/TimingEventListener.java0000644000175000017500000000502510603302240027016 0ustar tonytony/** * Copyright (c) 2007, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing; /** * This interface is implemented by any object wishing to receive events from a * {@link TimingSource} object. The TimingEventListener would be added as a * listener to the TimingSource object via the {@link * TimingSource#addEventListener(TimingEventListener)} method. *

* This functionality is handled automatically inside of {@link Animator}. To * use a non-default TimingSource object for Animator, simply call * {@link Animator#setTimer(TimingSource)} and the appropriate listeners * will be set up internally. * * @author Chet */ public interface TimingEventListener { /** * This method is called by the {@link TimingSource} object while the * timer is running. * * @param timingSource the object that generates the timing events. */ public void timingSourceEvent(TimingSource timingSource); } timingframework_1.0.orig/org/jdesktop/animation/timing/triggers/0002755000175000017500000000000010645705656024072 5ustar tonytonytimingframework_1.0.orig/org/jdesktop/animation/timing/triggers/MouseTriggerEvent.java0000644000175000017500000000733610554001570030341 0ustar tonytony/** * Copyright (c) 2007, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.triggers; /** * Mouse Enter/Exit/Press/Release/Click events * * @author Chet */ public class MouseTriggerEvent extends TriggerEvent { /** * Event fired when mouse enters */ public static final MouseTriggerEvent ENTER = new MouseTriggerEvent("Entered"); /** * Event fired when mouse exits */ public static final MouseTriggerEvent EXIT = new MouseTriggerEvent("Exit"); /** * Event fired when mouse button is pressed */ public static final MouseTriggerEvent PRESS = new MouseTriggerEvent("Press"); /** * Event fired when mouse button is released */ public static final MouseTriggerEvent RELEASE = new MouseTriggerEvent("Release"); /** * Event fired when mouse is clicked */ public static final MouseTriggerEvent CLICK = new MouseTriggerEvent("Click"); /** * Protected constructor; this helps ensure type-safe use of * pre-define TriggerEvent objects. */ private MouseTriggerEvent(String name) { super(name); } /** * This method finds the opposite of the current event.:
* ENTER -> EXIT
* EXIT -> ENTER
* PRESS -> RELEASE
* RELEASE -> PRESS
* Note that CLICK has no obvious opposite so * it simply returns CLICK (this method should probably not be called * for that case). * */ public TriggerEvent getOppositeEvent() { if (this == MouseTriggerEvent.ENTER) { return MouseTriggerEvent.EXIT; } else if (this == MouseTriggerEvent.EXIT) { return MouseTriggerEvent.ENTER; } else if (this == MouseTriggerEvent.PRESS) { return MouseTriggerEvent.RELEASE; } else if (this == MouseTriggerEvent.RELEASE) { return MouseTriggerEvent.PRESS; } // Possible to reach here for REPEAT action (but probably should not // have been called with this event) return this; } } timingframework_1.0.orig/org/jdesktop/animation/timing/triggers/FocusTriggerEvent.java0000644000175000017500000000517310554001266030327 0ustar tonytony/** * Copyright (c) 2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.triggers; /** * Focus In/Out events * * @author Chet */ public class FocusTriggerEvent extends TriggerEvent { /** * Event fired when Component receives focus */ public static final FocusTriggerEvent IN = new FocusTriggerEvent("FocusIn"); /** * Event fired when Component loses focus */ public static final FocusTriggerEvent OUT = new FocusTriggerEvent("FocusOut"); /** * Private constructor; this helps ensure type-safe use of * pre-defined TriggerEvent objects. */ private FocusTriggerEvent(String name) { super(name); } /** * This method finds the opposite of the current event.: IN -> * OUT and OUT -> IN. */ public TriggerEvent getOppositeEvent() { if (this == FocusTriggerEvent.IN) { return FocusTriggerEvent.OUT; } else { return FocusTriggerEvent.IN; } } }; timingframework_1.0.orig/org/jdesktop/animation/timing/triggers/TimingTriggerEvent.java0000644000175000017500000000607610554001360030475 0ustar tonytony/** * Copyright (c) 2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.triggers; /** * Timing events; TimingTriggers can be set to fire when an animator * starts, stops, or repeats. * * @author Chet */ public class TimingTriggerEvent extends TriggerEvent { /** Event fired when Animator starts */ public static final TimingTriggerEvent START = new TimingTriggerEvent("Start"); /** Event fired when Animator stops */ public static final TimingTriggerEvent STOP = new TimingTriggerEvent("Stop"); /** * Event fired when Animator finishes one cycle and starts another */ public static final TimingTriggerEvent REPEAT = new TimingTriggerEvent("Repeat"); private TimingTriggerEvent(String name) { super(name); } /** * This method finds the opposite of the current event.: START -> STOP * and STOP -> START. Note that REPEAT has no obvious opposite so * it simply returns REPEAT (this method should probably not be called * for that case). */ public TriggerEvent getOppositeEvent() { if (this.equals(TimingTriggerEvent.START)) { return TimingTriggerEvent.STOP; } else if (this.equals(TimingTriggerEvent.STOP)) { return TimingTriggerEvent.START; } // Possible to reach here for REPEAT action (but probably should not // have been called with this event) return this; } } timingframework_1.0.orig/org/jdesktop/animation/timing/triggers/TriggerEvent.java0000644000175000017500000000622210547110450027321 0ustar tonytony/** * Copyright (c) 2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.triggers; /** * Superclass for all TriggerEvents used in the Trigger classes. The methods * here are mostly protected; it is expected that callers will not use this * class directly, but will instead use subclasses with pre-defined event * types. The purpose of this superclass is to provide the ability for * {@link Trigger} to treat event types generically, rather than to have * all even logic in the subclasses of Trigger. * * @author Chet */ public class TriggerEvent { /** * The ID of events are simple strings. It is expected that subclasses * will define static objects that callers will use instead of users * having to manually create TriggerEvent objects from strings directly */ private String name; /** * Protected constructor; this helps ensure type-safe use of * pre-define TriggerEvent objects. */ protected TriggerEvent(String name) { this.name = name; } /** * This method returns the 'opposite' event from itself. This is used by * {@link Trigger} in running an auto-reversing animation, to determine * whether an opposite event has occurred (and whether to stop/reverse * the animation). Note that some events may have no opposite. * Default behavior returns same event; subclasses with multiple/opposite * events must override to do the right thing here. */ public TriggerEvent getOppositeEvent() { return this; } } timingframework_1.0.orig/org/jdesktop/animation/timing/triggers/FocusTrigger.java0000644000175000017500000001234710554001540027321 0ustar tonytony/** * Copyright (c) 2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.triggers; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import javax.swing.JComponent; import org.jdesktop.animation.timing.*; /** * FocusTrigger handles focus events * and triggers an animation based on those events. * For example, to have anim start when component receives an * IN event, one might write the following: *

 *     FocusTrigger trigger = 
 *         FocusTrigger.addTrigger(component, anim, FocusTriggerEvent.IN);
 * 
* * * * @author Chet */ public class FocusTrigger extends Trigger implements FocusListener { /** * Creates a non-auto-reversing FocusTrigger and adds it as a FocusListener * to the component. * * @param component component that will generate FocusEvents for this * trigger * @param animator the Animator that will start when the event occurs * @param event the FocusTriggerEvent that will cause the action to fire * @return FocusTrigger the resulting trigger */ public static FocusTrigger addTrigger(JComponent component, Animator animator, FocusTriggerEvent event) { return addTrigger(component, animator, event, false); } /** * Creates a FocusTrigger and adds it as a FocusListener * to the component. * * @param component component that will generate FocusEvents for this * trigger * @param animator the Animator that will start when the event occurs * @param event the FocusTriggerEvent that will cause the action to fire * @param autoReverse flag to determine whether the animator should * stop and reverse based on opposite triggerEvents. * @return FocusTrigger the resulting trigger */ public static FocusTrigger addTrigger(JComponent component, Animator animator, FocusTriggerEvent event, boolean autoReverse) { FocusTrigger trigger = new FocusTrigger(animator, event, autoReverse); component.addFocusListener(trigger); return trigger; } /** * Creates a non-auto-reversing FocusTrigger, which should be added * to a Component that will generate the focus events of interest. * @param animator the Animator that will start when the event occurs * @param event the FocusTriggerEvent that will cause the action to fire */ public FocusTrigger(Animator animator, FocusTriggerEvent event) { this(animator, event, false); } /** * Creates a FocusTrigger, which should be added * to a Component that will generate the focus events of interest. * @param animator the Animator that will start when the event occurs * @param event the FocusTriggerEvent that will cause the action to fire * @param autoReverse flag to determine whether the animator should * stop and reverse based on opposite triggerEvents. */ public FocusTrigger(Animator animator, FocusTriggerEvent event, boolean autoReverse) { super(animator, event, autoReverse); } /** * Called by the object which added this trigger as a FocusListener. * This method starts the animator if the trigger is waiting for a * IN event. */ public void focusGained(FocusEvent e) { fire(FocusTriggerEvent.IN); } /** * Called by the object which added this trigger as a FocusListener. * This method starts the animator if the trigger is waiting for a * OUT event. */ public void focusLost(FocusEvent e) { fire(FocusTriggerEvent.OUT); } } timingframework_1.0.orig/org/jdesktop/animation/timing/triggers/TriggerNotes0000644000175000017500000000760110543032734026416 0ustar tonytonyTrigger Notes Want the ability to start/stop animations based on events, something like: "When X happens, start Anim1" "When Y happens, stop Anim2" Also want to start/stop animations based on other animations: "When Anim3 stops, start Anim4" Also want ability to auto-stop animations based on opposite events, and auto-start opposite animations likewise: "When X happens, start Anim1, stop Anim. When inverse(X) happens, stop Anim1 Auto-reverse might be handleable through the new setDirection() API in Animator One of the problems with the current API is all these subclasses with essentially similar constructors. It seems like I should be able to have the main functionality of creating a Trigger in just the Trigger class itself, and then have the functionality of the event-specific actions and listeners embedded in some other structure. something like: Trigger myTrigger = new Trigger(myAnimator, ButtonAction.MOUSEOVER, TriggerAction.START); ---------------- 12/22/06 Triggers revisit: wouldn't it be nice if I could make these things actually work (and have a simple API) for 1.0 (and the book)? It seems like I should be able to have a *really* simple generic interface, with most of the current details hidden. let's try it: abstract class Trigger { protected Animator animator; protected Trigger(Animator animator, TriggerAction action) { this.animator = animator; this.action = action; } protected void fire() { if (action == TriggerAction.START) { animator.start(); } else { animator.stop(); } } public void disarm() { // cancel Animator // override to cancel any listeners } } public class TimingTarget { public TimingTarget(Animator source, TriggerAction action, TriggerEvent event, Animator animator) { super(animator, action); // Setup private TimingListener } private class TimingTriggerListener extends TimingTargetAdapter { TimingTriggerEvent event; protected TimingTriggerListener(TriggerAction action, TimingTriggerEvent event) { super(timer, action); this.event = event; } public void timingEvent(float fraction) {} public void begin() { if (event == TimingTriggerEvent.START) { pullTrigger(); } } public void end() { if (event == TimingTriggerEvent.STOP) { pullTrigger(); } } public void repeat() { if (event == TimingTriggerEvent.REPEAT) { pullTrigger(); } } } } ........ This is working so far, but I've hit a snag with the auto-reverse functionality. Previously, it was up to the developer to set up two separate animations that Trigger would then add with opposite events. In particular, it would do this: - setup listener with animator, START, event - setup listener with animator, STOP, event-opposite - setup listener with reverseAnimator, START, event-opposite - setup listener with reverseAnimator, STOP, event This was useful, but not particularly a great API. It seems like, with setDirection(), getFraction(), and setInitialFraction(), we should be able to create all of this stuff automatically. For any Trigger that wants to START on some EVENT, we should be able to do this: - create an Animator (opp) that is a copy of the one supplied (anim), but with the opposite direction - when EVENT occurs: - if (opp.isRunning()) { - f = opp.getFraction() - anim.setInitialFraction(f) - opp.stop(); } - anim.start() - when !EVENT occurs: - if (anim.isRunning()) { - f = anim.getFraction() - opp.setInitialFraction(f) - anim.stop(); } - opp.start() timingframework_1.0.orig/org/jdesktop/animation/timing/triggers/Trigger.java0000644000175000017500000001616410603303102026314 0ustar tonytony/** * Copyright (c) 2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.triggers; import org.jdesktop.animation.timing.Animator; /** * This abstract class should be overridden by any class wanting to * implement a new Trigger. The subclass will define the events to trigger * off of and any listeners to handle those events. That subclass will call * either {@link #fire()} or {@link #fire(TriggerEvent)} to start the * animator based on an event that occurred. *

* Subclasses should call one of the constructors in Trigger, according to * whether they want Trigger to discern between different TriggerEvents * and whether they want Trigger to auto-reverse the animation based on * opposite TriggerEvents. *

* Subclasses should call one of the fire methods based on * whether they want Trigger to perform any event logic or simply start * the animation. * * @author Chet */ public abstract class Trigger { private boolean disarmed = false; private Animator animator, reverseAnimator; private TriggerEvent triggerEvent; private boolean autoReverse = false; /** * Creates a Trigger that will start the animator when {@link #fire()} * is called. Subclasses call this method to set up a simple Trigger * that will be started by calling {@link #fire()}, and will have * no dependency upon the specific {@link TriggerEvent} that must have * occurred to start the animator. * @param animator the Animator that will start when the Trigger * is fired */ protected Trigger(Animator animator) { this(animator, null); } /** * Creates a Trigger that will start the animator when * {@link #fire(TriggerEvent)} is called with an event that equals * triggerEvent. * @param animator the Animator that will start when the Trigger * is fired * @param triggerEvent the TriggerEvent that must occur for this * Trigger to fire */ protected Trigger(Animator animator, TriggerEvent triggerEvent) { this(animator, triggerEvent, false); } /** * Creates a Trigger that will start the animator when * {@link #fire(TriggerEvent)} is called with an event that equals * triggerEvent. Also, automatically stops and reverses animator when * opposite event occurs, and stops reversing animator likewise * when triggerEvent occurs. * @param animator the Animator that will start when the Trigger * is fired * @param triggerEvent the TriggerEvent that must occur for this * Trigger to fire * @param autoReverse flag to determine whether the animator should * stop and reverse based on opposite triggerEvents. * @see TriggerEvent#getOppositeEvent() */ protected Trigger(Animator animator, TriggerEvent triggerEvent, boolean autoReverse) { this.animator = animator; this.triggerEvent = triggerEvent; this.autoReverse = autoReverse; } /** * This method disables this Trigger and effectively noop's any actions * that would otherwise occur */ public void disarm() { disarmed = true; } /** * Called by subclasses to start the animator if currentEvent equals * the event that the Trigger is based upon. Also, if the Trigger is * set to autoReverse, stops and reverses the animator running in the * opposite direction as appropriate. * @param currentEvent the {@link TriggerEvent} that just occurred, which * will be compared with the TriggerEvent used to construct this Trigger * and determine whether the animator should be started or reversed */ protected void fire(TriggerEvent currentEvent) { if (disarmed) { return; } if (currentEvent == triggerEvent) { // event occurred; fire the animation if (autoReverse) { if (animator.isRunning()) { float f = animator.getTimingFraction(); animator.stop(); animator.setStartFraction(f); } else { animator.setStartFraction(0f); } } if (animator.isRunning()) { animator.stop(); } animator.setStartDirection(Animator.Direction.FORWARD); fire(); } else if (triggerEvent != null && currentEvent == triggerEvent.getOppositeEvent()) { // Opposite event occurred - run reverse anim if autoReverse if (autoReverse) { if (animator.isRunning()) { float f = animator.getTimingFraction(); animator.stop(); animator.setStartFraction(f); } else { animator.setStartFraction(1f - animator.getStartFraction()); } animator.setStartDirection(Animator.Direction.BACKWARD); fire(); } } } /** * Utility method called by subclasses to start the animator. This variant * assumes that there need be no check of the TriggerEvent that fired, * which is useful for subclasses with simple events. */ protected void fire() { if (disarmed) { return; } if (animator.isRunning()) { animator.stop(); } animator.start(); } } timingframework_1.0.orig/org/jdesktop/animation/timing/triggers/package.html0000644000175000017500000000133610551272102026331 0ustar tonytony Provides simple mechanism for starting Animators when specific events occur.

This package provides classes for both using and subclassing that simplify the process of associating animations with events. Trigger and its subclasses associate specific events (subclasses of TriggerEvent) with listeners (as defined in Trigger subclasses). These listeners are then added (by the application) to appropriate objects. The animations are started when a Trigger detects that a specified event has occurred (through its listener).

timingframework_1.0.orig/org/jdesktop/animation/timing/triggers/ActionTrigger.java0000644000175000017500000000744510554002652027467 0ustar tonytony/** * Copyright (c) 2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.triggers; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.lang.reflect.Method; import org.jdesktop.animation.timing.*; /** * ActionTrigger handles action events and * starts the animator when actions occur. * For example, to have anim start when a button is clicked, * one might write the following: *
 *     ActionTrigger trigger = ActionTrigger.addTrigger(button, anim);
 * 
* * @author Chet */ public class ActionTrigger extends Trigger implements ActionListener { /** * Creates an ActionTrigger and adds it as a listener to object. * * @param object an object that will be used as an event source for * this trigger. This object must have the method addActionListener. * @param animator the Animator that start when the event occurs * @return ActionTrigger the resulting trigger * @throws IllegalArgumentException if object has no * addActionListener() */ public static ActionTrigger addTrigger(Object object, Animator animator) { ActionTrigger trigger = new ActionTrigger(animator); try { Method addListenerMethod = object.getClass().getMethod("addActionListener", ActionListener.class); addListenerMethod.invoke(object, trigger); } catch (Exception e) { throw new IllegalArgumentException("Problem adding listener" + " to object: " + e); } return trigger; } /** * Creates an ActionTrigger that will start the animator upon receiving * any ActionEvents. It should be added to any suitable object with * an addActionListener method. * @param animator the Animator that start when the event occurs */ public ActionTrigger(Animator animator) { super(animator); } /** * Called by an object generating ActionEvents to which this * trigger was added as an ActionListener. This starts the Animator. */ public void actionPerformed(ActionEvent ae) { fire(); } } timingframework_1.0.orig/org/jdesktop/animation/timing/triggers/TimingTrigger.java0000644000175000017500000001277010554002612027472 0ustar tonytony/** * Copyright (c) 2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.triggers; import org.jdesktop.animation.timing.*; /** * TimingTrigger handles timing events and starts the animator * when those events occur. This class can be useful in sequencing different * Animators. For example, one Animator can be set to start when another * ends using this Trigger. For example, to have anim2 start when anim1 ends, * one might write the following: *
 *     TimingTrigger trigger = 
 *         TimingTrigger.addTrigger(anim1, anim2, TimingTriggerEvent.STOP);
 * 
* * * * @author Chet */ public class TimingTrigger extends Trigger implements TimingTarget { private Animator source; private TimingTriggerEvent event; /** * Creates a non-auto-reversing TimingTrigger and adds it as a target * to the source Animator. * * @param source the Animator that will be listened to for events * to start the target Animator * @param target the Animator that will start when the event occurs * @param event the TimingTriggerEvent that will cause targetAnimator * to start * @return TimingTrigger the resulting trigger * @see org.jdesktop.animation.timing.Animator#addTarget(TimingTarget) */ public static TimingTrigger addTrigger(Animator source, Animator target, TimingTriggerEvent event) { return addTrigger(source, target, event, false); } /** * Creates a TimingTrigger and adds it as a target * to the source Animator. * * * @param source the Animator that will be listened to for events * to start the target Animator * @param target the Animator that will start when the event occurs * @param event the TimingTriggerEvent that will cause targetAnimator * to start * @param autoReverse flag to determine whether the animator should * stop and reverse based on opposite triggerEvents. * @return TimingTrigger the resulting trigger * @see org.jdesktop.animation.timing.Animator#addTarget(TimingTarget) */ public static TimingTrigger addTrigger(Animator source, Animator target, TimingTriggerEvent event, boolean autoReverse) { TimingTrigger trigger = new TimingTrigger(target, event, autoReverse); source.addTarget(trigger); return trigger; } /** * Creates a non-auto-reversing TimingTrigger, which should be added * to an Animator which will generate the events sent to the * trigger. */ public TimingTrigger(Animator animator, TimingTriggerEvent event) { this(animator, event, false); } /** * Creates a TimingTrigger, which should be added * to an Animator which will generate the events sent to the * trigger. */ public TimingTrigger(Animator animator, TimingTriggerEvent event, boolean autoReverse) { super(animator, event, autoReverse); } // // TimingTarget implementation methods // /** * Implementation of TimingTarget method; this method does nothing * in this implementation since the events of TimingTrigger are limited * to START, STOP, and REPEAT */ public void timingEvent(float fraction) {} /** * Called by Animator when starting. Sends the TimingTriggerEvent.START * event to the Trigger. */ public void begin() { fire(TimingTriggerEvent.START); } /** * Called by Animator when ending. Sends the TimingTriggerEvent.STOP * event to the Trigger. */ public void end() { fire(TimingTriggerEvent.STOP); } /** * Called by Animator when repeating. Sends the TimingTriggerEvent.REPEAT * event to the Trigger. */ public void repeat() { fire(TimingTriggerEvent.REPEAT); } } timingframework_1.0.orig/org/jdesktop/animation/timing/triggers/MouseTrigger.java0000644000175000017500000001317510554002172027334 0ustar tonytony/** * Copyright (c) 2007, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.triggers; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import javax.swing.JComponent; import org.jdesktop.animation.timing.Animator; /** * MouseTrigger handles mouse events * and triggers an animation based on those events. * For example, to have anim start when component receives an * ENTER event, one might write the following: *
 *     MouseTrigger trigger = 
 *         MouseTrigger.addTrigger(component, anim, MouseTriggerEvent.ENTER);
 * 
* * * * @author Chet */ public class MouseTrigger extends Trigger implements MouseListener { /** * Creates a non-auto-reversing MouseTrigger and adds it as a * listener to component. * * @param component component that will generate MouseEvents for this * trigger * @param animator the Animator that will start when the event occurs * @param event the MouseTriggerEvent that will cause the action to fire * @return MouseTrigger the resulting trigger */ public static MouseTrigger addTrigger(JComponent component, Animator animator, MouseTriggerEvent event) { return addTrigger(component, animator, event, false); } /** * Creates a MouseTrigger and adds it as a listener to component. * * @param component component that will generate MouseEvents for this * trigger * @param animator the Animator that will start when the event occurs * @param event the FocusTriggerEvent that will cause the action to fire * @param autoReverse flag to determine whether the animator should * stop and reverse based on opposite triggerEvents. * @return FocusTrigger the resulting trigger */ public static MouseTrigger addTrigger(JComponent component, Animator animator, MouseTriggerEvent event, boolean autoReverse) { MouseTrigger trigger = new MouseTrigger(animator, event, autoReverse); component.addMouseListener(trigger); return trigger; } /** * Creates a non-auto-reversing MouseTrigger, which should be added * to a Component that will generate the mouse events of interest */ public MouseTrigger(Animator animator, MouseTriggerEvent event) { this(animator, event, false); } /** * Creates a MouseTrigger, which should be added * to a Component that will generate the mouse events of interest */ public MouseTrigger(Animator animator, MouseTriggerEvent event, boolean autoReverse) { super(animator, event, autoReverse); } /** * Called by the object which added this trigger as a MouseListener. * This method starts the animator if the trigger is waiting for an * ENTER event. */ public void mouseEntered(MouseEvent e) { fire(MouseTriggerEvent.ENTER); } /** * Called by the object which added this trigger as a MouseListener. * This method starts the animator if the trigger is waiting for an * EXIT event. */ public void mouseExited(MouseEvent e) { fire(MouseTriggerEvent.EXIT); } /** * Called by the object which added this trigger as a MouseListener. * This method starts the animator if the trigger is waiting for a * PRESS event. */ public void mousePressed(MouseEvent e) { fire(MouseTriggerEvent.PRESS); } /** * Called by the object which added this trigger as a MouseListener. * This method starts the animator if the trigger is waiting for a * RELEASE event. */ public void mouseReleased(MouseEvent e) { fire(MouseTriggerEvent.RELEASE); } /** * Called by the object which added this trigger as a MouseListener. * This method starts the animator if the trigger is waiting for a * CLICK event. */ public void mouseClicked(MouseEvent e) { fire(MouseTriggerEvent.CLICK); } } timingframework_1.0.orig/org/jdesktop/animation/timing/interpolation/0002755000175000017500000000000010667306536025131 5ustar tonytonytimingframework_1.0.orig/org/jdesktop/animation/timing/interpolation/KeyInterpolators.java0000644000175000017500000000526110520152544031276 0ustar tonytony/** * Copyright (c) 2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.interpolation; import java.util.ArrayList; /** * * @author Chet */ class KeyInterpolators { private ArrayList interpolators = new ArrayList(); /** * Creates a new instance of KeyInterpolators */ KeyInterpolators(int numIntervals, Interpolator... interpolators) { if (interpolators == null || interpolators[0] == null) { for (int i = 0; i < numIntervals; ++i) { this.interpolators.add(LinearInterpolator.getInstance()); } } else if (interpolators.length < numIntervals) { for (int i = 0; i < numIntervals; ++i) { this.interpolators.add(interpolators[0]); } } else { for (int i = 0; i < numIntervals; ++i) { this.interpolators.add(interpolators[i]); } } } float interpolate(int interval, float fraction) { return interpolators.get(interval).interpolate(fraction); } } timingframework_1.0.orig/org/jdesktop/animation/timing/interpolation/SplineInterpolator.java0000644000175000017500000002042710525221062031613 0ustar tonytony/** * Copyright (c) 2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.interpolation; import java.awt.geom.Point2D; import java.util.ArrayList; import org.jdesktop.animation.timing.*; /** * This class interpolates fractional values using Bezier splines. The anchor * points * for the spline are assumed to be (0, 0) and (1, 1). Control points * should all be in the range [0, 1]. *

* For more information on how splines are used to interpolate, refer to the * SMIL specification at http://w3c.org. *

* This class provides one simple built-in facility for non-linear * interpolation. Applications are free to define their own Interpolator * implementation and use that instead when particular non-linear * effects are desired. * * @author Chet */ public final class SplineInterpolator implements Interpolator { // Note: (x0,y0) and (x1,y1) are implicitly (0, 0) and (1,1) respectively private float x1, y1, x2, y2; private ArrayList lengths = new ArrayList(); /** * Creates a new instance of SplineInterpolator with the control points * defined by (x1, y1) and (x2, y2). The anchor points are implicitly * defined as (0, 0) and (1, 1). * * @throws IllegalArgumentException This exception is thrown when values * beyond the allowed [0,1] range are passed in */ public SplineInterpolator(float x1, float y1, float x2, float y2) { if (x1 < 0 || x1 > 1.0f || y1 < 0 || y1 > 1.0f || x2 < 0 || x2 > 1.0f || y2 < 0 || y2 > 1.0f) { throw new IllegalArgumentException("Control points must be in " + "the range [0, 1]:"); } this.x1 = x1; this.y1 = y1; this.x2 = x2; this.y2 = y2; // Now contruct the array of all lengths to t in [0, 1.0] float prevX = 0.0f; float prevY = 0.0f; float prevLength = 0.0f; // cumulative length for (float t = 0.01f; t <= 1.0f; t += .01f) { Point2D.Float xy = getXY(t); float length = prevLength + (float)Math.sqrt((xy.x - prevX) * (xy.x - prevX) + (xy.y - prevY) * (xy.y - prevY)); LengthItem lengthItem = new LengthItem(length, t); lengths.add(lengthItem); prevLength = length; prevX = xy.x; prevY = xy.y; } // Now calculate the fractions so that we can access the lengths // array with values in [0,1]. prevLength now holds the total // length of the spline. for (int i = 0; i < lengths.size(); ++i) { LengthItem lengthItem = (LengthItem)lengths.get(i); lengthItem.setFraction(prevLength); } } /** * Calculates the XY point for a given t value. * * The general spline equation is: * x = b0*x0 + b1*x1 + b2*x2 + b3*x3 * y = b0*y0 + b1*y1 + b2*y2 + b3*y3 * where: * b0 = (1-t)^3 * b1 = 3 * t * (1-t)^2 * b2 = 3 * t^2 * (1-t) * b3 = t^3 * We know that (x0,y0) == (0,0) and (x1,y1) == (1,1) for our splines, * so this simplifies to: * x = b1*x1 + b2*x2 + b3 * y = b1*x1 + b2*x2 + b3 * @param t parametric value for spline calculation */ private Point2D.Float getXY(float t) { Point2D.Float xy; float invT = (1 - t); float b1 = 3 * t * (invT * invT); float b2 = 3 * (t * t) * invT; float b3 = t * t * t; xy = new Point2D.Float( (b1 * x1) + (b2 * x2) + b3, (b1 * y1) + (b2 * y2) + b3); return xy; } /** * Utility function: When we are evaluating the spline, we only care * about the Y values. See {@link getXY getXY} for the details. */ private float getY(float t) { Point2D.Float xy; float invT = (1 - t); float b1 = 3 * t * (invT * invT); float b2 = 3 * (t * t) * invT; float b3 = t * t * t; return (b1 * y1) + (b2 * y2) + b3; } /** * Given a fraction of time along the spline (which we can interpret * as the length along a spline), return the interpolated value of the * spline. We first calculate the t value for the length (by doing * a lookup in our array of previousloy calculated values and then * linearly interpolating between the nearest values) and then * calculate the Y value for this t. * @param lengthFraction Fraction of time in a given time interval. * @return interpolated fraction between 0 and 1 */ public float interpolate(float lengthFraction) { // REMIND: speed this up with binary search float interpolatedT = 1.0f; float prevT = 0.0f; float prevLength = 0.0f; for (int i = 0; i < lengths.size(); ++i) { LengthItem lengthItem = (LengthItem)lengths.get(i); float fraction = lengthItem.getFraction(); float t = lengthItem.getT(); if (lengthFraction <= fraction) { // answer lies between last item and this one float proportion = (lengthFraction - prevLength) / (fraction - prevLength); interpolatedT = prevT + proportion * (t - prevT); return getY(interpolatedT); } prevLength = fraction; prevT = t; } return getY(interpolatedT); } } /** * Struct used to store information about length values. Specifically, * each item stores the "length" (which can be thought of as the time * elapsed along the spline path), the "t" value at this length (used to * calculate the (x,y) point along the spline), and the "fraction" which * is equal to the length divided by the total absolute length of the spline. * After we calculate all LengthItems for a give spline, we have a list * of entries which can return the t values for fractional lengths from * 0 to 1. */ class LengthItem { float length; float t; float fraction; LengthItem(float length, float t, float fraction) { this.length = length; this.t = t; this.fraction = fraction; } LengthItem(float length, float t) { this.length = length; this.t = t; } public float getLength() { return length; } public float getT() { return t; } public float getFraction() { return fraction; } void setFraction(float totalLength) { fraction = length / totalLength; } }timingframework_1.0.orig/org/jdesktop/animation/timing/interpolation/LinearInterpolator.java0000644000175000017500000000616510525111540031575 0ustar tonytony/** * Copyright (c) 2005-2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.interpolation; import org.jdesktop.animation.timing.*; /** * This class implements the Interpolator interface by providing a * simple interpolate function that simply returns the value that * it was given. The net effect is that callers will end up calculating * values linearly during intervals. *

* Because there is no variation to this class, it is a singleton and * is referenced by using the {@link #getInstance} static method. * * @author Chet */ public final class LinearInterpolator implements Interpolator { private static LinearInterpolator instance = null; private LinearInterpolator() {} /** * Returns the single DiscreteInterpolator object */ public static LinearInterpolator getInstance() { if (instance == null) { instance = new LinearInterpolator(); } return instance; } /** * This method always returns the value it was given, which will cause * callers to calculate a linear interpolation between boundary values. * @param fraction a value between 0 and 1, representing the elapsed * fraction of a time interval (either an entire animation cycle or an * interval between two KeyTimes, depending on where this Interpolator has * been set) * @return the same value passed in as fraction */ public float interpolate(float fraction) { return fraction; } } timingframework_1.0.orig/org/jdesktop/animation/timing/interpolation/KeyFrames.java0000644000175000017500000002254110551235526027654 0ustar tonytony/** * Copyright (c) 2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.interpolation; import java.lang.reflect.Method; import org.jdesktop.animation.timing.*; /** * * KeyFrames holds information about the times at which values are sampled * (KeyTimes) and the values at those times (KeyValues). It also holds * information about how to interpolate between these values for * times that lie between the sampling points. * * @author Chet */ public class KeyFrames { private KeyValues keyValues; private KeyTimes keyTimes; private KeyInterpolators interpolators; /** * Simplest variation; determine keyTimes based on even division of * 0-1 range based on number of keyValues. This constructor * assumes LINEAR interpolation. * @param keyValues values that will be assumed at each time in keyTimes */ public KeyFrames(KeyValues keyValues) { init(keyValues, null, (Interpolator)null); } /** * This variant takes both keyValues (values at each * point in time) and keyTimes (times at which values are sampled). * @param keyValues values that the animation will assume at each of the * corresponding times in keyTimes * @param keyTimes times at which the animation will assume the * corresponding values in keyValues * @throws IllegalArgumentException keyTimes and keySizes must have the * same number of elements since these structures are meant to have * corresponding entries; an exception is thrown otherwise. */ public KeyFrames(KeyValues keyValues, KeyTimes keyTimes) { init(keyValues, keyTimes, (Interpolator)null); } /** * Full constructor: caller provides * an instance of all key* structures which will be used to calculate * between all times in the keyTimes list. A null interpolator parameter * is equivalent to calling {@link KeyFrames#KeyFrames(KeyValues, KeyTimes)}. * @param keyValues values that the animation will assume at each of the * corresponding times in keyTimes * @param keyTimes times at which the animation will assume the * corresponding values in keyValues * @param interpolators collection of Interpolators that control * the calculation of values in each of the intervals defined by keyFrames. * If this value is null, a {@link LinearInterpolator} will be used * for all intervals. If there is only one interpolator, that interpolator * will be used for all intervals. Otherwise, there must be a number of * interpolators equal to the number of intervals (which is one less than * the number of keyTimes). * @throws IllegalArgumentException keyTimes and keyValues must have the * same number of elements since these structures are meant to have * corresponding entries; an exception is thrown otherwise. * @throws IllegalArgumentException The number of interpolators must either * be zero (interpolators == null), one, or one less than the size of * keyTimes. */ public KeyFrames(KeyValues keyValues, KeyTimes keyTimes, Interpolator... interpolators) { init(keyValues, keyTimes, interpolators); } /** * Utility constructor that assumes even division of times according to * size of keyValues and interpolation according to interpolators * parameter. * @param keyValues values that the animation will assume at each of the * corresponding times in keyTimes * @param interpolators collection of Interpolators that control * the calculation of values in each of the intervals defined by keyFrames. * If this value is null, a {@link LinearInterpolator} will be used * for all intervals. If there is only one interpolator, that interpolator * will be used for all intervals. Otherwise, there must be a number of * interpolators equal to the number of intervals (which is one less than * the number of keyTimes). * @throws IllegalArgumentException The number of interpolators must either * be zero (interpolators == null), one, or one less than the size of * keyTimes. */ public KeyFrames(KeyValues keyValues, Interpolator... interpolators) { init(keyValues, null, interpolators); } /** * Utility function called by constructors to perform common * initialization chores */ private void init(KeyValues keyValues, KeyTimes keyTimes, Interpolator... interpolators) { int numFrames = keyValues.getSize(); // If keyTimes null, create our own if (keyTimes == null) { float keyTimesArray[] = new float[numFrames]; float timeVal = 0.0f; keyTimesArray[0] = timeVal; for (int i = 1; i < (numFrames - 1); ++i) { timeVal += (1.0f / (numFrames - 1)); keyTimesArray[i] = timeVal; } keyTimesArray[numFrames - 1] = 1.0f; this.keyTimes = new KeyTimes(keyTimesArray); } else { this.keyTimes = keyTimes; } this.keyValues = keyValues; if (numFrames != this.keyTimes.getSize()) { throw new IllegalArgumentException("keyValues and keyTimes" + " must be of equal size"); } if (interpolators != null && (interpolators.length != (numFrames - 1)) && (interpolators.length != 1)) { throw new IllegalArgumentException("interpolators must be " + "either null (implying interpolation for all intervals), " + "a single interpolator (which will be used for all " + "intervals), or a number of interpolators equal to " + "one less than the number of times."); } this.interpolators = new KeyInterpolators(numFrames - 1, interpolators); } Class getType() { return keyValues.getType(); } KeyValues getKeyValues() { return keyValues; } KeyTimes getKeyTimes() { return keyTimes; } /** * Returns time interval that contains this time fraction */ public int getInterval(float fraction) { return keyTimes.getInterval(fraction); } /** * Returns a value for the given fraction elapsed of the animation * cycle. Given the fraction, this method will determine what * interval the fraction lies within, how much of that interval has * elapsed, what the boundary values are (from KeyValues), what the * interpolated fraction is (from the Interpolator for the interval), * and what the final interpolated intermediate value is (using the * appropriate Evaluator). * This method will call into the Interpolator for the time interval * to get the interpolated method. To ensure that future operations * succeed, the value received from the interpolation will be clamped * to the interval [0,1]. */ Object getValue(float fraction) { // First, figure out the real fraction to use, given the // interpolation type and keyTimes int interval = getInterval(fraction); float t0 = keyTimes.getTime(interval); float t1 = keyTimes.getTime(interval + 1); float t = (fraction - t0) / (t1 - t0); float interpolatedT = interpolators.interpolate(interval, t); // clamp to avoid problems with buggy Interpolators if (interpolatedT < 0f) { interpolatedT = 0f; } else if (interpolatedT > 1f) { interpolatedT = 1f; } return keyValues.getValue(interval, (interval+1), interpolatedT); } } timingframework_1.0.orig/org/jdesktop/animation/timing/interpolation/Interpolator.java0000644000175000017500000000540410551235562030447 0ustar tonytony/** * Copyright (c) 2005-2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.interpolation; /** * Interface that defines the single {@link #interpolate(float)} method. * This interface is implemented by built-in interpolators. * Applications may choose to implement * their own Interpolator to get custom interpolation behavior. * * @author Chet */ public interface Interpolator { /** * This function takes an input value between 0 and 1 and returns * another value, also between 0 and 1. The purpose of the function * is to define how time (represented as a (0-1) fraction of the * duration of an animation) is altered to derive different value * calculations during an animation. * @param fraction a value between 0 and 1, representing the elapsed * fraction of a time interval (either an entire animation cycle or an * interval between two KeyTimes, depending on where this Interpolator has * been set) * @return a value between 0 and 1. Values outside of this boundary may * be clamped to the interval [0,1] and cause undefined results. */ public float interpolate(float fraction); } timingframework_1.0.orig/org/jdesktop/animation/timing/interpolation/Evaluator.java0000644000175000017500000003670010631322352027723 0ustar tonytony/** * Copyright (c) 2005-2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.interpolation; import java.awt.Color; import java.awt.geom.Arc2D; import java.awt.geom.CubicCurve2D; import java.awt.geom.Dimension2D; import java.awt.geom.Ellipse2D; import java.awt.geom.Line2D; import java.awt.geom.Point2D; import java.awt.geom.QuadCurve2D; import java.awt.geom.Rectangle2D; import java.awt.geom.RoundRectangle2D; import java.lang.reflect.Constructor; import java.util.HashMap; import java.util.Map; /** * This class is used by KeyValues to calculate intermediate values for * specific types. * This class has built-in support for the following data types: *

    *
  • java.lang.Byte *
  • java.lang.Short *
  • java.lang.Integer *
  • java.lang.Long *
  • java.lang.Float *
  • java.lang.Double *
  • java.awt.Color *
  • java.awt.geom.Point2D *
  • java.awt.geom.Line2D *
  • java.awt.geom.Dimension2D *
  • java.awt.geom.Rectangle2D *
  • java.awt.geom.RoundRectangle2D *
  • java.awt.geom.Ellipse2D *
  • java.awt.geom.Arc2D *
  • java.awt.geom.QuadCurve2D *
  • java.awt.geom.CubicCurve2D *
* * @author Chet */ public abstract class Evaluator { /** * HashMap that holds all registered evaluators */ private static final Map, Class> impls = new HashMap, Class>(); /** * Static registration of pre-defined evaluators */ static { impls.put(Byte.class, EvaluatorByte.class); impls.put(Short.class, EvaluatorShort.class); impls.put(Integer.class, EvaluatorInteger.class); impls.put(Long.class, EvaluatorLong.class); impls.put(Float.class, EvaluatorFloat.class); impls.put(Double.class, EvaluatorDouble.class); impls.put(Color.class, EvaluatorColor.class); impls.put(Point2D.class, EvaluatorPoint2D.class); impls.put(Line2D.class, EvaluatorLine2D.class); impls.put(Dimension2D.class, EvaluatorDimension2D.class); impls.put(Rectangle2D.class, EvaluatorRectangle2D.class); impls.put(RoundRectangle2D.class, EvaluatorRoundRectangle2D.class); impls.put(Ellipse2D.class, EvaluatorEllipse2D.class); impls.put(Arc2D.class, EvaluatorArc2D.class); impls.put(QuadCurve2D.class, EvaluatorQuadCurve2D.class); impls.put(CubicCurve2D.class, EvaluatorCubicCurve2D.class); } private static void register(Class type, Class impl) { impls.put(type, impl); } private static void deregister(Class type) { impls.remove(type); } static Evaluator create(Class type) { Class interpClass = null; for (Class klass : impls.keySet()) { if (klass.isAssignableFrom(type)) { interpClass = impls.get(klass); break; } } if (interpClass == null) { throw new IllegalArgumentException("No Evaluator" + " can be found for type " + type + "; consider using" + " different types for your values or supplying a custom" + " Evaluator"); } try { Constructor ctor = interpClass.getConstructor(); return (Evaluator)ctor.newInstance(); } catch (Exception e) { throw new IllegalArgumentException("Problem constructing " + "appropriate Evaluator for type " + type + ":", e); } } /** * Abstract method to evaluate between two boundary values. Built-in * implementations all use linear parametric evaluation: *
     *      v = v0 + (v1 - v0) * fraction
     * 
* Extenders of Evaluator will need to override this method * and do something similar for their own types. Note that this * mechanism may be used to create non-linear interpolators for * specific value types, although it may besimpler to just use * the linear/parametric interpolation * technique here and perform non-linear interpolation through * custom Interpolators rather than perform custom calculations in * this method; the point of this class is to allow calculations with * new/unknown types, not to provide another mechanism for non-linear * interpolation. */ public abstract T evaluate(T v0, T v1, float fraction); } class EvaluatorByte extends Evaluator { public EvaluatorByte() {} public Byte evaluate(Byte v0, Byte v1, float fraction) { return (byte)(v0 + (byte)((v1 - v0) * fraction)); } } class EvaluatorShort extends Evaluator { public EvaluatorShort() {} public Short evaluate(Short v0, Short v1, float fraction) { return (short)(v0 + (short)((v1 - v0) * fraction)); } } class EvaluatorInteger extends Evaluator { public EvaluatorInteger() {} public Integer evaluate(Integer v0, Integer v1, float fraction) { return v0 + (int)((v1 - v0) * fraction); } } class EvaluatorLong extends Evaluator { public EvaluatorLong() {} public Long evaluate(Long v0, Long v1, float fraction) { return v0 + (long)((v1 - v0) * fraction); } } class EvaluatorFloat extends Evaluator { public EvaluatorFloat() {} public Float evaluate(Float v0, Float v1, float fraction) { return v0 + ((v1 - v0) * fraction); } } class EvaluatorDouble extends Evaluator { public EvaluatorDouble() {} public Double evaluate(Double v0, Double v1, float fraction) { return v0 + ((v1 - v0) * fraction); } } class EvaluatorColor extends Evaluator { public EvaluatorColor() {} public Color evaluate(Color v0, Color v1, float fraction) { int r = v0.getRed() + (int)((v1.getRed() - v0.getRed()) * fraction + 0.5f); int g = v0.getGreen() + (int)((v1.getGreen() - v0.getGreen()) * fraction + 0.5f); int b = v0.getBlue() + (int)((v1.getBlue() - v0.getBlue()) * fraction + 0.5f); int a = v0.getAlpha() + (int)((v1.getAlpha() - v0.getAlpha()) * fraction + 0.5f); Color value = new Color(r, g, b, a); return value; } } class EvaluatorPoint2D extends Evaluator { // REMIND: apply this technique to other classes... private Point2D value; public EvaluatorPoint2D() {} public Point2D evaluate(Point2D v0, Point2D v1, float fraction) { if (value == null) { // TODO: Note that future calls to this Evaluator may // use a different subclass of Point2D, so the precision of the // result may vary because we are caching a clone of // the first instance we received value = (Point2D)v0.clone(); } double x = v0.getX() + ((v1.getX() - v0.getX()) * fraction); double y = v0.getY() + ((v1.getY() - v0.getY()) * fraction); value.setLocation(x, y); return value; } } class EvaluatorLine2D extends Evaluator { public EvaluatorLine2D() {} public Line2D evaluate(Line2D v0, Line2D v1, float fraction) { double x1 = v0.getX1() + ((v1.getX1() - v0.getX1()) * fraction); double y1 = v0.getY1() + ((v1.getY1() - v0.getY1()) * fraction); double x2 = v0.getX2() + ((v1.getX2() - v0.getX2()) * fraction); double y2 = v0.getY2() + ((v1.getY2() - v0.getY2()) * fraction); Line2D value = (Line2D)v0.clone(); value.setLine(x1, y1, x2, y2); return value; } } class EvaluatorDimension2D extends Evaluator { public EvaluatorDimension2D() {} public Dimension2D evaluate(Dimension2D v0, Dimension2D v1, float fraction) { double w = v0.getWidth() + ((v1.getWidth() - v0.getWidth()) * fraction); double h = v0.getHeight() + ((v1.getHeight() - v0.getHeight()) * fraction); Dimension2D value = (Dimension2D)v0.clone(); value.setSize(w, h); return value; } } class EvaluatorRectangle2D extends Evaluator { public EvaluatorRectangle2D() {} public Rectangle2D evaluate(Rectangle2D v0, Rectangle2D v1, float fraction) { double x = v0.getX() + ((v1.getX() - v0.getX()) * fraction); double y = v0.getY() + ((v1.getY() - v0.getY()) * fraction); double w = v0.getWidth() + ((v1.getWidth() - v0.getWidth()) * fraction); double h = v0.getHeight() + ((v1.getHeight() - v0.getHeight()) * fraction); Rectangle2D value = (Rectangle2D)v0.clone(); value.setRect(x, y, w, h); return value; } } class EvaluatorRoundRectangle2D extends Evaluator { public EvaluatorRoundRectangle2D() {} public RoundRectangle2D evaluate(RoundRectangle2D v0, RoundRectangle2D v1, float fraction) { double x = v0.getX() + ((v1.getX() - v0.getX()) * fraction); double y = v0.getY() + ((v1.getY() - v0.getY()) * fraction); double w = v0.getWidth() + ((v1.getWidth() - v0.getWidth()) * fraction); double h = v0.getHeight() + ((v1.getHeight() - v0.getHeight()) * fraction); double arcw = v0.getArcWidth() + ((v1.getArcWidth() - v0.getArcWidth()) * fraction); double arch = v0.getArcHeight() + ((v1.getArcHeight() - v0.getArcHeight()) * fraction); RoundRectangle2D value = (RoundRectangle2D)v0.clone(); value.setRoundRect(x, y, w, h, arcw, arch); return value; } } class EvaluatorEllipse2D extends Evaluator { public EvaluatorEllipse2D() {} public Ellipse2D evaluate(Ellipse2D v0, Ellipse2D v1, float fraction) { double x = v0.getX() + ((v1.getX() - v0.getX()) * fraction); double y = v0.getY() + ((v1.getY() - v0.getY()) * fraction); double w = v0.getWidth() + ((v1.getWidth() - v0.getWidth()) * fraction); double h = v0.getHeight() + ((v1.getHeight() - v0.getHeight()) * fraction); Ellipse2D value = (Ellipse2D)v0.clone(); value.setFrame(x, y, w, h); return value; } } class EvaluatorArc2D extends Evaluator { public EvaluatorArc2D() {} public Arc2D evaluate(Arc2D v0, Arc2D v1, float fraction) { double x = v0.getX() + ((v1.getX() - v0.getX()) * fraction); double y = v0.getY() + ((v1.getY() - v0.getY()) * fraction); double w = v0.getWidth() + ((v1.getWidth() - v0.getWidth()) * fraction); double h = v0.getHeight() + ((v1.getHeight() - v0.getHeight()) * fraction); double start = v0.getAngleStart() + ((v1.getAngleStart() - v0.getAngleStart()) * fraction); double extent = v0.getAngleExtent() + ((v1.getAngleExtent() - v0.getAngleExtent()) * fraction); Arc2D value = (Arc2D)v0.clone(); value.setArc(x, y, w, h, start, extent, v0.getArcType()); return value; } } class EvaluatorQuadCurve2D extends Evaluator { public EvaluatorQuadCurve2D() {} public QuadCurve2D evaluate(QuadCurve2D v0, QuadCurve2D v1, float fraction) { double x1 = v0.getX1() + ((v1.getX1() - v0.getX1()) * fraction); double y1 = v0.getY1() + ((v1.getY1() - v0.getY1()) * fraction); double x2 = v0.getX2() + ((v1.getX2() - v0.getX2()) * fraction); double y2 = v0.getY2() + ((v1.getY2() - v0.getY2()) * fraction); double ctrlx = v0.getCtrlX() + ((v1.getCtrlX() - v0.getCtrlX()) * fraction); double ctrly = v0.getCtrlY() + ((v1.getCtrlY() - v0.getCtrlY()) * fraction); QuadCurve2D value = (QuadCurve2D)v0.clone(); value.setCurve(x1, y1, ctrlx, ctrly, x2, y2); return value; } } class EvaluatorCubicCurve2D extends Evaluator { public EvaluatorCubicCurve2D() {} public CubicCurve2D evaluate(CubicCurve2D v0, CubicCurve2D v1, float fraction) { double x1 = v0.getX1() + ((v1.getX1() - v0.getX1()) * fraction); double y1 = v0.getY1() + ((v1.getY1() - v0.getY1()) * fraction); double x2 = v0.getX2() + ((v1.getX2() - v0.getX2()) * fraction); double y2 = v0.getY2() + ((v1.getY2() - v0.getY2()) * fraction); double ctrlx1 = v0.getCtrlX1() + ((v1.getCtrlX1() - v0.getCtrlX1()) * fraction); double ctrly1 = v0.getCtrlY1() + ((v1.getCtrlY1() - v0.getCtrlY1()) * fraction); double ctrlx2 = v0.getCtrlX2() + ((v1.getCtrlX2() - v0.getCtrlX2()) * fraction); double ctrly2 = v0.getCtrlY2() + ((v1.getCtrlY2() - v0.getCtrlY2()) * fraction); CubicCurve2D value = (CubicCurve2D)v0.clone(); value.setCurve(x1, y1, ctrlx1, ctrly1, ctrlx2, ctrly2, x2, y2); return value; } } timingframework_1.0.orig/org/jdesktop/animation/timing/interpolation/DiscreteInterpolator.java0000644000175000017500000000741210525111552032124 0ustar tonytony/** * Copyright (c) 2005-2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.interpolation; /** * This class implements the Interpolator interface. It should * be used in cases where a "discrete" animation is desired. A * discrete animation is defined to be one where the values during * an animation do not change smoothly between the boundary values, * but suddenly, at the boundary points. For example, a discrete animation * with KeyFrames where the KeyTimes are {0, .5, 1.0} and the KeyValues * are (0, 1, 2} would, during the animation, retain the value of 0 until * half-way through the animation and 1 through the rest of the animation. *

* Because there is no variation to this class, it is a singleton and * is referenced by using the {@link #getInstance} static method. * * @author Chet */ public final class DiscreteInterpolator implements Interpolator { private static DiscreteInterpolator instance = null; private DiscreteInterpolator() {} /** * Returns the single DiscreteInterpolator object */ public static DiscreteInterpolator getInstance() { if (instance == null) { instance = new DiscreteInterpolator(); } return instance; } /** * This method always returns 0 for inputs less than 1, * which will force users of this * interpolation to assign a value equal to the value at the beginning * of this timing interval, which is the desired behavior for discrete * animations. An input of 1 will return 1, since this means the * end of the current interval (and start to the next interval). * @param fraction a value between 0 and 1, representing the elapsed * fraction of a time interval (either an entire animation cycle or an * interval between two KeyTimes, depending on where this Interpolator has * been set) * @return number representing the start of the current interval, usually * 0, but if fracton == 0, returns 1. */ public float interpolate(float fraction) { if (fraction < 1.0f) { return 0; } return 1.0f; } } timingframework_1.0.orig/org/jdesktop/animation/timing/interpolation/PropertySetter.java0000644000175000017500000004164710667306536031021 0ustar tonytony/** * Copyright (c) 2005-2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.interpolation; import java.beans.PropertyDescriptor; import java.lang.reflect.Method; import org.jdesktop.animation.timing.Animator; import org.jdesktop.animation.timing.TimingTargetAdapter; /** * This class enables automating animation of object properties. * The class is a TimingTarget, and should be used as a target of * timing events from an Animator. These events will be used to * change a specified property over time, according to how the * PropertySetter is constructed. *

* For example, here is an animation of the "background" property * of some object "obj" from blue to red over a period of one second: *

 *  PropertySetter ps = new PropertySetter(obj, "background", Color.BLUE, 
 *                                         Color.RED);
 *  Animator anim = new Animator(1000, ps);
 *  anim.start();
 * 
* Here is the same animation, created using one of the utility * factory methods that returns an animator: *
 *  Animator animator = PropertySetter.createAnimator(1000, obj, "background", 
 *                                                    Color.BLUE, Color.RED);
 *  anim.start();
 * 
*

* More complex animations can be created by passing in multiple values * for the property to take on, for example: *

 *  Animator animator = PropertySetter.createAnimator(1000, obj, "background", 
 *                                                    Color.BLUE, Color.RED, 
 *                                                    Color.GREEN);
 *  anim.start();
 * 
* It is also possible to define more involved and tightly-controlled * steps in the animation, including the times between the values and * how the values are interpolated by using the constructor that takes * a {@link KeyFrames} object. KeyFrames defines the fractional times at which * an object takes on specific values, the values to assume at those times, * and the method of interpolation between those values. For example, * here is the same animation as above, specified through KeyFrames, where the * RED color will be set 10% of the way through the animation (note that * we are not setting an Interpolator, so the timing intervals will use the * default LinearInterpolator): *
 *  KeyValues vals = KeyValues.create(Color.BLUE, Color.RED, Color.GREEN);
 *  KeyTimes times = new KeyTimes(0.0f, .1f, 1.0f);
 *  KeyFrames frames = new KeyFrames(vals, times);
 *  Animator animator = PropertySetter.createAnimator(1000, obj, "background", 
 *                                                    frames);
 *  anim.start();
 * 
* * @author Chet */ public class PropertySetter extends TimingTargetAdapter { private Object object; private String propertyName; private KeyFrames keyFrames; private Method propertySetter; private Method propertyGetter; /** * Utility method that constructs a PropertySetter and an Animator using * that PropertySetter and returns the Animator * @param duration the duration, in milliseconds, of the animation * @param object the object whose property will be animated * @param propertyName the name of the property to be animated. For * any propertyName "foo" there must be an accessible "setFoo" method * on the object. If only one value is supplied in creating the * KeyValues for the keyFrames, the animation * will also need a "getFoo" method. * @param keyFrames the fractional times, values, and interpolation * to be used in calculating the values set on the object's property. * @throws IllegalArgumentException if appropriate set/get methods * cannot be found for propertyName. */ public static Animator createAnimator(int duration, Object object, String propertyName, KeyFrames keyFrames) { PropertySetter ps = new PropertySetter(object, propertyName, keyFrames); Animator animator = new Animator(duration, ps); return animator; } /** * Utility method that constructs a PropertySetter and an Animator using * that PropertySetter and returns the Animator * @param duration the duration, in milliseconds, of the animation * @param object the object whose property will be animated * @param propertyName the name of the property to be animated. For * any propertyName "foo" there must be an accessible "setFoo" method * on the object. If only one value is supplied in creating the * KeyValues for the keyFrames, the animation * will also need a "getFoo" method. * @param params the values that the object will take on during the * animation. Internally, a KeyFrames object will be created that * will use times that split the total duration evenly. Supplying * only one value for params implies that this is a "to" animation * whose intial value will be determined dynamically when the animation * starts. * @throws IllegalArgumentException if appropriate set/get methods * cannot be found for propertyName. */ public static Animator createAnimator(int duration, Object object, String propertyName, T... params) { PropertySetter ps = new PropertySetter(object, propertyName, params); Animator animator = new Animator(duration, ps); return animator; } /** * Utility method that constructs a PropertySetter and an Animator using * that PropertySetter and returns the Animator * * @param duration the duration, in milliseconds, of the animation * @param object the object whose property will be animated * @param propertyName the name of the property to be animated. For * any propertyName "foo" there must be an accessible "setFoo" method * on the object. If only one value is supplied in creating the * KeyValues for the keyFrames, the animation * will also need a "getFoo" method. * @param evaluator KeyValues knows how to calculate intermediate values * for many built-in types, but if you want to supply values in * types not understood by KeyValues, you will need to supply your * own Evaluator. * @param params the values that the object will take on during the * animation. Internally, a KeyFrames object will be created that * will use times that split the total duration evenly. Supplying * only one value for params implies that this is a "to" animation * whose intial value will be determined dynamically when the animation * starts. * @throws IllegalArgumentException if appropriate set/get methods * cannot be found for propertyName. */ public static Animator createAnimator(int duration, Object object, String propertyName, Evaluator evaluator, T... params) { PropertySetter ps = new PropertySetter(object, propertyName, evaluator, params); Animator animator = new Animator(duration, ps); return animator; } /** * Constructor for a PropertySetter where the values the propert * takes on during the animation are specified in a {@link KeyFrames} * object. * @param object the object whose property will be animated * @param propertyName the name of the property to be animated. For * any propertyName "foo" there must be an accessible "setFoo" method * on the object. If only one value is supplied in creating the * KeyValues for the keyFrames, the animation * will also need a "getFoo" method. * @param keyFrames the fractional times, values, and interpolation * to be used in calculating the values set on the object's property. * @throws IllegalArgumentException if appropriate set/get methods * cannot be found for propertyName. */ public PropertySetter(Object object, String propertyName, KeyFrames keyFrames) { this.object = object; this.propertyName = propertyName; this.keyFrames = keyFrames; try { setupMethodInfo(); } catch (NoSuchMethodException e) { throw new IllegalArgumentException("Bad property name (" + propertyName +"): could not find " + "an appropriate setter or getter method for that property"); } } /** * Constructor for a PropertySetter where the values the propert * takes on during the animation are specified in a {@link KeyFrames} * object. * @param object the object whose property will be animated * @param propertyName the name of the property to be animated. For * any propertyName "foo" there must be an accessible "setFoo" method * on the object. If only one value is supplied in params, the animation * will also need a "getFoo" method. * @param params the values that the object will take on during the * animation. Internally, a KeyFrames object will be created that * will use times that split the total duration evenly. Supplying * only one value for params implies that this is a "to" animation * whose intial value will be determined dynamically when the animation * starts. * @throws IllegalArgumentException if appropriate set/get methods * cannot be found for propertyName. */ public PropertySetter(Object object, String propertyName, T... params) { this(object, propertyName, new KeyFrames(KeyValues.create(params))); } /** * Constructor for a PropertySetter where the values the propert * takes on during the animation are specified in a {@link KeyFrames} * object. * * @param object the object whose property will be animated * @param propertyName the name of the property to be animated. For * any propertyName "foo" there must be an accessible "setFoo" method * on the object. If only one value is supplied in params, the animation * will also need a "getFoo" method. * @param evaluator KeyValues knows how to calculate intermediate values * for many built-in types, but if you want to supply values in * types not understood by KeyValues, you will need to supply your * own Evaluator. * @param params the values that the object will take on during the * animation. Internally, a KeyFrames object will be created that * will use times that split the total duration evenly. Supplying * only one value for params implies that this is a "to" animation * whose intial value will be determined dynamically when the animation * starts. * @throws IllegalArgumentException if appropriate set/get methods * cannot be found for propertyName. */ public PropertySetter(Object object, String propertyName, Evaluator evaluator, T... params) { this(object, propertyName, new KeyFrames(KeyValues.create(evaluator, params))); } /** * Translates the property name used in the PropertyRange object into * the appropriate Method in the Object to be modified. This uses * standard JavaBean naming convention (e.g., propertyName would * become setPropertyName). * @throws NoSuchMethodException if there is no method on the * object with the appropriate name * @throws SecurityException if the application does not have * appropriate permissions to request access to the Method */ private void setupMethodInfo() throws NoSuchMethodException { try { String firstChar = propertyName.substring(0, 1); String remainder = propertyName.substring(1); Class propertyType = getType(); String propertySetterName = "set" + firstChar.toUpperCase() + remainder; PropertyDescriptor prop = new PropertyDescriptor(propertyName, object.getClass(), null, propertySetterName); propertySetter = prop.getWriteMethod(); if (isToAnimation()) { // Only need the getter for "to" animations String propertyGetterName = "get" + firstChar.toUpperCase() + remainder; prop = new PropertyDescriptor(propertyName, object.getClass(), propertyGetterName, null); propertyGetter = prop.getReadMethod(); } } catch (Exception e) { throw new NoSuchMethodException("Cannot find property methods: " + e); } } // // TimingTargetAdapter overrides // /** * Called by Animator to signal that the timer is about to start. * The only operation performed in this method is setting an initial * value for the animation if appropriate; this accounts * for "to" animations, which need to start from the current value. *

* This method is not intended for use by application code. */ public void begin() { if (isToAnimation()) { try { setStartValue(propertyGetter.invoke(object)); } catch (Exception e) { System.out.println("Problem setting start value on object " + object + ": " + e); } } } /** * Called from Animator to signal a timing event. This * causes PropertySetter to invoke the property-setting method (as * specified by the propertyName in the constructor) with the * appropriate value of the property given the range of values in the * KeyValues object and the fraction of the timing cycle that has * elapsed. *

* This method is not intended for use by application code. */ public void timingEvent(float fraction) { try { setValue(object, propertySetter, fraction); } catch (Exception e) { System.out.println("Problem calling setValue in " + "PropertySetter.timingEvent: " + e); } } private String getPropertyName() { return propertyName; } /** * Called during begin() if this is a "to" animation, to set the start * value of the animation to whatever the current value is. */ private void setStartValue(Object object) { keyFrames.getKeyValues().setStartValue(object); } /** * Sets the appropriate value on the property given the current fraction */ private void setValue(Object object, Method method, float fraction) { try { method.invoke(object, keyFrames.getValue(fraction)); } catch (Exception e) { System.out.println("Problem invoking method " + propertySetter + " in object " + object + " in setValue" + e); } } /** * Returns the type used in this property setter (defers to KeyFrames * for this information). */ private Class getType() { return keyFrames.getType(); } /** * Utility method for determining whether this is a "to" animation * (true if the first value is null). */ private boolean isToAnimation() { return (keyFrames.getKeyValues().isToAnimation()); } } timingframework_1.0.orig/org/jdesktop/animation/timing/interpolation/package.html0000644000175000017500000000141310517667346027412 0ustar tonytony Provides a mechanism for animating object properties between different values.

This package provides classes for defining object properties to animate, via the PropertySetter class. KeyFrames encapsulates the definition of the times (using KeyTimes) and values (using KeyValues) to interpolate between, as well as the type of interpolation to use between these values. Interpolator is an interface that is implemented by DiscreteInterpolator, LinearInterpolator, and SplineInterpolator for built-in interpolations, but applications can define their own custom interpolation as well.

timingframework_1.0.orig/org/jdesktop/animation/timing/interpolation/KeyTimes.java0000644000175000017500000000771510517750070027524 0ustar tonytony/** * Copyright (c) 2005-2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.interpolation; import java.util.ArrayList; import org.jdesktop.animation.timing.*; /** * Stores a list of times from 0 to 1 (the elapsed fraction of an animation * cycle) that are used in calculating interpolated * values for PropertySetter given a matching set of KeyValues and * Interpolators for those time intervals. In the simplest case, a * KeyFrame will consist of just two times in KeyTimes: 0 and 1. * * @author Chet */ public class KeyTimes { private ArrayList times = new ArrayList(); /** * Creates a new instance of KeyTimes. Times should be in increasing * order and should all be in the range [0,1], with the first value * being zero and the last being 1 * @throws IllegalArgumentException Time values must be ordered in * increasing value, the first value must be 0 and the last value * must be 1 */ public KeyTimes(float... times) { if (times[0] != 0) { throw new IllegalArgumentException("First time value must" + " be zero"); } if (times[times.length - 1] != 1.0f) { throw new IllegalArgumentException("Last time value must" + " be one"); } float prevTime = 0; for (float time : times) { if (time < prevTime) { throw new IllegalArgumentException("Time values must be" + " in increasing order"); } this.times.add(time); prevTime = time; } } ArrayList getTimes() { return times; } int getSize() { return times.size(); } /** * Returns time interval that contains this time fraction */ int getInterval(float fraction) { int prevIndex = 0; for (int i = 1; i < times.size(); ++i) { float time = times.get(i); if (time >= fraction) { // inclusive of start time at next interval. So fraction==1 // will return the final interval (times.size() - 1) return prevIndex; } prevIndex = i; } return prevIndex; } float getTime(int index) { return times.get(index); } }timingframework_1.0.orig/org/jdesktop/animation/timing/interpolation/KeyValues.java0000644000175000017500000001527510611204406027672 0ustar tonytony/** * Copyright (c) 2006, Sun Microsystems, Inc * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials provided * with the distribution. * * Neither the name of the TimingFramework project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.jdesktop.animation.timing.interpolation; import java.awt.Point; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; import java.util.List; /** * Stores a list of values that correspond to the times in a {@link * KeyTimes} object. These structures are then used to create a * {@link KeyFrames} object, which is then used to create a * {@link PropertySetter} for the purposes of modifying an object's * property over time. *

* At each of the times in {@link KeyTimes}, the property will take * on the corresponding value in the KeyValues object. Between these * times, the property will take on a value based on the interpolation * information stored in the KeyFrames object and the {@link * Evaluator} for the type of the values in KeyValues. *

* This class has built-in support for various known types, as defined * in {@link Evaluator}. *

* For a simple example using KeyValues to create a KeyFrames and * PropertySetter object, see the class header comments in * {@link PropertySetter}. * * * @author Chet */ public class KeyValues { private final List values = new ArrayList(); private final Evaluator evaluator; private final Class type; private T startValue; /** * Constructs a KeyValues object from one or more values. The * internal Evaluator is automatically determined by the * type of the parameters. * * @param params the values to interpolate between. If there is only * one parameter, this is assumed to be a "to" animation where the * first value is dynamically determined at runtime when the animation * is started. * @throws IllegalArgumentException if an {@link Evaluator} cannot be * found that can interpolate between the value types supplied */ public static KeyValues create(T... params) { return new KeyValues(params); } /** * Constructs a KeyValues object from a Evaluator * and one or more values. * * @param params the values to interpolate between. If there is only * one parameter, this is assumed to be a "to" animation where the * first value is dynamically determined at runtime when the animation * is started. * @throws IllegalArgumentException if params does not have at least * one value. */ public static KeyValues create(Evaluator evaluator, T... params) { return new KeyValues(evaluator, params); } /** * Private constructor, called by factory method */ private KeyValues(T... params) { this(Evaluator.create(params.getClass().getComponentType()), params); } /** * Private constructor, called by factory method */ private KeyValues(Evaluator evaluator, T... params) { if (params == null) { throw new IllegalArgumentException("params array cannot be null"); } else if (params.length == 0) { throw new IllegalArgumentException( "params array must have at least one element"); } if (params.length == 1) { // this is a "to" animation; set first element to null values.add(null); } Collections.addAll(values, params); this.type = params.getClass().getComponentType(); this.evaluator = evaluator; } /** * Returns the number of values stored in this object. * * @return the number of values stored in this object */ int getSize() { return values.size(); } /** * Returns the data type of the values stored in this object. * * @return a Class value representing the type of values stored in this * object */ Class getType() { return this.type; } /** * Called at start of animation; sets starting value in simple * "to" animations. */ void setStartValue(T startValue) { if (isToAnimation()) { this.startValue = startValue; } } /** * Utility method for determining whether this is a "to" animation * (true if the first value is null). */ boolean isToAnimation() { return (values.get(0) == null); } /** * Returns value calculated from the value at the lower index, the * value at the upper index, the fraction elapsed between these * endpoints, and the evaluator set up by this object at construction * time. */ T getValue(int i0, int i1, float fraction) { T value; T lowerValue = values.get(i0); if (lowerValue == null) { // "to" animation lowerValue = startValue; } if (i0 == i1) { // trivial case value = lowerValue; } else { T v0 = lowerValue; T v1 = values.get(i1); value = evaluator.evaluate(v0, v1, fraction); } return value; } }