/*
 *  CellEdge.java
 *  Author: Chun-Chung Chen
 *  Date: 2001-12-09
 *
 */
import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class CellEdge
	extends Applet
	implements Runnable,
		   MouseListener
{
	Thread th;
	int my_w;
	int my_h;
	Image im = null;
	int anchor;
	Image bim = null;
	int banchor;
	int bh = 10;
	int shift;
	boolean cell[];
	int size;
	double p = 0.6347;
	boolean suspend;

	int acc[];
	double acn;
	double amx;
	double xscale;
	double tscale;

	double xshift;

	public void init()
	{
		Thread.currentThread().setPriority(Thread.MIN_PRIORITY);
		suspend = false;
		addMouseListener(this);
	}

	public void destroy()
	{
		removeMouseListener(this);
	}

	public void initcell()
	{
		my_w = getSize().width;
		my_h = getSize().height;
		size = my_w;
		acc = new int[my_w];
		xscale = 5;
		tscale = 5;
		acn = 0;
		amx = xscale * tscale;
		size = (int)(my_w * xscale);
		cell = new boolean[size];
		cell[0] = true;
		im = createImage(my_w, my_h);
		bim = createImage(my_w, bh);
		im.getGraphics().clearRect(0, 0, my_w, my_h);
		bim.getGraphics().clearRect(0, 0, my_w, my_h);
		anchor = 0;
		banchor = 0;
		shift = 0;
		xshift = 0;
	}

	public void paint(Graphics g)
	{
		if (im == null) initcell();
		g.drawImage(im, 0, 0, null);
	}

	public void start()
	{
		th = new Thread(this);
		th.start();
	}

	public synchronized void stop()
	{
		th = null;
		if (suspend) {
			suspend = false;
			notify();
		}
	}

	public void roll()
	{
		for (int i = size - 1; i > 0; i --)
			cell[i] = cell[i] && Math.random() < p || cell[i - 1] && Math.random() < p;
		if (xscale >= 1) for (int i = 0; i < size && (acn + i) / xscale < my_w; i ++) {
			if (cell[i]) acc[(int)((acn + i) / xscale)] ++;
		} else for (int i = 0; i < my_w && i * xscale < size; i ++) {
			if (cell[(int)(i * xscale)]) acc[i] ++;
		}
	}

	public void run()
	{
		Thread me = Thread.currentThread();
		while (me == th) {
			try {
				Thread.sleep(10);
				synchronized(this) {
					while (suspend) wait();
				}
			} catch (InterruptedException e) {
			}

			if (im != null) {
				if (acn < tscale) {
					for (int i = 0; i < my_w; i ++) acc[i] = 0;
					while (acn < tscale) {
						roll();
						acn += 1.0;
					}
				}
				Graphics bg = bim.getGraphics();
				if (banchor >= bh) {
					Graphics g = im.getGraphics();
					if (shift > 0) {
						// int shift = anchor - my_h + bh;
						xshift += shift * tscale / xscale / 2;
						g.copyArea(0, shift, my_w - (int) xshift, my_h - shift, (int) xshift, - shift);
						shift = 0;
						xshift -= (int) xshift;
						// anchor -= shift;
					}
					g.drawImage(bim, 0, anchor, null);
					repaint();
					anchor += bh;
					if (anchor > my_h - bh) {
						shift = anchor - my_h + bh;
						anchor = my_h - bh;
					}
					banchor = 0;
					bg.clearRect(0, 0, my_w, bh);
				}
				int a = (int)((my_h - anchor - banchor - 1) * tscale / xscale / 2);
				for (int x = a; x < my_w; x ++) {
					int c = 255 - (int)(255 * acc[x - a] / amx);
					bg.setColor(new Color(c, c, c));
					bg.drawLine(x, banchor, x, banchor);
				}
				banchor ++;
				acn -= tscale;
			}
		}
	}

	public synchronized void mousePressed(MouseEvent e)
	{
		e.consume();
		suspend = ! suspend;
		if (! suspend) notify();
	}

	public void mouseReleased(MouseEvent e) {}
	public void mouseEntered(MouseEvent e) {}
	public void mouseExited(MouseEvent e) {}
	public void mouseClicked(MouseEvent e) {}
}
