/** * Light is a JavaBean that displays a status light (it can blink, if *ænecessary).  Adapted from Mastering Java Beans. * * Copyright &copy; 1996-1998 Martin Minow. All Rights Reserved.<p> * * Permission to use, copy, modify, and redistribute this software and its * documentation for personal, non-commercial use is hereby granted provided that * this copyright notice and appropriate documentation appears in all copies. This * software may not be distributed for fee or as part of commercial, "shareware," * and/or not-for-profit endevors including, but not limited to, CD-ROM collections, * online databases, and subscription services without specific license.<p> * * @author <a href="mailto:minow@apple.com">Martin Minow</a> * @version 1.0 * Set tabs every 4 characters. */import java.awt.*;import java.awt.event.*;import java.beans.*;public class Light extends java.awt.Canvas		implements java.io.Serializable,					ActionListener,					Runnable{	protected Color				lightColor;	protected Color				lightOnColor;	protected Color				lightOffColor;	protected int				pulseTimeMSec;		/* Zero means no blink	*/	protected boolean			lightOn;	protected boolean			showCounter;	protected int				counter;	protected Thread			runner;	protected ActionListener	actionListeners;		public static final int		defaultPulseTimeMSec	= 800;		/*	 * Constructors	 */	public Light()	{		this(Color.green);	}	public Light(			Color			lightColor		)	{		this(lightColor, false, defaultPulseTimeMSec);	}	public Light(			Color			lightColor,			boolean			showCounter		)	{		this(lightColor, showCounter, defaultPulseTimeMSec);	}	public Light(			Color			lightColor,			int				pulseTimeMSec		)	{		this(lightColor, false, pulseTimeMSec);	}	public Light(			Color			lightColor,			boolean			showCounter,			int				pulseTimeMSec		)	{		this.pulseTimeMSec	= pulseTimeMSec;		this.lightOn		= false;		this.showCounter	= showCounter;		actionListeners		= null;		setLightColor(lightColor);		resetCounter();	}	/*	 * Implement the runnable interface	 */	public void run()	{		try {			Thread.sleep(pulseTimeMSec);		}		catch (InterruptedException e) { };		setLightOn(false);		runner = null;	/* Kill the thread	*/	}	/*	 * Manage the lightOn property	 */	public void setLightOn(			boolean			value		)	{		if (showCounter && value) {			++counter;		}		lightOn = value;		repaint();		/*		 * If the light is now on and it's an "auto-off" light,		 * start a timer to turn it off after the pulse time.		 */		if (lightOn && pulseTimeMSec > 0 && runner == null) {			runner = new Thread(this);			runner.setName("Light");			runner.start();		}	}	public boolean isLightOn()	{		return (lightOn);	}	/*	 * Manage the CounterOn property.	 */	public void setShowCounter(			boolean			value		)	{		showCounter	= value;	}	public boolean isShowCounter()	{		return (showCounter);	}	/*	 * Mange the LightColor property	 */	public void setLightColor(			Color			value		)	{		lightColor		= value;		lightOnColor	= lightColor.brighter();		lightOffColor	= lightColor.darker().darker();		repaint();	}	public Color getLightColor()	{		return (lightColor);	}	/*	 * Manage the PulseTime property.	 */	public void setPulseTime(			int				value		)	{		this.pulseTimeMSec	= value;	}	public int getPulseTime()	{		return (pulseTimeMSec);	}	/*	 * Manage the Count property (This version does not range-limit	 * the counter value).	 */	public void setCounter(			int				value		)	{		counter = value;	}	public int getCounter()	{		return (counter);	}	public void resetCounter()	{		counter = 0;	}	/*	 * Light is an ActionListener. When it receives an ActionEvent,	 * the light comes on, and the event is passed through to	 * other listeners, so that the light can act as a probe for	 * unicast action sources as wel as multicast.	 */	public void actionPerformed(			ActionEvent		event		)	{		setLightOn(true);		if (actionListeners != null) {			actionListeners.actionPerformed(event);		}	}	/*	 * Manage the ActionListener event chain.	 */	public void removeActionListener(			ActionListener	listener		)	{		actionListeners = AWTEventMulticaster.add(actionListeners, listener);	}	public void addActionListener(			ActionListener	listener		)	{		actionListeners = AWTEventMulticaster.remove(actionListeners, listener);	}	/*	 * Draw the light	 */	public void paint(			Graphics		g		)	{		Dimension size		= getSize();		int		width		= size.width;		int		height		= size.height;		if (lightOn) {			g.setColor(lightOnColor);			g.fillOval(2, 2, width - 5, height - 5);		}		else {			g.setColor(lightOffColor);			g.fillOval(3, 3, width - 7, height - 7);		}		/*		 * Add a rectangular outline		 */		g.setColor(Color.gray);		g.drawRect(0, 0, width - 1, height - 1);		/*		 * If the event counter is enabled, draw that, too.		 */		if (showCounter) {			g.setColor((lightOn) ? Color.black : Color.white);			String text		= String.valueOf(counter % 100);			FontMetrics fm	= g.getFontMetrics();			g.drawString(					text,					(width - fm.stringWidth(text)) / 2,					(height / 2) + fm.getDescent()				);		}	}	public Dimension preferredSize()	{		return (new Dimension(25, 25));	}	public Dimension getPreferredSize()	{		return (preferredSize());	}}