
/* A small applet that shows mulitple copies of the string "Java!"
   in random colors, at random locations, and in a number of fonts
   on a black background.  Strings are added one-by-one, then removed
   in the reverse order.  Then the process is repeated.
   
   David Eck
   Deparment of Mathematics and Computer Science
   Hobart and William Smith Colleges
   Geneva, NY 14456
   eck@hws.edu
   
   August 2, 1996
*/

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

public class JavaPops extends Applet implements Runnable {

   final String str = "Java!";   // the string to display 
   final int maxJavas = 25;      // number of instances of the string to be displayed

   Image OSC = null;        // offscreen canvas for smooth animation
   Graphics OSC_g;          // graphics context for OSC
   int width,height;        // width and height of OSC (changes only if applet is stopped and restarted)
   Thread runner = null;    // thread for doing the animation
   int sleepTime = 100;     // wait time between frames
   
   Font[] fontList;         // various fonts to be used for displaying the string  (set up in init())
   FontMetrics[] fm;        // FontMetrics for each font in fontList
   
   int[] x, y;              // (x[i],y[i]) is position of i-th instance of string
   int[] font;              // font[i] is index in fontList[] of i-th instance of string
   Color[] color;           // color[i] is color used for i-th instance
   int javaCt = 0;          // number of instances of string currently shown
   boolean ascending = true;// are strings currently being added? (or removed?)
   
   
   public void init() {
   
      x = new int[maxJavas];
      y = new int[maxJavas];
      font = new int[maxJavas];
      color = new Color[maxJavas];
      
      fontList = new Font[5];   // create fonts for displaying the string
      fontList[0] = new Font("TimesRoman",Font.BOLD,24);
      fontList[1] = new Font("TimesRoman",Font.BOLD,42);
      fontList[2] = new Font("TimesRoman",Font.BOLD,60);
      fontList[3] = new Font("TimesRoman",Font.BOLD+Font.ITALIC,24);
      fontList[4] = new Font("TimesRoman",Font.BOLD+Font.ITALIC,42);
      
    /*  I had 18 different fonts, but my Sun workstation completely
        choked on more than 5 !!!!! (I had to stop netscape/appletviewer
        by telnetting from another machine !)
      fontList[5] = new Font("TimesRoman",Font.BOLD+Font.ITALIC,60);
      fontList[6] = new Font("Helvetica",Font.BOLD,24);
      fontList[7] = new Font("Helvetica",Font.BOLD,42);
      fontList[8] = new Font("Helvetica",Font.BOLD,60);
      fontList[9] = new Font("Helvetica",Font.BOLD+Font.ITALIC,24);
      fontList[10] = new Font("Helvetica",Font.BOLD+Font.ITALIC,42);
      fontList[11] = new Font("Helvetica",Font.BOLD+Font.ITALIC,60);
      fontList[12] = new Font("Courier",Font.BOLD,24);
      fontList[13] = new Font("Courier",Font.BOLD,42);
      fontList[14] = new Font("Courier",Font.BOLD,60);
      fontList[15] = new Font("Courier",Font.BOLD+Font.ITALIC,24);
      fontList[16] = new Font("Courier",Font.BOLD+Font.ITALIC,42);
      fontList[17] = new Font("Courier",Font.BOLD+Font.ITALIC,60); 
   */
      
      fm = new FontMetrics[fontList.length];
      for (int i=0; i<fontList.length; i++) {
         fm[i] = getFontMetrics(fontList[i]);
      }
          
   }

   public void start() {
      if (OSC == null) {  // set up offscreen canvas and variables for keeping track of drawing
         width = size().width;
         height = size().height;
         OSC = createImage(width,height);
         OSC_g = OSC.getGraphics();
         javaCt = 0;
         ascending = true;
         OSC_g.setColor(Color.black);
         OSC_g.fillRect(0,0,width,height);
      }
      if (runner == null) {
         runner = new Thread(this);
         runner.start();
      }
   }
   
   public void stop() {
      if (runner != null) {
         runner.stop();
         runner = null;
      }
      OSC = null;
      OSC_g = null;
   }

    public void paint(Graphics g) {  // just copy the offscreen canvas to the screen
       if (OSC != null)
          g.drawImage(OSC,0,0,this);
   }
   
   public void update(Graphics g) {   // override this to avoid erasing before painting
      paint(g);
   }
   
   public void run() {
     while (true) {
        try { Thread.sleep(sleepTime); }  
        catch (InterruptedException e) { }
        if (OSC != null) {
          if (javaCt < 0) {  // check for reversal of ascending/descending mode
             javaCt = 0;
             ascending = true;
          }
          else if (javaCt >= maxJavas) {
             javaCt = maxJavas - 1;
             ascending = false;
          }
          if (ascending) {  // add an instance of the string with random color, location, font
             int fontNum = (int)(fontList.length * Math.random());
             OSC_g.setFont(fontList[fontNum]);
             int strlen = fm[fontNum].stringWidth(str);
             int strasc = fm[fontNum].getAscent();
             int minx = -(strlen / 2);
             int miny = strasc / 2;
             int maxx = width + minx;
             int maxy = height + miny;
             int basex = (int)(minx + Math.random()*(maxx-minx));
             int basey = (int)(miny + Math.random()*(maxy-miny));
             Color c = new Color((float)Math.random(), (float)Math.random(), (float)Math.random());
             OSC_g.setColor(c);
             OSC_g.drawString(str,basex,basey);
             x[javaCt] = basex;  // record data about this string instance
             y[javaCt] = basey;
             font[javaCt] = fontNum;
             color[javaCt] = c;
             javaCt++;
          }
          else {  // remove a string (this is really too time-consuming!!!)
             OSC_g.setColor(Color.black);  // start with a black background
             OSC_g.fillRect(0,0,width,height);
             javaCt--;  // cut off highest-numbered string instance
             for (int i = 0; i<javaCt && OSC_g != null; i++) {  // redraw all the other string instances
                 OSC_g.setFont(fontList[font[i]]);
                 OSC_g.setColor(color[i]);
                 OSC_g.drawString(str,x[i],y[i]);
             }
          }
          repaint();
        }  // end of if 
      } // end of while
   }  // end of run()

}  // end of applet
