
// An applet that says "Hello World" in a big bold font.  When the user
// clicks on a button labeled "Blink!", the message starts cycling
// between two color.  If the user clicks on the button again, the 
// cycling stops.  Two other buttons can be used to select whether the
// applet cycles between read and green or between black and 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 useRedAndGreen;     // True if the colors are red/green;
                               // False if the colors are black/blue.
                               
   boolean showingFirstColor;  // True if the current color is the first
                               // color (red or black), false if it is the
                               // second color (green or blue).
   
                          

   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);
       buttonBar.add(redGreenBttn);
       
       Button redBlueBttn = new Button("Black/Blue");
       redBlueBttn.addActionListener(this);       
       buttonBar.add(redBlueBttn);

       setLayout(new BorderLayout(3,3));  // Lay out the applet.
       add(canvas, BorderLayout.CENTER);
       add(buttonBar, BorderLayout.SOUTH);
       
       useRedAndGreen = true;
       showingFirstColor = true;

   }  // 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 colors to red/green
            useRedAndGreen = true;
            if (showingFirstColor)
               canvas.setTextColor(Color.red);
            else
               canvas.setTextColor(Color.green);
         }
         else if (command.equals("Black/Blue")) { // set colors to black/blue
            useRedAndGreen = false;
            if (showingFirstColor)
               canvas.setTextColor(Color.black);
            else
               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 from first to second color or vice versa.
       if (showingFirstColor) {
             // Change to showing second color.
          showingFirstColor = false;
          if (useRedAndGreen)
             canvas.setTextColor(Color.green);
          else
             canvas.setTextColor(Color.blue);
       }
       else {
             // Change to showing first color.
          showingFirstColor = true;
          if (useRedAndGreen)
             canvas.setTextColor(Color.red);
          else
             canvas.setTextColor(Color.black);
       }
   }  // end chandeColor()

   
   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


