home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-18 | 16.2 KB | 640 lines |
- package symantec.itools.multimedia;
-
- import java.awt.Graphics;
- import java.awt.MediaTracker;
- import java.awt.Canvas;
- import java.awt.Image;
- import java.awt.Dimension;
- import java.net.URL;
- import java.util.Vector;
- import java.util.Enumeration;
- import java.beans.PropertyVetoException;
- import java.beans.PropertyChangeListener;
- import java.beans.VetoableChangeListener;
- import java.beans.PropertyChangeEvent;
-
- // 01/29/97 TWB Integrated changes from Windows
- // 05/30/97 RKM Changed symantec.beans references to java.beans
- // Moved AnimatorImage class into its own file as the compiler suggested
- // 05/31/97 RKM Updated to support Java 1.1
- // Made properties bound & constrained
- // 07/15/97 CAR marked fields transient as needed
- // modified addImage to call the AnimatorImage constructor which takes a Component reference
- // 08/27/97 CAR setting repeatMode from false to true will re-start the animation
-
- /**
- * This is a simple animation component. <br>
- * It creates an animation by displaying a series of images in sequence.
- * The programmer can specify the delay between frames in milliseconds.
- * The animation can loop for a specific
- * number of iterations or can run forever.
- *
- * @version 1.0, Nov 26, 1996
- * @author Symantec
- */
-
- public class Animator extends Canvas implements Runnable, PropertyChangeListener
- {
- /**
- * Constructs a default Animator. The animator defaults to a 500 millisecond delay, and loops forever.
- */
- public Animator()
- {
- delay = 500;
- numLoops = 1;
- forever = true;
- images = new Vector();
- currentImage = null;
- clearFrame = false;
- previewMode = false;
-
- maxWidth = 0;
- maxHeight = 0;
-
- vetos = new symantec.itools.beans.VetoableChangeSupport(this);
- changes = new symantec.itools.beans.PropertyChangeSupport(this);
-
- changes.addPropertyChangeListener(this);
- }
-
- //
- // Properties
- //
-
- /**
- * Sets the delay between animation frames.
- * @param i animation delay, in milliseconds
- * @see #getDelay
- * @exception PropertyVetoException
- * if the specified property value is unacceptable
- */
- public void setDelay(int newDelay)
- throws PropertyVetoException
- {
- if (delay != newDelay)
- {
- Integer oldDelayInt = new Integer(delay);
- Integer newDelayInt = new Integer(newDelay);
-
- vetos.fireVetoableChange("Delay", oldDelayInt, newDelayInt);
-
- delay = newDelay;
-
- changes.firePropertyChange("Delay", oldDelayInt, newDelayInt);
- }
- }
-
- /**
- * Returns the current delay between animation frames.
- * @return current animation delay, in milliseconds
- * @see #setDelay
- */
- public int getDelay()
- {
- return delay;
- }
-
- /**
- * Sets the number of loops to perform when displaying
- * the animation set.
- * @param i loop count
- * @see #getNumLoops
- * @exception PropertyVetoException
- * if the specified property value is unacceptable
- */
- public void setNumLoops(int newNumLoops)
- throws PropertyVetoException
- {
- if (numLoops != newNumLoops)
- {
- Integer oldNumLoopsInt = new Integer(numLoops);
- Integer newNumLoopsInt = new Integer(newNumLoops);
-
- vetos.fireVetoableChange("NumLoops", oldNumLoopsInt, newNumLoopsInt);
-
- numLoops = newNumLoops;
-
- changes.firePropertyChange("NumLoops", oldNumLoopsInt, newNumLoopsInt);
- }
- }
-
- /**
- * Returns the current animation set loop count.
- * @return loop count
- * @see #setNumLoops
- */
- public int getNumLoops()
- {
- return numLoops;
- }
-
- /**
- * Sets the repeat mode setting.
- * @param b repeat mode, repeats if true
- * @see #getRepeatMode
- * @exception PropertyVetoException
- * if the specified property value is unacceptable
- */
- public void setRepeatMode(boolean newRepeatMode)
- throws PropertyVetoException
- {
- if (forever != newRepeatMode)
- {
- Boolean oldRepeatModeBool = new Boolean(forever);
- Boolean newRepeatModeLoopsBool = new Boolean(newRepeatMode);
-
- vetos.fireVetoableChange("RepeatMode", oldRepeatModeBool, newRepeatModeLoopsBool);
-
- forever = newRepeatMode;
-
- changes.firePropertyChange("RepeatMode", oldRepeatModeBool, newRepeatModeLoopsBool);
- }
- }
-
- /**
- * @deprecated
- * @see #isRepeatMode
- */
- public boolean getRepeatMode()
- {
- return isRepeatMode();
- }
-
- /**
- * Returns the current repeat mode setting.
- * @return current repeat mode setting, true if repeat forever
- * @see #setRepeatMode
- */
- public boolean isRepeatMode()
- {
- return forever;
- }
-
- /**
- * Sets the image list. Images in this list are displayed in
- * sequence to form the animation.
- * @param list array of image URLs
- * @see #getImageList
- * @exception PropertyVetoException
- * if the specified property value is unacceptable
- */
- public synchronized void setImageList(URL[] newImageList)
- throws PropertyVetoException
- {
- //???RKM??? I'm not comparing the two lists here, should I?
-
- boolean wasAnimating = (displayThread != null);
-
- if (wasAnimating)
- stopAnimation();
-
- URL[] oldImageList = getImageList();
-
- vetos.fireVetoableChange("ImageList", oldImageList, newImageList);
-
- currentImage = null;
-
- images = new Vector();
- for (int i = 0; i < newImageList.length; ++i)
- addImage(newImageList[i]);
-
- changes.firePropertyChange("ImageList", oldImageList, newImageList);
-
- if (wasAnimating || previewMode || !java.beans.Beans.isDesignTime())
- {
- startAnimation();
- }
- else if (newImageList.length > 0)
- {
- currentImage = ((AnimatorImage)images.elementAt(0)).image;
- }
-
- repaint();
- }
-
- /**
- * Returns the image list.
- * @return URL list of images
- * @see #setImageList
- */
- public synchronized URL[] getImageList()
- {
- URL[] list = new URL[images.size()];
-
- int i = 0;
- Enumeration enum = images.elements();
- while (enum.hasMoreElements())
- {
- list[i++] = ((AnimatorImage)enum.nextElement()).url;
- }
-
- return list;
- }
-
- /**
- * Sets whether or not the animation frame area is cleared
- * between each frame.
- * @param newClearFrame if true, the frame area is cleared between each
- * animation frame; if false, the frame area is not cleared.
- * @see #getClearFrame
- * @exception PropertyVetoException
- * if the specified property value is unacceptable
- */
- public void setClearFrame(boolean newClearFrame)
- throws PropertyVetoException
- {
- if (clearFrame = newClearFrame)
- {
- Boolean oldClearFrameBool = new Boolean(clearFrame);
- Boolean newClearFrameBool = new Boolean(newClearFrame);
-
- vetos.fireVetoableChange("ClearFrame", oldClearFrameBool, newClearFrameBool);
-
- clearFrame = newClearFrame;
-
- changes.firePropertyChange("ClearFrame", oldClearFrameBool, newClearFrameBool);
- }
- }
-
- /**
- * @deprecated
- * @see #isClearFrame
- */
- public boolean getClearFrame()
- {
- return isClearFrame();
- }
-
- /**
- * Gets the current clear frame setting.
- * @return boolean - if true, the frame area is cleared
- * between each animation frame; if false, the frame area
- * is not cleared.
- * @see #setClearFrame
- */
- public boolean isClearFrame()
- {
- return clearFrame;
- }
-
- /**
- * Sets the preview mode flag. This flag is used by Visual Cafe to
- * determine if this component should be run during design time.
- * @param newPreviewMode new preview mode
- * @see #getPreviewMode
- */
- public void setPreviewMode(boolean newPreviewMode)
- {
- if (previewMode != newPreviewMode)
- {
- if (java.beans.Beans.isDesignTime())
- {
- previewMode = newPreviewMode;
-
- if (previewMode && (images.size() > 0))
- startAnimation();
- else
- stopAnimation();
- }
- }
- }
-
- /**
- * @deprecated
- * @see #setPreviewMode
- */
- public boolean getPreviewMode()
- {
- return isPreviewMode();
- }
-
- /**
- * Gets the preview mode flag. This flag is used by Visual Cafe to
- * determine if this component should be run during design time.
- * @see #setPreviewMode
- */
- public boolean isPreviewMode()
- {
- return previewMode;
- }
-
- //
- // Methods
- //
-
- /**
- * Adds an image to the animation set.
- * @param url URL of the image to add
- */
- public synchronized void addImage(URL url)
- {
- Image image = getToolkit().getImage(url);
-
- boolean loadWait = images.size() == 0 || previewMode || !java.beans.Beans.isDesignTime();
-
- if (loadWait)
- {
- imageLoadWait(image);
- }
-
- images.addElement(new AnimatorImage(url, image, loadWait, this));
- }
-
- /**
- * Starts the animation.
- * @see #stopAnimation
- */
- public void startAnimation()
- {
- if (displayThread == null)
- {
- displayThread = new Thread(this);
- displayThread.start();
- }
- else
- {
- try {
- displayThread.join();
- } catch (InterruptedException e) {}
- displayThread = new Thread(this);
- displayThread.start();
- }
- }
-
- /**
- * Stops the animation.
- * @see #startAnimation
- */
- public void stopAnimation()
- {
- if (displayThread != null)
- {
- displayThread.stop();
- displayThread = null;
- }
- }
-
- /**
- * Body of Animation Thread. This method is called by the Java Virtual Machine
- * in response to a call to the start method of this object.
- */
-
- public synchronized void run()
- {
- for (int i = 0; i < numLoops || forever; ++i)
- {
- if (images.size() == 0)
- {
- try
- {
- wait(delay);
- }
- catch(InterruptedException e)
- {
- }
-
- }
- else
- {
-
- for (int j = 0; j < images.size(); ++j)
- {
- synchronized(this)
- {
- try
- {
- wait(delay);
- }
- catch(InterruptedException e)
- {
- }
-
- AnimatorImage ai = (AnimatorImage)images.elementAt(j);
-
- if (!ai.loaded)
- {
- imageLoadWait(ai.image);
- images.setElementAt(new AnimatorImage(ai.url, ai.image, true), j);
- }
-
- currentImage = ai.image;
- }
-
- repaint();
- }
- }
- }
- }
-
- /**
- * Paints this component using the given graphics context.
- * This is a standard Java AWT method which typically gets called
- * by the AWT to handle painting this component. It paints this component
- * using the given graphics context. The graphics context clipping region
- * is set to the bounding rectangle of this component and its <0,0>
- * coordinate is this component's top-left corner.
- *
- * @param g the graphics context used for painting
- * @see java.awt.Component#repaint
- * @see #update
- */
- public synchronized void paint(Graphics g)
- {
- if (currentImage != null)
- g.drawImage(currentImage, 0, 0, this);
- }
-
- /**
- * Handles redrawing of this component on the screen.
- * This is a standard Java AWT method which gets called by the Java
- * AWT (repaint()) to handle repainting this component on the screen.
- * The graphics context clipping region is set to the bounding rectangle
- * of this component and its <0,0> coordinate is this component's
- * top-left corner.
- * Typically this method paints the background color to clear the
- * component's drawing space, sets graphics context to be the foreground
- * color, and then calls paint() to draw the component.
- *
- * It is overridden here to make clearing the background before painting
- * optional. If the clearFrame flag is true the background will be erased
- * before painting begins.
- *
- * @param g the graphics context
- * @see java.awt.Component#repaint
- * @see #paint
- */
- public void update(Graphics g)
- {
- if (clearFrame)
- super.update(g);
- else
- paint(g);
- }
-
- /**
- * Returns the recommended dimensions to properly display this component.
- * This is a standard Java AWT method which gets called to determine
- * the recommended size of this component.
- *
- * @return If no images have been loaded, a dimension of 10 by 10 is returned.
- * If one or more images have been loaded, the largest height and the
- * largest width of any image is returned.
- *
- * @see #minimumSize
- */
- public Dimension preferredSize()
- {
- if (images == null || images.size() == 0)
- return new Dimension(10, 10);
-
- return new Dimension(maxWidth, maxHeight);
- }
-
- /**
- * Returns the minimum dimensions to properly display this component.
- * This is a standard Java AWT method which gets called to determine
- * the minimum size of this component.
- *
- * @return If no images have been loaded, a dimension of 10 by 10 is returned.
- * If one or more images have been loaded, the largest height and the
- * largest width of any image is returned.
- *
- * @see #preferredSize
- */
- public Dimension minimumSize()
- {
- return preferredSize();
- }
-
- /**
- * A method of the PropertyChangeListener interface.
- * This method is called when a property of this component changes.
- * It starts the animation when the Repeat Mode property is set.
- * @param the event
- * @see java.awt.PropertyChangeListener
- */
- public void propertyChange(PropertyChangeEvent evt)
- {
- String property = evt.getPropertyName();
-
- if(property != null) {
- if(property.equalsIgnoreCase("RepeatMode")) {
- startAnimation();
- }
- }
-
- }
-
- /**
- * Adds a listener for all event changes.
- * @param PropertyChangeListener listener the listener to add.
- * @see #removePropertyChangeListener
- */
- public void addPropertyChangeListener(PropertyChangeListener listener)
- {
- changes.addPropertyChangeListener(listener);
- }
-
- /**
- * Removes a listener for all event changes.
- * @param PropertyChangeListener listener the listener to remove.
- * @see #addPropertyChangeListener
- */
- public void removePropertyChangeListener(PropertyChangeListener listener)
- {
- changes.removePropertyChangeListener(listener);
- }
-
- /**
- * Adds a vetoable listener for all event changes.
- * @param VetoableChangeListener listener the listener to add.
- * @see #removeVetoableChangeListener
- */
- public void addVetoableChangeListener(VetoableChangeListener listener)
- {
- vetos.addVetoableChangeListener(listener);
- }
-
- /**
- * Removes a vetoable listener for all event changes.
- * @param VetoableChangeListener listener the listener to remove.
- * @see #addVetoableChangeListener
- */
- public void removeVetoableChangeListener(VetoableChangeListener listener)
- {
- vetos.removeVetoableChangeListener(listener);
- }
-
- void imageLoadWait(Image image)
- {
- MediaTracker tracker = new MediaTracker(this);
-
- tracker.addImage(image, 0);
-
- try
- {
- tracker.waitForAll();
- }
- catch(InterruptedException e)
- {
- }
-
- int size;
-
- if ((size = image.getWidth(this)) > maxWidth)
- maxWidth = size;
-
- if ((size = image.getHeight(this)) > maxHeight)
- maxHeight = size;
- }
-
- /**
- * Delay time between images, in milliseconds.
- */
- protected int delay;
-
- /**
- * Number of times to show the animation sequence.
- */
- protected int numLoops;
-
- /**
- * Run animation forever. If false, use numLoops.
- */
- protected boolean forever;
-
- /**
- * Images to be displayed.
- */
- protected Vector images;
-
- /**
- * Image currently being shown.
- */
- transient protected Image currentImage;
-
- /**
- * Thread which runs the animation.
- */
- transient protected Thread displayThread;
-
- /**
- * Dimension of largest image in sequence.
- */
- protected int maxWidth, maxHeight;
-
- /**
- * Clear frame between each image.
- */
- protected boolean clearFrame;
-
- /**
- * Preview this component at design time.
- */
- protected boolean previewMode;
-
- // Private members
- private symantec.itools.beans.VetoableChangeSupport vetos;
- private symantec.itools.beans.PropertyChangeSupport changes;
- }
-