import java.awt.Graphics;
import java.util.*;
import java.awt.*;

/********************************************************************
 *
 * This extension to the Applet class bounces a line around in a box.
 *
 * The size of the box is specified by the 'width' and 'height'
 * values in the applet tag.
 *
 * @author  Dave Wylie
 * @version 0.1, 31-Jul-1996
 *
 ********************************************************************/
public class Stick extends java.applet.Applet implements Runnable
{
   int theHeight;          // Height of our bounce box
   int theWidth;           // Width of our bounce box
   int maxX;               // Maximum X co-ordinate of line end
   int minX;               // Minimum X co-ordinate of line end
   int maxY;               // Maximum Y co-ordinate of line end
   int minY;               // Minimum Y co-ordinate of line end
   int x1;                 // Current X co-ordinate of one end
   int y1;                 // Current Y co-ordinate of one end
   int x2;                 // Current X co-ordinate of other end
   int y2;                 // Current Y co-ordinate of other end
   int x1Dir;              // Current X1 axis step size and direction
   int y1Dir;              // Current Y1 axis step size and direction
   int x2Dir;              // Current X2 axis step size and direction
   int y2Dir;              // Current Y2 axis step size and direction
   Thread stickThread;     // Thread that bounces the stick

   /*****************************************************************
    *
    * Applet initialisation routine
    *
    *****************************************************************/
   public void init()
   {
      // Create a new random number object
      Random rand = new Random();

      // Get the size of the applet screen area we are to work in
      theHeight =  size().height;
      theWidth  =  size().width;

      // Initialise our bounce points
      minX  = 0;
      maxX  = theWidth;
      minY  = 0;
      maxY  = theHeight;

      // Set up the initial line to have random start and end points
      x1 = Math.abs( rand.nextInt() ) % maxX;
      y1 = Math.abs( rand.nextInt() ) % maxY;
      x2 = Math.abs( rand.nextInt() ) % maxX;
      y2 = Math.abs( rand.nextInt() ) % maxY;

      // Set up our directions a bit randomly too
      x1Dir = Math.abs( rand.nextInt() ) % 5 + 1;
      y1Dir = Math.abs( rand.nextInt() ) % 5 + 1;
      x2Dir = Math.abs( rand.nextInt() ) % 5 + 1;
      y2Dir = Math.abs( rand.nextInt() ) % 5 + 1;

      // Set the width and height, set background to BLACK
      // and make sure it is visible.
      setBackground( Color.black );
      show( );
   }

   /*****************************************************************
    *
    * Called each time the browser displays the page.
    * If we haven't got a running thread, then create one,
    * and call start it up.
    *
    *****************************************************************/
   public void start()
   {
      if( stickThread == null )
      {
        stickThread = new Thread( this );
        stickThread.start();
      }
   }

   /*****************************************************************
    *
    * Called each time the browser leaves the page.
    * Stop and junk any thread that may be running.
    *
    *****************************************************************/
   public void stop()
   {
      if( stickThread != null)
      {
         stickThread.stop();
         stickThread = null;
      }
   }

   /*****************************************************************
    *
    * The main thread of execution.
    * While we have a running thread, update the display,
    * sleep for the specified time and go round again.
    *
    *****************************************************************/
   public void run()
   {
      // This thread keeps running until it is destroyed
      while( true )
      {
         // Force a display update
         repaint();

         // The sleep may fail
         try
         {
            // Nap for a while
            Thread.sleep( 10 );
         }
         catch (InterruptedException e)
         {
            // Log any problem on the Java console
            System.out.println( "Exception:  " + e );
         }
      }
   }

   /*****************************************************************
    *
    * Display update method. We overwrite the existing line in
    * black, check if we need to bounce the either endpoint, move
    * the endpoints and draw a new line in white.
    *
    * @param g     Graphics context we are to draw the text in
    *
    *****************************************************************/
   public void update( Graphics g )
   {
      // Overwrite the old line in the background colour
      g.setColor( Color.black );
      g.drawLine( x1, y1, x2, y2 );

      // See if we have reached an edge in either direction
      if( ( x1 >= maxX ) || ( x1 <= minX ) ) x1Dir = -x1Dir;
      if( ( y1 >= maxY ) || ( y1 <= minY ) ) y1Dir = -y1Dir;
      if( ( x2 >= maxX ) || ( x2 <= minX ) ) x2Dir = -x2Dir;
      if( ( y2 >= maxY ) || ( y2 <= minY ) ) y2Dir = -y2Dir;

      // Move along the two co-ordinates in the current direction
      x1 += x1Dir;
      y1 += y1Dir;
      x2 += x2Dir;
      y2 += y2Dir;

      // Draw the new line in WHITE
      g.setColor( Color.white );
      g.drawLine( x1, y1, x2, y2 );
   }
}

