Previous <--> Next <==> All
-rw-r--r--   1 kinzler  www          3339 Apr 11  1996 ColorSeq.class
-rw-r--r--   1 kinzler  www          1199 Apr 11  1996 RectMaker.class
-rw-r--r--   1 kinzler  www          7535 Apr 11  1996 StackedRects.class
-rw-r--r--   1 kinzler  www         11999 May 29  1996 StackedRects.java
<applet code=StackedRects.class width=150 height=75>
Cannot run the StackedRects applet.
</applet>
Cannot run the StackedRects applet.
import java.applet.Applet;
import java.awt.*;
import java.net.*;
import java.util.StringTokenizer;

///////////////////////////////////////////////////////////////////////////////
// StackedRects // Declaration ////////////////////////////////////////////////

public class StackedRects extends Applet implements Runnable {

	final static int MINSLEEP = 25;
	int width  = 480, height = 280;	// 4x4 minimum
	String url = "http://www.cs.indiana.edu/hyplan/kinzler/fun/"
		   + "StackedRects/index.html";

	public String getAppletInfo() {
		return
"StackedRects - a continuous, random graphic of overlaying rectangles\n"
+ "Development version 15: append ColorSeq class\n"
+ "Steve Kinzler, kinzler@cs.indiana.edu, Nov 95/Mar 96\n" + url;
	}

	int	  nrects, pause;
	boolean   cover, center, grid, freeze;
	RectMaker outrect, inrect;

	int	  num = 1;
	boolean	  innum = false;
	Image	  image;
	Graphics  imageG;
	Thread	  kicker = null;

	String pinfo[][] = {
		{"nrects",   "# rects",  "starting rectangles [0]"},
		{"pause",    "ds",       "pause between rectangles [1]"},
		{"cover",    "boolean",  "overlap rectangles [false]"},
		{"center",   "boolean",  "center rectangles [false]"},
		{"grid",     "boolean",  "constrain to a grid [true]"},
		{"freeze",   "boolean",  "start applet suspended [false]"},
		{"outthick", "# pixels", "outer line thickness (5%)"},
		{"inthick",  "# pixels", "inner line thickness (5%)"},
		{"outdimen", "int",      "outer 3D height [0]"},
		{"indimen",  "int",      "inner 3D height [0]"}
	};

	public String[][] getParameterInfo() {
		return pinfo;
	}

// StackedRects // Initialization /////////////////////////////////////////////

	public void init() {
		Dimension d = size();
		if (d.width  >= 4) width  = d.width;
		if (d.height >= 4) height = d.height;
		resize(width, height);

		outrect = new RectMaker(getForeground());
		inrect  = new RectMaker(getBackground());
		setParams();

		image  = createImage(width, height);
		imageG = image.getGraphics();
		clear();
		stackRect(nrects);
	}

	void setParams() {
		String s = getParameter("NRECTS");
		nrects = (s != null) ? Math.abs(Integer.parseInt(s)) : 0;
		s = getParameter("PAUSE");
		pause  = (s != null) ? Math.abs(Integer.parseInt(s)) : 1;
		s = getParameter("COVER");
		cover  = (s != null) ? s.equals("true") : false;
		s = getParameter("CENTER");
		center = (s != null) ? s.equals("true") : false;
		s = getParameter("GRID");
		grid   = (s != null) ? s.equals("true") : true;
		s = getParameter("FREEZE");
		freeze = (s != null) ? s.equals("true") : false;

		setParams(outrect);
		setParams(inrect);
	}

	void setParams(RectMaker rect) {
		boolean out = (rect == outrect);
		String s    = getParameter((out) ? "OUTTHICK" : "INTHICK");
		setThick(rect, (s != null) ? Integer.parseInt(s)
					   : Math.min(width, height) / 20);
		s	    = getParameter((out) ? "OUTDIMEN" : "INDIMEN");
		rect.dimen  = (s != null) ? Integer.parseInt(s) : 0;
	}

	void setThick(RectMaker rect, int t) {
		RectMaker other = ((rect == outrect) ? inrect : outrect);
		int max = Math.min(width, height) / 2 - other.getThick();
		rect.setThick((t < max) ? t : max);
	}

	void addThick(RectMaker rect, int n) {
		setThick(rect, rect.getThick() + n);
	}

// StackedRects // Graphics ///////////////////////////////////////////////////

	public void update(Graphics g) {
		paint(g);
	}

	public synchronized void paint(Graphics g) {
		g.drawImage(image, 0, 0, this);
	}

	synchronized void clear() {
		imageG.setColor(getBackground());
		imageG.fillRect(0, 0, width, height);
	}

	void stackRect(int n) {
		for (int i = 0; i < n; i++) stackRect();
	}

	synchronized void stackRect() {
		int a, b, x, y;
		int t  = outrect.getThick();
		int tt = t + inrect.getThick();

		if (cover || center) {
			double maxa = width  / 2.0 - tt;
			double maxb = height / 2.0 - tt;
			a =		 (int) (Math.random() * maxa);
			b =		 (int) (Math.random() * maxb);
			x = width  - 1 - (int) (Math.random() * maxa);
			y = height - 1 - (int) (Math.random() * maxb);
			if (center) {
				x = width  - 1 - a;
				y = height - 1 - b;
			}
			if (grid) {
				a -= a % t; x += (width  - 1 - x) % t;
				b -= b % t; y += (height - 1 - y) % t;
			}
		} else {
			int maxa = width  - 2 * tt + 1;
			int maxb = height - 2 * tt + 1;
			a =		 (int) (Math.random() * maxa);
			b =		 (int) (Math.random() * maxb);
			x = width  - 1 - (int) (Math.random() * (maxa - a));
			y = height - 1 - (int) (Math.random() * (maxb - b));
			if (Math.random() >= 0.5) {
				int c = a, d = b;
				a = width - 1 - x; b = height - 1 - y;
				x = width - 1 - c; y = height - 1 - d;
			}
			if (grid) {
				a -= a % t; x -= (x + 1) % t;
				b -= b % t; y -= (y + 1) % t;
			}
		}

		outrect.paint(imageG, a,   b,   x,   y);
		inrect.paint( imageG, a+t, b+t, x-t, y-t);
	}

// StackedRects // Execution //////////////////////////////////////////////////

	public void start() {
		start(! freeze);
	}

	synchronized void start(boolean b) {
		if (kicker == null && b) {
			kicker = new Thread(this, this.getClass().getName());
			kicker.setPriority(Thread.MIN_PRIORITY);
			kicker.start();
		}
	}

	public void run() {
		while (kicker != null) {
			stackRect();
			repaint();
			try { kicker.sleep(MINSLEEP + pause * 100); }
			catch (InterruptedException e) { break; }
		}
	}

	void toggle() {
		if (kicker == null) { start(true); } else { stop(); }
	}

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

// StackedRects // Events /////////////////////////////////////////////////////

	public boolean mouseEnter(Event evt, int x, int y) {
		showStatus(url);
		return true;
	}

	public boolean mouseExit(Event evt, int x, int y) {
		showStatus(null);
		return true;
	}

	public boolean mouseUp(Event evt, int x, int y) {
		goHome();
		return true;
	}

	public void goHome() {
		if (url != null) {
			try { getAppletContext().showDocument(new URL(url)); }
			catch (MalformedURLException e) {
				url = null;
				showStatus("Ignoring Malformed URL");
			}
		}
	}

	public synchronized boolean keyDown(Event evt, int key) {
		if ('0' <= key && key <= '9') {
			num   = (innum) ? 10 * num + key - '0' : key - '0';
			innum = true;
			return true;
		}

		switch (key) {
		case 'h':	goHome();	    break;
		case 'i':	setParams();	    break;
		case 'I':	setParams(outrect); break;
		case '\011':	setParams(inrect);  break;
		case '!':	cover  = ! cover;   break;
		case '@':	center = ! center;  break;
		case '#':	grid   = ! grid;    break;
		case 'f':	freeze = ! freeze;  break;
		case 'n':	nrects = Math.max(0, nrects - num); break;
		case 'N':	nrects = nrects + num;		    break;
		case 'p':
		case '+':	pause  = Math.max(0, pause - num);  break;
		case 'P':
		case '-':	pause  = pause + num;		    break;
		case 't':	addThick(inrect,   num);
		case 'T':	addThick(outrect,  num); break;
		case '\024':	addThick(inrect,   num); break;
		case 'y':	addThick(inrect,  -num);
		case 'Y':	addThick(outrect, -num); break;
		case '\031':	addThick(inrect,  -num); break;
		case 'd':	inrect.dimen  += num;
		case 'D':	outrect.dimen += num; break;
		case '\004':	inrect.dimen  += num; break;
		case 'e':	inrect.dimen  -= num;
		case 'E':	outrect.dimen -= num; break;
		case '\005':	inrect.dimen  -= num; break;
		case 'c':	clear(); stackRect(nrects); repaint(); break;
		case 'C':	clear();		    repaint(); break;
		case '\f':				    repaint(); break;
		case ' ':		 stackRect(num);    repaint(); break;
		case '\r':
		default:	toggle();
		}

		num   = 1;
		innum = false;
		return true;
	}
}

///////////////////////////////////////////////////////////////////////////////
// RectMaker //////////////////////////////////////////////////////////////////

class RectMaker {
	private int thick = 1;
	int	    dimen = 0;
	Color	    color = null;

	RectMaker(Color c) {
		color = c;
	}

	RectMaker(int t, int d, Color c) {
		this(c);
		setThick(t);
		dimen = d;
	}

	int  getThick()      { return thick; }
	void setThick(int t) { thick = Math.max(1, t); }

	void paint(Graphics g, int a, int b, int x, int y) {
		int t = thick, w = x - a + 1, h = y - b + 1;

		if (color != null) g.setColor(color);
		g.fillRect(a,     b,     w, t);
		g.fillRect(a,     y-t+1, w, t);
		g.fillRect(a,     b,     t, h);
		g.fillRect(x-t+1, b,     t, h);

		boolean up = (dimen > 0);
		int     n  = Math.min(Math.abs(dimen), thick / 2);
		for (int i = 0, j = 0; i < n; i++, j += 2) {
		    g.draw3DRect(a+i,     b+i,     w-1-j,     h-1-j,      up);
		    g.draw3DRect(a+t-1-i, b+t-1-i, w-t-t+1+j, h-t-t+1+j, !up);
		}
	}
}

///////////////////////////////////////////////////////////////////////////////
// ColorSeq // Construction ///////////////////////////////////////////////////

class ColorSeq {
	Color colors[], fg, bg, dflt, random;
	private protected int p;

	public ColorSeq() {
		this(null, null, null, null, null);
	}

	public ColorSeq(String s) {
		this(   s, null, null, null, null);
	}

	public ColorSeq(String s, Color f, Color b) {
		this(   s,    f,    b, null, null);
	}

	public ColorSeq(String s, Color f, Color b, Color d, Color r) {
		fg     = (f == null) ? Color.black   : f;
		bg     = (b == null) ? Color.white   : b;
		dflt   = (d == null) ? fg	     : d;
		random = (r == null) ? randomColor() : r;

		if (s == null) {
			colors = new Color[1];
			colors[p = 0] = dflt;
		} else {
			StringTokenizer st = new StringTokenizer(s);
			colors = new Color[st.countTokens()];
			p      = -1;
			while (st.hasMoreTokens())
				colors[++p] = parseColor(st.nextToken());
		}
	}

// ColorSeq // Use ////////////////////////////////////////////////////////////

	public synchronized void reset() {
		p = colors.length - 1;
	}

	public Color currColor() {
		return((colors[p] == null) ? randomColor() : colors[p]);
	}

	public synchronized Color nextColor() {
		p = (p + 1) % colors.length;
		return currColor();
	}

	public synchronized Color prevColor() {
		p = (p > 0) ? p - 1 : (p == 0) ? colors.length - 1 : p;
		return currColor();
	}

	public String toString() {
		StringBuffer buf = new StringBuffer();
		buf.append("ColorSeq{");
		for (int i = 0; i < colors.length; i++) {
			if (i == p) buf.append("^");
			buf.append((colors[i] == null) ? "null"
						       : colors[i].toString());
			if (i < colors.length - 1) buf.append(", ");
		}
		buf.append("}");
		return buf.toString();
	}

// ColorSeq // Utilities //////////////////////////////////////////////////////

	public Color parseColor(String s) {
		if      (s.equals("fg"))        return fg;
		else if (s.equals("bg"))        return bg;
		else if (s.equals("default"))   return dflt;
		else if (s.equals("random"))    return random;
		else if (s.equals("Random"))    return randomColor();
		else if (s.equals("RANDOM"))    return null;
		else if (s.equals("black"))     return Color.black;
		else if (s.equals("blue"))      return Color.blue;
		else if (s.equals("cyan"))      return Color.cyan;
		else if (s.equals("darkGray"))  return Color.darkGray;
		else if (s.equals("gray"))      return Color.gray;
		else if (s.equals("green"))     return Color.green;
		else if (s.equals("lightGray")) return Color.lightGray;
		else if (s.equals("magenta"))   return Color.magenta;
		else if (s.equals("orange"))    return Color.orange;
		else if (s.equals("pink"))      return Color.pink;
		else if (s.equals("red"))       return Color.red;
		else if (s.equals("white"))     return Color.white;
		else if (s.equals("yellow"))    return Color.yellow;
		return new Color(parseTaggedInt(s));
	}

	public static Color randomColor() {
		return new Color((int) (Math.random() * 256),
				 (int) (Math.random() * 256),
				 (int) (Math.random() * 256));
	}

	public static int parseTaggedInt(String s)
	    throws NumberFormatException {
		if (s.startsWith("0x"))
			return Integer.parseInt(s.substring(2), 16);
		else if (s.startsWith("#"))
			return Integer.parseInt(s.substring(1), 16);
		else if (s.startsWith("0") && s.length() > 1)
			return Integer.parseInt(s.substring(1), 8);
		return Integer.parseInt(s);
	}
}