home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / IFC_112 / netscape / application / DrawingSequence.java < prev    next >
Encoding:
Text File  |  1999-05-28  |  15.6 KB  |  484 lines  |  [TEXT/CWIE]

  1. // DrawingSequence.java
  2. // By Ned Etcode
  3. // Copyright 1995, 1996, 1997 Netscape Communications Corp.  All rights reserved.
  4.  
  5. package netscape.application;
  6.  
  7. import netscape.util.*;
  8.  
  9. /** Abstract Image subclass that simplifies frame-by-frame animation.  A
  10.   * DrawingSequence works with a collection of "frames."  It animates
  11.   * its frames by incrementing or decrementing its current frame number and
  12.   * drawing the new frame.  A DrawingSequence is not a View - it must ask its
  13.   * owner, typically a View, to display its new frame by calling its
  14.   * <b>drawingSequenceFrameChanged()</b> method.<p>
  15.   * Note that the machinery within the DrawingSequence abstract class does not
  16.   * know what it's animating, only that it has a current frame number that
  17.   * must be incremented or decremented.  As a subclasser overriding the
  18.   * <b>drawAt()</b> method, you can perform whatever drawing operation you
  19.   * want, such as draw a Bitmap or fill a Rect, based on the value returned by
  20.   * <b>currentFrameNumber()</b>.  The ImageSequence class is
  21.   * a DrawingSequence subclass that specifically animates a collection of
  22.   * Images.  If you only need to animate Images, you should use
  23.   * an instance of the ImageSequence class.
  24.   * @see DrawingSequenceOwner
  25.   * @see ImageSequence
  26.   * @note 1.0 stop constant was fixed to 'stop'
  27.   */
  28. public abstract class DrawingSequence extends Image implements Target, Codable{
  29.     DrawingSequenceOwner            owner;
  30.     String              name;
  31.     Timer               animateTimer;
  32.     int                 currentFrameNumber, frameCount, frameRate;
  33.     int                 playbackMode;
  34.     boolean             animating, resetOnStart, resetOnStop,
  35.                         bounceForward = true;
  36.  
  37.     /** Increment the frame number; upon reaching the sequence's last frame,
  38.         stop animating. */
  39.     public final static int     FORWARD = 0;
  40.  
  41.     /** Increment the frame number;  upon reaching the sequence's last frame,
  42.         return to the first frame and continue animating. */
  43.     public final static int     FORWARD_LOOP = 1;
  44.  
  45.     /** Decrement the frame number; upon reaching the sequence's first frame,
  46.         stop animating. */
  47.     public final static int     BACKWARD = 2;
  48.  
  49.     /** Decrement the frame number;  upon reaching the sequence's first frame,
  50.         return to the last frame and continue animating. */
  51.     public final static int     BACKWARD_LOOP = 3;
  52.  
  53.     /** Increment the frame number; upon reaching the sequence's last frame,
  54.         decrement to the first frame, then start again. */
  55.     public final static int     BOUNCE = 4;
  56.  
  57.     final static int            MIN_FRAME_RATE = 1;
  58.  
  59.     final static String         OWNER_KEY = "owner", NAME_KEY = "name",
  60.                                 CURRENTFRAME_KEY = "currentFrameNumber",
  61.                                 FRAMECOUNT_KEY = "frameCount",
  62.                                 FRAME_RATE_KEY = "frameRate",
  63.                                 PLAYBACKMODE_KEY = "playbackMode",
  64.                                 ANIMATING_KEY = "animating",
  65.                                 RESETONSTART_KEY = "resetOnStart",
  66.                                 RESETONSTOP_KEY = "resetOnStop";
  67.  
  68.     /** Command that starts the DrawingSequence. */
  69.     public final static String START = "start";
  70.  
  71.     /** Command that stops the DrawingSequence. */
  72.     public final static String STOP = "stop";
  73.  
  74.     /** Command that moves the DrawingSequence to its next frame. */
  75.     public final static String NEXT_FRAME = "nextFrame";
  76.  
  77.     /* constructors */
  78.  
  79.     /** Constructs a DrawingSequence without an owner.
  80.       */
  81.     public DrawingSequence() {
  82.         this(null);
  83.     }
  84.  
  85.     /** Constructs a DrawingSequence with owner <B>owner</B>, frame
  86.       * rate of 1 millisecond, current frame number of 0, and FORWARD
  87.       * direction.
  88.       */
  89.     public DrawingSequence(DrawingSequenceOwner owner) {
  90.         super();
  91.  
  92.         this.owner = owner;
  93.         frameRate = MIN_FRAME_RATE;
  94.         playbackMode = FORWARD;
  95.     }
  96.  
  97.     /** Sets the DrawingSequence's owner, the object that the DrawingSequence
  98.       * contacts when its current frame number changes or the DrawingSequence
  99.       * reaches its final frame.
  100.       * @see DrawingSequenceOwner
  101.       */
  102.     public void setOwner(DrawingSequenceOwner anObject) {
  103.         owner = anObject;
  104.     }
  105.  
  106.     /** Returns the DrawingSequence's owner.
  107.       * @see #setOwner
  108.       */
  109.     public DrawingSequenceOwner owner() {
  110.         return owner;
  111.     }
  112.  
  113.     /** Sets the DrawingSequence's name. */
  114.     public void setName(String aName) {
  115.         name = aName;
  116.     }
  117.  
  118.      /** Returns the DrawingSequence's name.
  119.       * @see #setName
  120.       */
  121.     public String name() {
  122.         return name;
  123.     }
  124.  
  125.     /** Implemented to respond to the NEXT_FRAME, START and STOP commands.
  126.       * The NEXT_FRAME command results in calls to the
  127.       * <b>nextFrame()</b> method. If the DrawingSequence completes its
  128.       * animation, it sends the <b>drawingSequenceCompleted()</b> message to
  129.       * its owner and calls its <b>stop()</b> method, otherwise it sends the
  130.       * <b>drawingSequenceFrameChanged()</b> message to its owner. When the
  131.       * frame changes, the owner is responsible for redisplaying the
  132.       * DrawingSequence.  The START and STOP commands start or stop the
  133.       * DrawingSequence.
  134.       * @see DrawingSequenceOwner
  135.       * @see #stop
  136.       */
  137.     public void performCommand(String command, Object data) {
  138.         if (START.equals(command))
  139.             start();
  140.         else if (STOP.equals(command))
  141.             stop();
  142.         else if (NEXT_FRAME.equals(command)) {
  143.             nextFrame();
  144.         } else
  145.             throw new NoSuchMethodError("unknown command: " + command);
  146.     }
  147.  
  148.     /** Instructs the DrawingSequence to animate itself by changing its current
  149.       * frame every <b>frameRate()</b> milliseconds.
  150.       * @see #setFrameRate
  151.       */
  152.     public void start() {
  153.         if (resetOnStart) {
  154.             reset();
  155.         }
  156.  
  157.         animating = true;
  158.  
  159.         if (animateTimer == null) {
  160.             if (owner != null) {
  161.                 owner.drawingSequenceFrameChanged(this);
  162.             }
  163.  
  164.             animateTimer = new Timer(this, "nextFrame", frameRate);
  165.             animateTimer.start();
  166.         }
  167.     }
  168.  
  169.     /** Returns <b>true</b> if the DrawingSequence is currently animating
  170.       * itself.
  171.       * @see #start
  172.       */
  173.     public boolean isAnimating() {
  174.         return animating;
  175.     }
  176.  
  177.     /** Stops the DrawingSequence's animation.
  178.       * @see #start
  179.       */
  180.     public void stop() {
  181.         animating = false;
  182.         if (animateTimer != null) {
  183.             animateTimer.stop();
  184.             animateTimer = null;
  185.         }
  186.  
  187.         if (resetOnStop) {
  188.             reset();
  189.         }
  190.     }
  191.  
  192.     /** Sets the DrawingSequence's current frame to its initial frame:
  193.       * the first frame if it has a forward or bounce direction, its last
  194.       * if a backward direction.
  195.       */
  196.     public void reset() {
  197.         if (playbackMode == FORWARD || playbackMode == FORWARD_LOOP ||
  198.                playbackMode == BOUNCE) {
  199.             currentFrameNumber = 0;
  200.         } else {
  201.             currentFrameNumber = frameCount - 1;
  202.         }
  203.     }
  204.  
  205.     /** Sets the number of frames the DrawingSequence animates. */
  206.     public void setFrameCount(int count) {
  207.         if (count > 0) {
  208.             frameCount = count;
  209.         } else {
  210.             frameCount = 0;
  211.         }
  212.     }
  213.  
  214.     /** Returns the number of frames the DrawingSequence animates.
  215.       * @see #setFrameCount
  216.       */
  217.     public int frameCount() {
  218.         return frameCount;
  219.     }
  220.  
  221.     /** Sets the DrawingSequence's current frame number.  When asked to draw
  222.       * itself, a DrawingSequence displays its current frame.
  223.       */
  224.     public void setCurrentFrameNumber(int anInt) {
  225.         if (anInt < 0) {
  226.             anInt = 0;
  227.         } else if (anInt >= frameCount) {
  228.             anInt = frameCount - 1;
  229.         }
  230.  
  231.         currentFrameNumber = anInt;
  232.     }
  233.  
  234.     /** Returns the DrawingSequence's current frame number.
  235.       * @see #setCurrentFrameNumber
  236.       */
  237.     public int currentFrameNumber() {
  238.         return currentFrameNumber;
  239.     }
  240.  
  241.     /** Sets the millisecond delay between calls to <b>nextFrame()</b>.
  242.       * @see #nextFrame
  243.       */
  244.     public void setFrameRate(int milliseconds) {
  245.         if (milliseconds > MIN_FRAME_RATE) {
  246.             frameRate = milliseconds;
  247.         } else {
  248.             frameRate = MIN_FRAME_RATE;
  249.         }
  250.  
  251.         if (animateTimer != null) {
  252.             animateTimer.setDelay(frameRate);
  253.         }
  254.     }
  255.  
  256.     /** Returns the millisecond delay between calls to <b>nextFrame()</b>.
  257.       * @see #setFrameRate
  258.       */
  259.     public int frameRate() {
  260.         return frameRate;
  261.     }
  262.  
  263.     /** Sets the DrawingSequence's frame playback mode.  Currently, the five
  264.       * options are FORWARD, FORWARD_LOOP, BACKWARD, BACKWARD_LOOP, and
  265.       * BOUNCE.
  266.       * Resets the DrawingSequence's current frame to its initial frame by
  267.       * calling <b>reset()</b>.
  268.       * @see #reset
  269.       */
  270.     public void setPlaybackMode(int mode) {
  271.         if (mode < 0 || mode > BOUNCE) {
  272.             return;
  273.         }
  274.         playbackMode = mode;
  275.  
  276.         reset();
  277.     }
  278.  
  279.     /** Returns the DrawingSequence's playback mode.
  280.       * @see #setPlaybackMode
  281.       */
  282.     public int playbackMode() {
  283.         return playbackMode;
  284.     }
  285.  
  286.     /** Configures the DrawingSequence to automatically reset its frame to its
  287.       * initial frame (by calling <b>reset()</b>) before it begins
  288.       * animating.
  289.       * @see #setPlaybackMode
  290.       * @see #reset
  291.       * @see #start
  292.       */
  293.     public void setResetOnStart(boolean flag) {
  294.         resetOnStart = flag;
  295.     }
  296.  
  297.     /** Returns <b>true</b> if the DrawingSequence resets its frame
  298.       * to its initial frame before it begins animating.
  299.       * @see #setResetOnStart
  300.       */
  301.     public boolean doesResetOnStart() {
  302.         return resetOnStart;
  303.     }
  304.  
  305.     /** Sets the DrawingSequence to automatically reset its frame to its
  306.       * initial frame (by calling <b>reset()</b>) after it finishes
  307.       * animating.
  308.       * @see #setPlaybackMode
  309.       * @see #reset
  310.       * @see #stop
  311.       */
  312.     public void setResetOnStop(boolean flag) {
  313.         resetOnStop = flag;
  314.     }
  315.  
  316.     /** Returns <b>true</b> if the DrawingSequence resets its frame
  317.       * to its initial frame after it finishes animating.
  318.       * @see #setResetOnStop
  319.       */
  320.     public boolean doesResetOnStop() {
  321.         return resetOnStop;
  322.     }
  323.  
  324.     /** Returns <b>true</b> if the DrawingSequence continues animating
  325.       * from its initial frame after reaching its final frame, or if it
  326.       * animates in BOUNCE mode.
  327.       * @see #setPlaybackMode
  328.       */
  329.     public boolean doesLoop() {
  330.         return (playbackMode == FORWARD_LOOP ||
  331.                 playbackMode == BACKWARD_LOOP || playbackMode == BOUNCE);
  332.     }
  333.  
  334.     /** Moves the DrawingSequence to its next frame, incrementing or
  335.       * decrementing its frame number.  Returns <b>false</b> if the
  336.       * DrawingSequence has reached its final frame and its playback mode does
  337.       * not allow it to loop back to its initial frame.
  338.       * @see #setPlaybackMode
  339.       */
  340.     public boolean nextFrame() {
  341.         boolean framesLeft = true;
  342.  
  343.         if (frameCount == 0) {
  344.             stop();
  345.             throw new InconsistencyException("Frame count is 0");
  346.         }
  347.  
  348.         if (playbackMode == FORWARD || playbackMode == FORWARD_LOOP) {
  349.             currentFrameNumber++;
  350.             if (currentFrameNumber >= frameCount) {
  351.                 if (playbackMode != FORWARD_LOOP) {
  352.                     currentFrameNumber = frameCount - 1;
  353.                     framesLeft = false;
  354.                 } else {
  355.                     currentFrameNumber = 0;
  356.                 }
  357.             }
  358.         } else if (playbackMode == BOUNCE) {
  359.             framesLeft = true;
  360.             if (frameCount == 1) {
  361.                 currentFrameNumber = 0;
  362.             } else if (bounceForward == true) {
  363.                 currentFrameNumber++;
  364.                 if (currentFrameNumber >= frameCount) {
  365.                     bounceForward = false;
  366.                     currentFrameNumber = currentFrameNumber - 2;
  367.                 }
  368.             } else if (bounceForward == false) {
  369.                 currentFrameNumber--;
  370.                 if (currentFrameNumber < 0) {
  371.                     bounceForward = true;
  372.                     currentFrameNumber = currentFrameNumber + 2;
  373.                 }
  374.             }
  375.         } else {
  376.             currentFrameNumber--;
  377.             if (currentFrameNumber < 0) {
  378.                 if (playbackMode != BACKWARD_LOOP) {
  379.                     currentFrameNumber = 0;
  380.                     framesLeft = false;
  381.                 } else {
  382.                     currentFrameNumber = frameCount - 1;
  383.                 }
  384.             }
  385.         }
  386.  
  387.         if (framesLeft) {
  388.             if (owner != null) {
  389.                 owner.drawingSequenceFrameChanged(this);
  390.             }
  391.             return true;
  392.         } else {
  393.             stop();
  394.  
  395.             if (owner != null) {
  396.                 owner.drawingSequenceCompleted(this);
  397.             }
  398.             return false;
  399.         }
  400.     }
  401.  
  402.     /** Subclassers must implement this method to return the
  403.       * DrawingSequence's width.
  404.       */
  405.     public abstract int width();
  406.  
  407.     /** Subclassers must implement this method to return the
  408.       * DrawingSequence's height.
  409.       */
  410.     public abstract int height();
  411.  
  412.     /** Displays the DrawingSequence's current frame at the given location.
  413.       * Subclassers must implement this method to display the current frame.
  414.       */
  415.     public abstract void drawAt(Graphics g, int x, int y);
  416.  
  417.  
  418.  
  419. /* archiving */
  420.  
  421.  
  422.     /** Describes the DrawingSequence class' information.
  423.       * @see Codable#describeClassInfo
  424.       */
  425.     public void describeClassInfo(ClassInfo info) {
  426.         info.addClass("netscape.application.DrawingSequence", 1);
  427.         info.addField(OWNER_KEY, OBJECT_TYPE);
  428.         info.addField(NAME_KEY, STRING_TYPE);
  429.         info.addField(CURRENTFRAME_KEY, INT_TYPE);
  430.         info.addField(FRAMECOUNT_KEY, INT_TYPE);
  431.         info.addField(FRAME_RATE_KEY, INT_TYPE);
  432.         info.addField(PLAYBACKMODE_KEY, INT_TYPE);
  433.         info.addField(ANIMATING_KEY, BOOLEAN_TYPE);
  434.         info.addField(RESETONSTART_KEY, BOOLEAN_TYPE);
  435.         info.addField(RESETONSTOP_KEY, BOOLEAN_TYPE);
  436.     }
  437.  
  438.     /** Encodes the DrawingSequence instance.
  439.       * @see Codable#encode
  440.       */
  441.     public void encode(Encoder encoder) throws CodingException {
  442.         encoder.encodeObject(OWNER_KEY, (Codable)owner);
  443.  
  444.         encoder.encodeString(NAME_KEY, name);
  445.  
  446.         encoder.encodeInt(CURRENTFRAME_KEY, currentFrameNumber);
  447.         encoder.encodeInt(FRAMECOUNT_KEY, frameCount);
  448.         encoder.encodeInt(FRAME_RATE_KEY, frameRate);
  449.         encoder.encodeInt(PLAYBACKMODE_KEY, playbackMode);
  450.  
  451.         encoder.encodeBoolean(ANIMATING_KEY, animating);
  452.         encoder.encodeBoolean(RESETONSTART_KEY, resetOnStart);
  453.         encoder.encodeBoolean(RESETONSTOP_KEY, resetOnStop);
  454.     }
  455.  
  456.     /** Decodes the DrawingSequence instance.
  457.       * @see Codable#decode
  458.       */
  459.     public void decode(Decoder decoder) throws CodingException {
  460.         owner = (DrawingSequenceOwner)decoder.decodeObject(OWNER_KEY);
  461.  
  462.         name = decoder.decodeString(NAME_KEY);
  463.  
  464.         currentFrameNumber = decoder.decodeInt(CURRENTFRAME_KEY);
  465.         frameCount = decoder.decodeInt(FRAMECOUNT_KEY);
  466.         frameRate = decoder.decodeInt(FRAME_RATE_KEY);
  467.         playbackMode = decoder.decodeInt(PLAYBACKMODE_KEY);
  468.  
  469.         animating = decoder.decodeBoolean(ANIMATING_KEY);
  470.         resetOnStart = decoder.decodeBoolean(RESETONSTART_KEY);
  471.         resetOnStop = decoder.decodeBoolean(RESETONSTOP_KEY);
  472.     }
  473.  
  474.     /** Finishes the DrawingSequence decoding.
  475.       * @see Codable#finishDecoding
  476.       */
  477.     public void finishDecoding() throws CodingException {
  478.         if (animating) {
  479.             animating = false;
  480.             start();
  481.         }
  482.     }
  483. }
  484.