/*
 * PedestrianLight.java  97/10/20
 * Copyright (c) 1997, B. F. Caviness
 *
 * This software may be copied/modified for any non-commercial educational
 * use.  It is found in the directory
 * $CLASSHOME/exer-solutions/tlApplet/withPedLight/synchronized/
 */

/**
 * This class provides a canvas for a pedestrian light that is designed
 * to be used in a coordinated fashion with a traffic light.  The
 * pedestrian light class implements the Runnable interface and hence
 * provides its own run method that displays and flashes the pedestrian
 * light when so signaled from the associated traffic light.
 */

import java.awt.*;

public class PedestrianLight extends Canvas implements Runnable{

   /************************
    * Class variables
    ************************/  
 static Font messageFont = new Font("Serif", Font.BOLD, 24);
 static int fontAscent,
            fontDescent;
 static                         // Initialize class variables
 {
  FontMetrics f = Toolkit.getDefaultToolkit().getFontMetrics(messageFont);
  fontAscent = f.getAscent();
  fontDescent = f.getDescent();
 }
/*********************************************
  * Instance variables
  ********************************************/
 private String message;	// Variables should be private so that
 private int messageWidth;	// they can be accessed only through
 private Color msgColor;	// synchronized getters and setters.
 private boolean flashing;
 private boolean lightOn;	// Set to true if light is to be displayed.
 
/********************************************
 * Constructors
 ********************************************/
 
 public PedestrianLight( String s ) {
    System.out.println("Entering PedestrianLight constructor");
    setMessage( s );
    msgColor = Color.black;	// Set default color and flaher off
    flashing = false;
    lightOn = true;		// By default turn light on
 }

 public PedestrianLight( String s, Color c, boolean flasherOn ){
     setMessage( s );
     msgColor = c;
     flashing = flasherOn;
    lightOn = true;		// By default turn light on
 }

/*******************************************
 * Instance methods
 *******************************************/
 
 public synchronized void setMessage( String msg )
 {
     message = msg;
     FontMetrics f = getFontMetrics(messageFont);
     messageWidth = f.stringWidth(message);
     repaint();
 }

 public synchronized void setMessage( String msg,boolean flasherOn ){
     message = msg;
     FontMetrics f = getFontMetrics(messageFont);
     messageWidth = f.stringWidth(message);
     flashing = flasherOn;
     repaint();
 }

 public synchronized void setMessage( String msg, Color c, boolean flasherOn ){
     message = msg;
     FontMetrics f = getFontMetrics(messageFont);
     messageWidth = f.stringWidth(message);
     msgColor = c;
     flashing = flasherOn;
     repaint();
 }

 public synchronized String getMessage(){
     return message;
 }

 public synchronized Color getColor(){
     return msgColor;
 }

 public synchronized void setFlashing( boolean flashing ){
     this.flashing = flashing;
 }

 public synchronized boolean isFlashing(){
     return flashing;
 }
 
/*******************************************/

 public void paint(Graphics g) {
   System.out.println("Painting pedestrian light again");
   Dimension d = getSize();
   g.drawRect(0,0,d.width-1,d.height-1);
   if ( lightOn ){
       g.setFont(messageFont);
       Point p = new Point( (d.width - messageWidth)/2, 
                            (d.height + fontAscent - fontDescent)/2);
       Color saveColor = g.getColor();	// Save current foreground color
       g.setColor( getColor() );	// Get message color
       g.drawString(message, p.x, p.y);
       g.setColor( saveColor );		// Restore foreground color
   }
 }

/*******************************************/

 public void run(){
     System.out.println( "Entering PedestrianLight.run()" );
     while( true ){
         while ( isFlashing() ){
             lightOn = false;		// Turn off message
             repaint();
             try{
                 Thread.sleep( 200 );
             }
             catch( InterruptedException e )
             {}
             lightOn = true;		// Turn on message
             repaint();			// How to insure that light always
             try{			// gets turned back on?
                 Thread.sleep( 200 );
             }
             catch( InterruptedException e )
             {}
         }
         if ( !lightOn ){
             lightOn = true;		// Help ensure that light is on
             repaint();			// once flashing is turned off
         }
         try{
             Thread.sleep( 200 );	// Relinquish control to tl thread
         }				// Is there a better way to do this?
         catch( InterruptedException e )
         {}
     }
 }
 
/*******************************************/

 public Dimension getMinimumSize() {return new Dimension(50, 15);}
 
 public Dimension getPreferredSize() {return new Dimension(200, 50);}
}
