/*  The ConsoleApplet provides a basis for writing applets that simulate
    line-oriented console-type input/output.  The class ConsoleCanvas is
    used to provide the I/O routines; these routines type output into
    the ConsoleCanvas and read input typed there by the user.  See the
    file ConsoleCanvas.java for information.
    
    A console applet is set up to run one particular program.  The applet
    includes a button that the user presses to run the program (or to
    abort it when it is running).  It also includes a label, which by default
    is "Java I/O Console".  The default program, defined in this file,
    is a simple Hello World program.
    
    To write a new console applet, with a more interesting program, you
    should create a subclass of ConsoleApplet.  The subclass should
    override the method  program() , which represents the program to 
    be run.  The program should use the instance variable console to
    do input/output.  For example, console.putln("HelloWorld.")
    or N=console.getInt().  All the public methods of class ConsolePanel
    can be called in the program.
    
    (Of course, you could also just modify this file, instead of
    writing a subclass.)
    
    David Eck
    Department of Mathematics and Computer Science
    Hobart and William Smith Colleges
    Geneva, NY 14456
    eck@hws.edu
    
    December 9, 1997.  This is a modification of a version written
    on August 2, 1996.  (The modified version uses a new ConsolePanel
    instead of an old ConsoleCanvas.  Subclasses of the old applet
    should still work with this new version.)

*/



import java.awt.*;

public class ConsoleApplet extends java.applet.Applet
                           implements Runnable
{

   protected String title = "Java I/O Console";  // label that appears over the console;
       // if you want to change this, override the init() method to assign a different
       // value to title and THEN call super.init()/
       
   protected  ConsolePanel console;  // console for use in program()
   
   protected void program() {  // the console-type program; override this in your sub-class
      console.putln("Hello World!");
   }
   
   
   private Button runButton;  // user presses this to run the program
   
   private Thread programThread = null;     // thread for running the program; the run()
                                            //    method calls program()
   private boolean programRunning = false;
   private boolean firstTime = true;  //    set to false the first time program is run
   
   public void run() {   // just run the program()
      programRunning = true;
      program();
      programRunning = false;
      stopProgram();
   }
   
   synchronized private void startProgram() {
      programThread = new Thread(this);
      if (!firstTime) {
         console.clear();
         try { Thread.sleep(500); }  // some delay before restarting the program
         catch (InterruptedException e) { }
      }
      firstTime = false;
      runButton.setLabel("Abort Program");
     // programThread.setPriority(programThread.getPriority() - 1);  Security error in Netscape for Mc 3.0 ??????
      programThread.start();
   }
   
   synchronized private void stopProgram() {
      if (programRunning) {
         programThread.stop();
         try { programThread.join(200); }
         catch (InterruptedException e) { }
      }
      console.clearBuffers();
      programThread = null;
      programRunning = false;
      runButton.setLabel("Run Again");
      runButton.requestFocus();
   }

   public void init() {
   
      setBackground(Color.black);
   
      setLayout(new BorderLayout(2,2));
      console = new ConsolePanel();
      add("Center",console);
      
      Panel temp = new Panel();
      temp.setBackground(Color.white);
      Label lab = new Label(title);
      temp.add(lab);
      lab.setForeground(new Color(180,0,0));
      add("North", temp);
      
      runButton = new Button("Run the Program");
      temp = new Panel();
      temp.setBackground(Color.white);
      temp.add(runButton);
      add("South",temp);
      
   }

   public Insets insets() {
      return new Insets(2,2,2,2);
   }
      
   public void stop() {
      if (programRunning) {
         stopProgram();
         console.putln();
         console.putln("*** PROGRAM HALTED");
      }
   }
   
   public boolean action(Event evt, Object arg) {
      if (evt.target instanceof Button) {
         doButton();
         return true;
      }
      return false;         
   }
   
   synchronized private void doButton() {  // if program is running, stop it; otherwise, run it
      if (programThread != null) {
         stopProgram();
         console.putln();
         console.putln("*** PROGRAM ABORTED BY USER");
      }
      else
         startProgram();
   }
   
}