import java.awt.*; import java.awt.event.*; import java.beans.*; import utilities.*; public class Light extends Canvas implements java.io.Serializable, ActionListener, Runnable { // the Light bean's properties protected Color lightColor, lightOnColor, lightOffColor; protected boolean lightOn, counterOn; protected int pulseTime; // 0 means stay ON until explicit OFF protected int counter; // its own timer thread to switch the light off protected Thread timer; // the chain of ActionListeners protected ActionListener actionListenerChain; //------------------------------------------------------------------- // Light Constructor //------------------------------------------------------------------- public Light() { this(Color.green); // default light color is green } public Light(Color lightColor) { this(lightColor, false, 800); // default light pulse time = N ms. } public Light(Color lightColor, boolean withCounter) { this(lightColor, withCounter, 800); } public Light(Color lightColor, int pulseTime) { this(lightColor, false, pulseTime); } public Light(Color lightColor, boolean withCounter, int pulseTime) { this.pulseTime = pulseTime; lightOn = false; // light is off counterOn = withCounter; // dont display its counter actionListenerChain = null; // no registered listeners yet setLightColor(lightColor); resetCounter(); // reset counter to 0 } //------------------------------------------------------------------- // Interface Runnable. Used to implement a "light off" timer //------------------------------------------------------------------- public void run() { MiscKit.delay(pulseTime); // wait a while setLightOn(false); // then switch light off timer = null; // "kill" thread } //------------------------------------------------------------------- // set()/get() for 'LightOn' property //------------------------------------------------------------------- public void setLightOn(boolean value) { if ( counterOn && value) { counter++; // keep track of # of light ON commands counter %= 100; // restrict to two digits } // set new light state and reflect graphically lightOn = value; repaint(); // if new state is ON if ( lightOn ) { // and light is auto-OFF type start a timer to switch // the light off if ( pulseTime != 0) { if ( timer == null ) { // (if no timer curr. running) timer = new Thread(this); timer.start(); } } } // endif light switched ON } public boolean isLightOn() { return lightOn; } //------------------------------------------------------------------- // set()/get() for 'CounterOn' property //------------------------------------------------------------------- public void setCounterOn(boolean value) { counterOn = value; } public boolean isCounterOn() { return counterOn; } //------------------------------------------------------------------- // set()/get() for 'LightColor' property //------------------------------------------------------------------- public void setLightColor(Color value) { lightColor = value; lightOnColor = lightColor.brighter(); lightOffColor = lightColor.darker().darker(); repaint(); } public Color getLightColor() { return lightColor; } //------------------------------------------------------------------- // set()/get() for 'PulseTime' property // a pulseTime of 0 means the light does not automatically switch OFF //------------------------------------------------------------------- public void setPulseTime(int value) { pulseTime = value; } public int getPulseTime() { return pulseTime; } //------------------------------------------------------------------- // set()/get() for 'Count' property //------------------------------------------------------------------- public void setCounter(int value) { counter = value % 100; // limit to 2 digits } public int getCounter() { return counter; } public void resetCounter() { counter = 0; } //------------------------------------------------------------------- // Light is an ActionListener: on action event -> light comes ON. // event is "passed through" to any interested listeners so Light can // act as probe for unicast Action sources as well as multicast. //------------------------------------------------------------------- public void actionPerformed(ActionEvent actionEvent) { setLightOn(true); // switch light on if (actionListenerChain != null) { actionListenerChain.actionPerformed(actionEvent); } } //------------------------------------------------------------------- // ActionListener management methods //------------------------------------------------------------------- public void addActionListener(ActionListener listener) { actionListenerChain = AWTEventMulticaster.add(actionListenerChain, listener); } public void removeActionListener(ActionListener listener) { actionListenerChain = AWTEventMulticaster.remove(actionListenerChain, listener); } //------------------------------------------------------------------- // paint() draws the light in its on or off state. //------------------------------------------------------------------- public void paint(Graphics g) { int width, height; Dimension size; size = getSize(); width = size.width; height = size.height; // render light's ON/OFF state if ( lightOn ) { g.setColor(lightOnColor); g.fillOval(2,2, width-5, height-5); // grow slightly when ON } 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); // additionally, display action event counter if enabled. if ( counterOn ) { g.setColor(lightOn ? Color.black : Color.white); String count = String.valueOf(counter); int x = width/2 - g.getFontMetrics().stringWidth(count)/2; g.drawString(count,x,height/2 + 5); } } //------------------------------------------------------------------- // Light Dimensions //------------------------------------------------------------------- public Dimension preferredSize() { return new Dimension(25,25); } public Dimension getpreferredSize() { return preferredSize(); } //------------------------------------------------------------------- // component self-test //------------------------------------------------------------------- public static void main (String[] args) { Frame window; Light[] lights = new Light[5]; window = new Frame("Light component test"); window.setLayout(new FlowLayout()); lights[0] = new Light(); lights[1] = new Light(Color.red); lights[2] = new Light(Color.blue,2000); lights[3] = new Light(Color.gray,0); // light stays on. lights[4] = new Light(); // counter test lights[4].setCounterOn(true); lights[4].setCounter(9); // start with 9 on the clock // add four lights to window for (int i=0; i < lights.length; i++) { window.add(lights[i]); } window.setSize(200,100); window.setVisible(true); MiscKit.delay(1000); // switch them all ON, one by one. for (int i=0; i < lights.length; i++) { lights[i].setLightOn(true); MiscKit.delay(3000); } // manually turn off light 3 lights[3].setLightOn(false); MiscKit.delay(10000); System.exit(0); } } // End of Class Light