/* File: GIFCanvasPlusApplet.java
 * Copyright (C) 1998 by Bill Giel/KCMDG. All rights reserved.
 *
 * This little applet demonstrates use of an extended GIFCanvas
 * class to display animated GIF's with Java-controlled foreground
 * animation.
 */
 
import java.awt.*;
import java.io.*;
import java.applet.*;
import java.net.*;

import com.kcmultimedia.gifcanvas.*;

/////////////////////////////////////////////////////////////////////////////
// Used to pass a mouseDown event to an interested listener. In this example
// the GIFCanvas is the source of the event and the applet is the listener.
// When the canvas is clicked, the applet will attempt to show the associated
// document.
/////////////////////////////////////////////////////////////////////////////

interface ClickListener
{
    public void handleClick();
}

/////////////////////////////////////////////////////////////////////////////
// This class contains a bouncing ball image, its current coordinates and
// direction.
/////////////////////////////////////////////////////////////////////////////

class PongBall
{
    Image image;
    int X;
    int Y;
    double theta;
}

////////////////////////////////////////////////////////////////////////////
// Here's the heart of the applet, an extended class of GIFCanvas that paints
// a standard animated GIF as the background, and does some other "creative"
// stuff in the foreground, hopefully enticing the viewer to click-thru the
// banner.
/////////////////////////////////////////////////////////////////////////////

class GIFCanvasPlus extends GIFCanvas
{
    Image buffer; //For double-buffered display.
    Graphics og;  //Graphics context for buffer.

    boolean quit; //Thread killer
    
    int x1, //Minimum barrier x-coordinate, bounce when "hit".
        x2, //Maximum barrier x-coordinate, bounce when "hit".
        y1, //Minimum barrier y-coordinate, bounce when "hit".
        y2, //Maximum barrier y-coordinate, bounce when "hit".
        W;  //half-width of a "PongBall" (all are the same).

            //We don't need separate half-heights since we are
            //using "square" images.

        
    int w,  //The overall width of the GIFCanas
        h;  //The overall height of the GIFCanvas
        
    int d = 5; //How far does each PongBall move per iteration
    
    int delay = 10; //Milliseconds delay before recomputing/repainting
                    //the PongBalls

    Thread thread;  //A Thread for our animation loop, independent of the
                    //GIFCanvas animation loop.

    PongBall[] pongBalls; //An array of PongBalls, the little bouncy things
                          //that dart over the GIFCanvas background.

    ClickListener cl; //The ClickListener is notified when a mouseDown Event
                      //occurs within the GIFCanvas.
    
    public GIFCanvasPlus(URL bg, URL[] imageNames, ClickListener cl)
        throws Exception
    {
        super(bg);
        this.cl = cl;
 
        pongBalls = new PongBall[imageNames.length];
        MediaTracker tracker = new MediaTracker(this);        

        for(int i=0; i<imageNames.length; i++){
            pongBalls[i] = new PongBall();
            pongBalls[i].image = getToolkit().getImage(imageNames[i]);
            tracker.addImage(pongBalls[i].image,i);
        }
       
        try{
            tracker.waitForAll();
        }catch(Exception e){}
        
        W = pongBalls[0].image.getWidth(this)/2;
    }

    public void start()
    {
        super.start();
        if(null == thread){
            thread=new Thread();
            thread.start();
        }
        quit=false;
        animate();
    }

    public void stop()
    {
        quit=true;
    }    

    public void paint(Graphics g)
    {
        if(null == buffer){
            w=size().width;
            h=size().height;
            buffer = createImage(w, h);
            og = buffer.getGraphics();

             double j = Math.PI/(2*pongBalls.length);
             for(int i=0; i < pongBalls.length;i++){
                pongBalls[i].X = w/2;
                pongBalls[i].Y = h/2;
                pongBalls[i].theta = j;
                j+= Math.PI/2;

            }
 
            x1=W;x2=w-W;
            y1=W;y2=h-W;

            
        }
        super.paint(og);
        if(getCurrentFrame() < 20){
            for(int i=0; i<pongBalls.length; i++){
                og.drawImage(pongBalls[i].image, pongBalls[i].X-W, pongBalls[i].Y-W, this);
            }
        }

        g.drawImage(buffer,0,0,this);
    }

    public void update(Graphics g)
    {
        paint(g);
    }

    private void where(PongBall pb)
    {
            pb.X = (int)(pb.X + d * Math.sin(pb.theta));
            pb.Y = (int)(pb.Y - d * Math.cos(pb.theta));

            if(pb.X <= x1){
                pb.X=x1;
                pb.theta = 2.0 * Math.PI - pb.theta;
            }
            else if(pb.X >= x2){
                 pb.X=x2;
                pb.theta = 2.0 * Math.PI - pb.theta;
            }
            if(pb.Y <= y1){
                pb.Y=y1;
                pb.theta = 3.0 * Math.PI - pb.theta;
            }
            else if(pb.Y >= y2){
                pb.Y=y2;
                pb.theta = 3.0 * Math.PI - pb.theta;
            }
    }


    public boolean mouseDown(Event e, int x, int y)
    {
        if(null != cl)
            cl.handleClick();

        return true;
    }
        

        

    public void animate()
    {
        while(!quit){

            for(int i=0; i<pongBalls.length; i++){
                where(pongBalls[i]);
            }
            repaint();

            try{
                thread.sleep(delay);
            }catch(Exception e){}
        }
        thread = null;
    }
}


public class GIFCanvasPlusApplet extends Applet
    implements ClickListener, Runnable
{
    GIFCanvasPlus gif;
    URL hyperlink;
    Thread kicker;

    public void init()
    {
        ////////////////////////////////////////////////////////////////////
        //These would probably be provided through applet parameters. We're
        //hardcoding them here for the sake of simplicity.
        ////////////////////////////////////////////////////////////////////
        String mainImage = "kcmdg.gif";
        String[] ballImages = {"ball1.gif", "ball2.gif", "ball3.gif"};
        
        setLayout(new BorderLayout());

        try{
            URL animatedGIF = new URL(getCodeBase(), "images/" + mainImage);
            URL[] balls = new URL[ballImages.length];
            for(int i = 0; i < ballImages.length; i++){
                balls[i] = new URL(getCodeBase(), "images/" + ballImages[i]);
            }
            hyperlink = new URL("http://www.kcmultimedia.com");
            gif = new GIFCanvasPlus(animatedGIF, balls, this);            
            
        }catch(Exception e){
            System.out.println(e.toString());
            return;
        }

	    add("North",gif);
    }

    public void start()
    {
        if(null == kicker){
             kicker = new Thread(this);
            kicker.start();
        }
    }

    public void stop()
    {
        kicker=null;
    }

    public void run()
    {
        gif.start();
        kicker=null;
    }
    
    public void destroy()
    {
        gif.stop();
    }

    public void handleClick()
    {
        getAppletContext().showDocument(hyperlink);
    }

    
}

