// Copyright 1996, Marimba Inc. All Rights Reserved.


// @(#)AnimatedImageWidget.java, 1.25, 11/13/96





package marimba.gui;





import java.awt.*;


import java.net.*;





import marimba.persist.*;





/**


 * A simple animation widget modelled after the AnimatedImage applets.


 *


 * @author	Arthur van Hoff


 * @version 	1.25, 11/13/96


 */


public class AnimatedImageWidget extends AnimatedWidget {


    /**


     * The frame number with which the animation starts.


     * @see #getStartframe


     * @see #setStartframe


     */


    public int startframe = 1;





    /**


     * The frame number with which the animation ends.


     * @see #getEndframe


     * @see #setEndframe


     */


    public int endframe = 8;





    /**


     * The current x-position of the image being displayed.


     */


    public float imgx;





    /**


     * The current y-position of the image being displayed.


     */


    public float imgy;





    /**


     * The source directory in which the images for the


     * animation reside. In that directory there must be .gif


     * files with the name T's'.gif to T'e'.gif, where 'e' is


     * endFrame and 's' is the startFrame.


     * If both startframe and endframe are zero, it is assumed


     * that the animation consists of one image with the filename


     * in this variable. So in that case no subdirectory is used.


     * @see #getSource


     * @see #setSource


     */


    public String  src = "~builder/jon";





    /**


     * The number of pixels to be skipped in the x-direction.


     * This also determines the direction of the animation.


     * @see #getDx


     * @see #setDx


     * @see #setDirection


     */


    public int  dx = 0;





    /**


     * The number of pixels to be skipped in the y-direction.


     * This also determines the direction of the animation.


     * @see #getDy


     * @see #setDy


     * @see #setDirection


     */


    public int  dy = 0;





    /**


     * Preload the animation frames when the animation is


     * first created.


     */


    public boolean preload;





    Image imgs[];





    /**


     * Create an animation with the rotating head of Johnathan.


     */


    public AnimatedImageWidget() {


	this("~builder/jon", 7, 1, 8);


    }





    /**


     * Create an animation.


     */


    public AnimatedImageWidget(String src, int fps, int startFrame, int endFrame) {


	this.src = src;


	this.fps = fps;


	this.startframe = startframe;;


	this.endframe = endframe;


    }





    /**


     * Get the properties of this widget.


     */


    public void getProperties(PropertyList list) {


	super.getProperties(list);


	list.setBoolean("preload", preload, false);


	list.setInteger("dx", dx, 0);


	list.setInteger("dy", dy, 0);


	list.setInteger("startframe", startframe, 1);


	list.setInteger("endframe", endframe, 0);


	list.setURL("src", src, null);


    }





    /**


     * Set the properties of this widget.


     */


    public void setProperties(PropertyList list) {


	super.setProperties(list);


	preload = list.getBoolean("preload", false);


	dx = list.getInteger("dx", 0);


	dy = list.getInteger("dy", 0);


	startframe = list.getInteger("startframe", 1);


	endframe = list.getInteger("endframe", 0);


	src = list.getURL("src", null);


	imgx = imgy = 0;


    }





    /**


     * Get the frame number with which the animation starts.


     * @see #startframe


     */


    public int getStartframe() {


	return startframe;


    }





    /**


     * Set the frame number with which the animation starts.


     * @see #startframe


     */


    public void setStartframe(int startframe) {


	if (this.startframe != startframe) {


	    this.startframe = startframe;


	    init();


	}


    }





    /**


     * Get the frame number with which the animation ends.


     * @see #endframe


     */


    public int getEndframe() {


	return endframe;


    }





    /**


     * Set the frame number with which the animation ends.


     * @see #endframe


     */


    public void setEndframe(int endframe) {


	if (this.endframe != endframe) {


	    this.endframe = endframe;


	    init();


	}


    }





    /**


     * Get the source for this animated image.


     * @see #src


     */


    public String getSource() {


	return src;


    }





    /**


     * Set the source for this animated image.


     * @see #src


     */


    public void setSource(String src) {


	if (src != null && !src.equals(this.src)) {


	    this.src = src;


	    init();


	}


    }





    /**


     * Load the animation frames.


     */


    public void init() {


	if ((startframe  == 0) && (endframe == 0)) {


	    imgs = new Image[1];


	    imgs[0] = getImage(src);


	} else if (startframe <= endframe) {


	    Toolkit tk = Toolkit.getDefaultToolkit();


	    int nimgs = (endframe - startframe) + 1;


	    imgs = new Image[nimgs];


	    for (int i = 0 ; i < nimgs ; i++) {


		imgs[i] = getImage(src + "/T" + (startframe + i) + ".gif");


		if (preload) {


		    tk.prepareImage(imgs[i], -1, -1, this);


		}


	    }


	}


    }





    /**


     * Start the animation.


     */


    public void start() {


	super.start();


	if ((src != null) && (imgs != null)) {


	    Toolkit tk = Toolkit.getDefaultToolkit();


	    for (int i = 0 ; i < imgs.length ; i++) {


		tk.prepareImage(imgs[i], -1, -1, this);


	    }


	}


    }





    /**


     * Get the number of pixels to be skipped in the x-direction.


     * @see #dx


     */


    public int getDx() {


	return dx;


    }





    /**


     * Set the number of pixels to be skipped in the x-direction.


     * @see #dx


     */


    public void setDx(int dx) {


	this.dx = dx;


    }





    /**


     * Get the number of pixels to be skipped in the y-direction.


     * @see #dy


     */


    public int getDy() {


	return dy;


    }





    /**


     * Set the number of pixels to be skipped in the y-direction.


     * @see #dy


     */


    public void setDy(int dy) {


	this.dy = dy;


    }





    /**


     * Set the direction.


     * @see #dx


     * @see #dy


     */


    public void setDirection(int dx, int dy) {


	this.dx = dx;


	this.dy = dy;


    }





    /**


     * Advance the animation.


     */


    public void advance() {


	if (imgs != null) {


	    frame = (frame + 1 < imgs.length) ? frame + 1 : 0;


	    if (dx != 0) {


		imgx += (float)dx/fps;





		int w = imgs[0].getWidth(null);


		if (w > 0) {


		    if (imgx + w < 0) {


			imgx = width + imgx + w;


		    } else if (imgx > width) {


			imgx -= width + w;


		    }


		}


	    }


	    if (dy != 0) {


		imgy += (float)dy/fps;





		int h = imgs[0].getHeight(null);


		if (h > 0) {


		    if (imgy + h < 0) {


			imgy = height + imgy + h;


		    } else if (imgy > height) {


			imgy -= height + h;


		    }


		}


	    }


	    repaint();


	}


    }





    /**


     * Update the image.


     */


    public boolean imageUpdate(Image newimg, int flags, int x, int y, int w, int h) {


	if ((flags & ALLBITS) != 0) {


	    if ((imgs != null) && (imgs.length > 0) && (imgs[frame % imgs.length] == newimg)) {


		repaint();


	    }


	    return false;


	}


	return (flags & ERROR) == 0;


    }





    /**


     * Paint the current frame of animation.


     */


    public synchronized void paint(Graphics g) {


	if ((imgs != null) && (imgs.length > 0)) {


	    g.drawImage(imgs[frame % imgs.length], (int)imgx, (int)imgy, (fps > 0) ? null : this);


	}


    }   


}


