/**
 * @version spuren.java, Wed Jan 10 22:57:09 CET 1999
 * @author  Copyright (c) 1991 - 99 by
 * @author  Thomas Feuerstein <bik@ast5.uibk.ac.at>, Idee
 * @author  Armin Hanika, erste DOS Version 1991
 * @author  Peter Chiocchetti <girbal@super.tacheles.de>, Portierung 99-01-03
 *
 * Das Spuren Applet verschiebt in Streifen angeordnete Rechtecke in
 * unterschiedlichen Geschwindigkeiten von links nach rechts.
 * Zwei Knpfe und ein Zufallsgenerator erzeugen verschiedene Werte, die
 * Spuren an ein Bild von Malewitsch oder an den Barcode auf einer
 * Verpackung erinnern lassen.
 * 
 * @param Name       Default    Legal values     Meaning
 * @param ---------- ---------  ---------------  ----------------------------
 * @param sleepTime  1000       1 to 5000        Time in milliseconds between
 * @param                                        movements of the pattern
 */

import java.awt.*;
import java.applet.*;
import java.util.Random;

public class spuren extends Applet
{
  int sleepTime; // applet <param>'s, described above
  spurenCanvas manga = new spurenCanvas();

  private Integer getIntParam(String paramName)
    { // retrieve an integer <param>; return null if the specified
      // param is not present or if the value is illegal
      String param = getParameter(paramName);
      if (param == null)
	return null;
      int i;
      try {
	i = Integer.parseInt(param);
      }
      catch (NumberFormatException e) {
	return null;
      }
      return new Integer(i);
    }

  public void init()
    {
      Integer temp;
      if ((temp = getIntParam("sleepTime")) != null )
	sleepTime = temp.intValue();
      if (sleepTime < 1 || sleepTime > 5000)
	sleepTime = 250;

      setBackground(Color.lightGray);
      setLayout(new BorderLayout());

      Panel title = new Panel();
      title.setLayout (new FlowLayout(FlowLayout.LEFT,0,5));
      title.add(new Label("Spuren"));
      title.add(new Label(" von "));
      title.add(new Button("Malewitsch"));
      title.add(new Label(" zu "));
      title.add(new Button("Barcode"));
      add ("North", title);

      add ("Center", manga);
      manga.setSleep(sleepTime);
    }

  public void start()
    {
      manga.start();
    }

  public void stop()
    {
      manga.stop();
    }

  public void destroy()
    {
      remove(manga);
    }

  public boolean action(Event e, Object arg)
    {
      if (e.target instanceof Button) {
	if (!manga.stopped()) {
	  manga.stop();
	  manga.stopped(true);
	}
	if (arg.equals("Malewitsch")) {
	  manga.setCols(2);
	  manga.setRows(2);
	}
	else if (arg.equals("Barcode")) {
	  manga.setCols(1);
	  manga.setRows(66);
	}
	manga.stopped(false);
	manga.start();
      }
      return true;
    }
}

class spurenCanvas extends Canvas
  implements Runnable
{
  Thread runner; // thread to produce the animation
  static final Random rand = new Random();
  Image buffer       = null;  // an off-screen canvas
  boolean stopped    = false; // toggled when user clicks on the applet.
  int sleepTime      = 250;
  int d[]            = new int[200];
  int i[]            = new int[200];
  boolean r[]        = new boolean[200];
  int numCols        = (Math.abs(rand.nextInt() % 33) + 1);
  int numRows        = (Math.abs(rand.nextInt() % 66) + 2);
  int maxPix, cellWidth, cellHeight, j, w, h;

  public void setSleep(int i)
    {
      sleepTime = i;
    }

  public boolean stopped()
    {
      return stopped;
    }

  public void stopped(boolean b)
    {
      stopped = b;
    }

  public void setCols(int i)
    {
      numCols = i;
    }

  public void setRows(int i)
    {
      numRows = i;
    }

  public void start()
    {
      if (runner == null && !stopped) {
	runner = new Thread(this);
	runner.start();
      }
    }

  public void stop()
    {
      if (runner != null) {
	runner.stop();
	runner = null;
      }
    }

  public boolean mouseDown(Event evt, int x, int y) {
    stopped = !stopped;
    if (stopped)
      stop();
    else {
      numCols = Math.abs(rand.nextInt() % 33) + 2;
      numRows = Math.abs(rand.nextInt() % 66) + 2;
      start();
    }
    return true;
  }

  private synchronized void doMove(Graphics g)
    { // copy buffer to spurenCanvas
      g.drawImage(buffer,0,0,this);
    }

  public void paint(Graphics g)
    { // paint method just copies canvas to applet
      if (buffer != null)
	doMove(g);
    }

  public void update(Graphics g)
    { // replace standard update method
      // so it doesn't erase the screen
      paint(g);
    }

  private synchronized void move (Graphics g,
				  int numRows, int numCols,
				  int maxPix, int cellWidth,
				  int cellHeight, int d[],
				  int i[], boolean r[])
    {
      int j, k, x, y, v;

      for (j = 0; j < numRows; ++j) {
	if (i[j] + d[j] < cellWidth)
	  i[j] += d[j];
	else {
	  i[j] = 0;
	  d[j] = (Math.abs(rand.nextInt() % maxPix)) + 1;
	}
	y = j * cellHeight;
	x = 0;
	for (k = 0; k <= numCols; ++k) {
	  if ((k % 2) == (r[j] == true ? 0 : 1))
	    g.setColor(Color.white);
	  else
	    g.setColor(Color.black);
	  switch(k) {
	  case 0:
	    x = 0;
	    v = i[j];
	    break;
	  case 1:
	    x += i[j];
	    v = cellWidth;
	    break;
	  default:
	    x += cellWidth;
	    if (k == numCols)
	      v = cellWidth -i[j];
	    else
	      v = cellWidth;
	  }
	  g.fillRect(x, y, v, cellHeight);
	}
	if (i[j] + d[j] >= cellWidth)
	  r[j] = !r[j];
      }
    }

  public void run()
    { // run method for animation thread
      if (buffer == null) {
	w = size().width;          // get the width and height
	                           // of the canvas
	h = size().height;         // (Applet is not
	                           // effectively resizable)
	buffer = createImage(w,h); // create an off screen canvas
	                           // of the same size
      }
      cellWidth  = w / numCols;
      cellHeight = h / numRows;
      numCols    = w / cellWidth;
      numRows    = h / cellHeight;
      maxPix     = Math.abs(rand.nextInt() % (Math.min(cellWidth, 15))) + 1;
      for (j = 0; j < numRows; ++j) {
	i[j] = 0;
	d[j] = (Math.abs(rand.nextInt() % maxPix)) + 1;
	r[j] = (j % 2 == 0) ? true : false;
      }

      Graphics g = buffer.getGraphics(); // create and display the pattern
      g.setColor(Color.lightGray);
      g.fillRect(0,0,w,h);

      while (true) {
	g = buffer.getGraphics();
	move (g, numRows, numCols, maxPix,
	      cellWidth, cellHeight, d, i, r);
	g.dispose();
	repaint();
	try {
	  Thread.sleep(sleepTime);
	}
	catch (InterruptedException e) {
	}
      }
    }
}

