/*
Introduction to Java. A tutorial from A-SQUARE, Inc. January 2003
c 2000-2003 A-Square, Inc. Cambridge, MA

Source Code for Banner1.java
As always you get the sourcecode by selecting and copying any text
below into Banner1.java
 ---
Ans here is the HTML document to embed the Java Applet:

<applet code=Banner1.java 
    width=300  height=200>

*****/

/*
 * Banner1 applet  Version 2.0
 * 
 * Jan Aminoff , September 2000
 * c A-Square 1997-2000.
 *
 */

import java.awt.*;
import java.applet.Applet;

/**
 * This Applet demonstrates the main components of successful animations 
 * including double buffering and simple user/applet interaction. 
 * It also introduces some of the main elements of Java syntax.
 *
 * author Jan Aminoff/  c A-Square 1997
 * version 2.0, modified September 2000, for use at IEEE/A-Square 
 * Introduction to Java, tutorial.
 * 
 * This version should compile and run under JDK 1.0.2
 */

public class Banner1 extends Applet implements Runnable {
   ///////////////////////////////////////////////////////////////////////////
   // The Java coding conventions dictate that any Java class starts out by
   // declaring the public methods, that is the methods whereby the outside
   // world can use an instantiated class object.
   // 
   // The Banner1 class declares the following public methods and no public
   // variables: init, start, run, stop, mouseDown, and update.
   ///////////////////////////////////////////////////////////////////////////   
   /*
    * The init() method is prescribed by the Applet class, or more
    * precisely, the init() method here overrides a method in the
    * Applet class that Banner1 extends. In what is typical for applets this
    * method sets up the initial conditions from which the update or paint
    * methods can start the action rolling.
    */
    public void init() {
      // Set maxx and maxy to the size of the applet window given in the
      // applet tag,that is the html document initializing the applet.
      maxx = size().width;    
      maxy = size().height;
     /* The following is an example of exception handling, a real cool Java
      * thing. In this case we attempt to create an offscreen graphics 
      * resource. If this is not possible, perhaps because we are running
      * out of memory, the line that includes a call to the library method
      * will generate an out of memory exception. Below, the catch clause is 
      * executed for any exception causing the gc graphics variable to have
      * the value null.
      */
      try {                      
         // allocate an offscreen graphics
         imagebuffer = createImage(maxx, maxy);
         gc = imagebuffer.getGraphics();
         // clear it
         gc.setColor(Color.lightGray);
         gc.fillRect(0, 0, maxx, maxy );
         
      }
      catch (Exception e) { gc = null; }
      
      // The following gives initial values to position (x,y) and
      // speed (dx, dy) of the Logo 
      x = 50 ; 
      y = maxy/2 ;
      // Initial movement to NW
      dx = -1;       
      dy = -1;    
      
   }  

  /* Normally private variables would be placed at the end of the class
   * source. We are giving them here to allow them to be considered in the 
   * textual context where they are set initially.
   */
   private Graphics     gc;  // used for drawing
   private Image        imagebuffer; // Used for drawing when double buffering
   // The applet appears as a rectangle with upper left coordinates (0, 0)
   // and lower right coordinates (maxx, maxy),.
   private int maxx;         // The right edge of the applet
   private int maxy;         // The lower edge of the applet
   private int maxv =8;      // Max speed of logo
   private int x, y;         // Position of Logo
   private int  dx, dy;      // Speed of Logo
  
   // End of init and declarations of private variables initiated in init.
  

  /*
   * The following three public methods: start, stop and run deal with a thread
   * of execution. run() is prescribed by the Runnable Interface. The methods are 
   * useful to allow programs outside the Applet to control the animation.
   */
 
   public void start() {
      if (clock == null) {
         clock = new Thread(this, "Banner");
         clock.start();
      }
   }

  /*
   * The run method interupts execution for stime milliseconds between repaints.
   * This is a crude way to get the applet to execute frames at a rate which is
   * relatively independent of processor speed.
   */

   public void run() {
      while (clock != null) {
         try {
            clock.sleep(stime);       //wait for stime milliseconds.
         }
         catch (InterruptedException e) {}  //resume
         repaint();
      }
      clock = null;
   }
   
   public void stop() {
      if (clock != null) {
         clock.stop();
         clock = null;
      }
   }
   private Thread clock = null;  //A thread is a thread of execution

  /* If dtime is 1000 milliseconds then stime is about 25 milliseconds which
   * means there are about 40 frames in a second if the time to do the 
   * actual animation is ignored. This should give a smooth animation.
   */
   private int dtime=1000;       
   private int stime=dtime/40;

   // End of Runnable related methods and variables  
                                 

  /*
   * mouseDown, Library method called when the user presses the mouse.
   *
   * The mouseDown method is now depreciated and replaced with more general
   * but also more complex methods for event handling. However, we use the
   * older method to be compatible with older browsers. The Java virtual 
   * machine automatically invokes the mouseDown method when the user
   * presses the mouse button. In this case we are not intersted in
   * xd and yd, which would give the coordinates for the mouse click.
   */

   public boolean mouseDown(java.awt.Event evt, int xd, int yd) {
      if (move){
         dx1=dx;
         dx=0;
         dy1=dy;
         dy=0;
      }else{ 
         dx=dx1;
         dy=dy1;
      }  
      move=!move;  
      return true;
   }
   
   private boolean move=true; // This variable says that the logo is moving
   private int dx1, dy1;      // Placeholders for speed component when not moving

   // End of mouseDown method and related private variables

  /*
   * The update method is prescribed by the Applet.
   *
   * The update method is called periodically. It has two branches depending
   * on wether or not we were succesfull in securing us a buffer for double
   * buffering.
   * If the imagebuffer is null  we have to paint this applet directly
   * on the graphichs context g.
   */
   
   public void update(Graphics g)
   {
      
      if (imagebuffer != null) {
         paintBanner(gc);
         g.drawImage(imagebuffer, 0, 0, this);
      }
      else {
         g.clearRect(0, 0, maxx, maxy);
         paintBanner(g);
      }
   }

   ///////////////////////////////////////////////////////////////////////////
   // Following the declarations of public methods and variables, the Java 
   // coding conventions require the positioning of private methods and 
   // variables. The Banner1 class has the following private methods:
   // paintBanner, drawAsquare, and some private methods RND, ABS and 
   // printString which may be considered utility methods.
   ///////////////////////////////////////////////////////////////////////////

  /*
   * The paintBanner method paints the whole rectangle (0, 0, maxx, maxy)
   * using the graphics context g. It starts by painting it all light gray.
   * It then draws the Logo at x,y and draws the three strings s1, s2 and s3.
   * It then moves the Logo and does the right thing if the center of the 
   * Logo should happen to hit any edge.
   */ 

   private void paintBanner(Graphics g){
       // This method paints the whole rectangle (0,0, maxx, maxy) starting
       // with a blanked out rectangle:
   	  g.setColor(Color.lightGray);   
      g.fillRect(0, 0, maxx, maxy);    // Paint the screen light gray
      drawAsquare(g, x, y, 35);        // Draw A-Square logo
      printString(g, s1, maxx,45  ,24);// Draw the three strings
      printString(g, s2, maxx,70  ,12);
      printString(g, s3,maxx,maxy-5,9);
      //Move center of A-Square logo
      x += dx;
      y += dy;    
      
      // Check to see if the point  hit the edge
      // Check to see if the point  hit the edge in the x-direction    
      if (x < 0 || x > maxx )    {     
         dx = (x < 0)? ABS(dx):-ABS(dx);    //Point alwayas moves toward center
         x += 2*dx;                       //Double back
         do dy = maxv/2-RND(maxv); while (dy ==0); //change speed in y-direction
      }
      // Check to see if the point  hit the edge in the y-direction 
      if (y < 0 || y > maxy ){
         dy =  (y < 0)? ABS(dy):-ABS(dy);   //Point alwayas moves toward center
         y += 2*dy;                       //Double back
         do dx = maxv/2-RND(maxv); while (dx ==0); //change speed in x-direction
      }
   }
   
   private String s1="Welcome to Introductory Java";
   private String s2="Jan Aminoff, Instructor";
   private String s3="Also inventor of RARTa, Random Art for the Internet";

   // End of paintBanner and declarations of strings
   
   /*
    * drawAsquare
    * Draws A-Square Logo with center at x,y and size s
    * A fairly staightforward use of the drawing of rectangles
    * in different colors. I have selected a Logo for A-Square, easy to draw!
    */
   
   private void drawAsquare(Graphics g, int x,int y,int s)
   {
      int w=s;
      int h=(int) (1.2*s);       
      g.setColor(Color.darkGray);
      g.fillRect(x-w,y-h,2*w,2*h);
      w=(int) (0.8*w);
      h=(int) (0.8*h);
      g.setColor(Color.yellow);
      g.fillRect(x-w,y-h,2*w,2*h);
      g.setColor(Color.red);
      g.fillRect(x-w,y-h,w,h);
      g.fillRect(x,y,w,h);
   }
   
   /* Standard methods
    *
    * The following three methods are standard methods used throughout Rart.
    * The first two break the Java convention of having method names that
    * consist of lowercase verb followed by capitalized noun.
    * Better names would have been genRandom and takeAbs. However, I have kept
    * these names in the Rart systems for historic reasons since they
    * emulate the QuickBasic methods of the same names from long long ago.
    *
    * They are declared static which means that they exist regardless of the
    * instantiation of any Banner1 object.
    */

   // RND generates any of the integers in the interval 0 to max - 1.
   private static int RND(int max){
      return (int)(java.lang.Math.random() * max);
   }

   // ABS(x) returns the absolute value of the integer x
   private static int ABS(int x){
      return ((x>0)? x: -x);
   }

   // The following prints the String st using the color blue and the font 
   // Helvetica at pointsize s according to coordinates x and y.
   // The text is centered between 0 and x 
   private static void printString(Graphics g, String st, int x, int y, int s){
      Font  Hel = new Font("Helvetica", Font.BOLD, s);
      g.setFont(Hel);
      FontMetrics fm = g.getFontMetrics(Hel);
      int cx=fm.stringWidth(st);
      cx=(x-cx)/2;      
      g.setColor(Color.blue);
      g.drawString( st, cx, y );
         
   }  // End of standard methods  
      
}	// End of Banner1

