
// An applet that says "Hello World" in a big bold font.  When the user
// clicks on a button labeled "Blink at Me!", the message starts cycling
// between red and another color.  If the user clicks on the button again, the 
// cycling stops.  Two other buttons can be used to select whether the
// second color besides red is green or blue.   This applet depends on the 
// class ColoredHelloWorldCanvas, which is defined in a separate file.

import java.awt.*;
import java.awt.event.*;
import java.applet.Applet;

public class BlinkingHelloWorld2 extends Applet implements ActionListener, Runnable {

   ColoredHelloWorldCanvas canvas;  // A canvas which actually displays the message
   
   Button blinkBttn;  // The control button.
   
   Thread runner;  // a thread that is responsible for cycling the message colors.
   
   private final static int GO = 0,           // Constants for use as value of status.
                            TERMINATE = 1;
                            
   private volatile int status = GO;  // This variable is used for communication between
                                      // the applet and the thread.  The value is set by
                                      // the applet to tell the thread what to do.  In
                                      // particlar, when the applet wants the thread
                                      // to terminate, it sets the value of status to
                                      // TERMINATE.
   
   boolean isRed = true;  // True if the message is currently displayed in red;
                          // false if it is displayed in green.
                          
   Color alternateColor = Color.green;  // Color that cycles with red.

   public void init() {

          // This routine is called by the system to initilize the applet.
          // It creates the canvas and lays out the applet to consist of a
          // bar of control buttons below the canvas.
          
       setBackground(Color.lightGray);

       canvas = new ColoredHelloWorldCanvas();

       Panel buttonBar = new Panel();  // a panel to hold the control buttons
       
       blinkBttn = new Button("Blink!");   // Create buttons and add them to the
       blinkBttn.addActionListener(this);  //    button bar.
       buttonBar.add(blinkBttn);
       
       Button redGreenBttn = new Button("Red/Green");
       redGreenBttn.addActionListener(this);           //    button bar.
       buttonBar.add(redGreenBttn);
       
       Button redBlueBttn = new Button("Red/Blue");
       redBlueBttn.addActionListener(this);       
       buttonBar.add(redBlueBttn);

       setLayout(new BorderLayout(3,3));  // Lay out the applet
       add("Center",canvas);
       add("South", buttonBar);

   }  // end init()
   
   
   public Insets getInsets() {
   
        // This routine is called by the system to determine how much
        // space to leave between the edges of the applet and the
        // components that the applet contains.  It leaves a 3-pixel
        // border, which will be displayed in the background color.
        
      return new Insets(3,3,3,3);
      
   }
   
   
   
   synchronized public void stop() {

         // Called by the system when the applet is stopped.  Also called
         // by the actionPerformed() method when the user clicks on the
         // button to stop the blinking.  The purpose is to tell the
         // runner to terminate (if it exists and is running).

      if (runner != null && runner.isAlive()) {
         status = TERMINATE;
         notify();
         runner = null;
      }

   }  // end stop()
   
   
   
   synchronized public void actionPerformed(ActionEvent evt) {
   
         // This routine is called by the system when an "action" is performed
         // by the user, provided that the applet has been set as a "listener"
         // for such events.
         
         String command = evt.getActionCommand();
         
         if (command.equals("Blink!")) {   // start a thread to blink the message
            runner = new Thread(this);
            status = GO;
            runner.start();
         }
         else if (command.equals("Stop!")) {  // stop the thread
            stop();
         }
         else if (command.equals("Red/Green")) {  // set alternate color to green
            alternateColor = Color.green;
            if (!isRed)  // if alternate color is visible, change the display
               canvas.setTextColor(Color.green);
         }
         else if (command.equals("Red/Blue")) { // set alternate color to blue
            alternateColor = Color.blue;
            if (!isRed) // if alternate color is visible, change the display
               canvas.setTextColor(Color.blue);
         }
         
   }  // end init()
   
   
   public void run() {
   
         // This routine is run by the thread, runner.  It blinks the message
         // from red to green as long as the status variable has value GO.
         
      blinkBttn.setLabel("Stop!");
      while (status == GO) {
         waitDelay(300);
         changeColor();
      }
      blinkBttn.setLabel("Blink!");
      
   } // end run()
   
   
   synchronized void changeColor() {
         // change color from red to alternateColor or vice versa.
      if (isRed) {
         canvas.setTextColor(alternateColor);
         isRed = false;
      }
      else {
         canvas.setTextColor(Color.red);
         isRed = true;
      }
   }

   
   synchronized void waitDelay(int milliseconds) {
         // Pause for the specified number of milliseconds
         // OR until the notify() method is called by some other thread.
      try {
         wait(milliseconds);
      }
      catch (InterruptedException e) {
      }
   }
   
   
} // end class ColoredHelloWorldApplet2


