//    $Id: DemonGUI.java,v 3.11 1998/12/11 18:40:04 jpg3u Exp $
 /////////////////////////////////////////////////////////////////////
 //
 // File: DemonGUI.java
 //
 // Purpose: The    DemonGUI is responsible    for providing a    graphical
 //        interface for the DemonEngine.  The    GUI uses the
 //        DemonApplet    to display components and detect user
 //        actions in the browser.
 //
 // Authors: txr     Travis    Emmitt    emmitt@virginia.edu
 //          jpg  James P. Gunderson  gunders@Virginia.EDU
 //
 // Modifications:
 //   11-DEC-1998  jpg  fixed null pointer problems, editable problem in
 //                     delay field, cosmetic changes to buttons.
 //   09-DEC-1998  jpg  added state constants, set initial state to SHUTDOWN
 //   09-DEC-1998  jpg  added Quit method, initial state
 //   09-DEC-1998  jpg  fixed start of run messaging
 //   09-DEC-1998  jpg  fixed race condition in event handler/ submit button
 //   09-DEC-1998  jpg  converted to ReceiveState signature
 //   08-DEC-1998  jpg  added new constructor for port and server strings
 //   07-DEC-1998  jpg  modified to support changes to ClientConnectStatus
 //   03-DEC-1998  jpg  modified SetState functionality
 //   02-DEC-1998  jpg  added auto/manual and abort buttond
 //   02-DEC-1998  jpg  modified ClientConnect Status to int
 //   16-NOV-1998  jpg  renamed existing ClientGUI.java to DemonGUI.java
 //   17-NOV-1998  jpg  shimmed display
 //   17-NOV-1998  jpg  conformed DisplayStats
 //   18-NOV-1998  jpg  added Exception Exit code
 //   20-NOV-1998  jpg  input is disabled during simulation
 //   20-NOV-1998  jpg  updated stats display
 //   20-NOV-1998  jpg  added graphic connection status display
 //
 /////////////////////////////////////////////////////////////////////
 import java.applet.*;
 import java.awt.*;
 import java.util.*;
 public class DemonGUI {
   // Adjoining Modules //
   private DemonApplet applet;      // provides access to    browser
   private DemonEngine engine;      // handles high-level    logic
     // Screen components //
   private DrawableMap draw_map;       // screen representation of map
   private Panel main_panel;       // area    where drawable map goes
   private TextArea details_area;   // details area    (at top    right)
   private TextArea stats_area;       // stats   area    (at right)
   private TextArea ccs_area;       // Client Connection Display
   private TextArea status_area;       // status  area (at bottom left)
   private TextField run_field;   // used for selecting delay
   private TextField delay_field;   // used for selecting number of runs
   private Button all_button;       // used for selecting all prob mode
   private Button sum_button;       // used for selecting sum prob mode
   private Button any_button;       // used for selecting any prob mode
   private Button manual_button;       // used for selecting manual mode
   private Button automatic_button; // used for selecting automatic mode
   private Button abort_button;     // used to kill a running simulation
   private ClientConnectStatus ccs ;
   private Button submit_button;       // used for submitting changes
   private Button quit_button;
     // Component resources //
   private int font_size       = 10;  // size of default font
   private int stats_cols   = 47;  // number of columns in stats    area
   private int stats_rows   = 12;    // number of rows in stats area
   private int ccs_cols     = 70;    // number of columns in stats    area
   private int ccs_rows     = 1;      // number of rows in stats area
   private int status_cols  = 47;  // number of columns in status area
   private int status_rows  = 20;    // number of rows in status area
   private int delay_cols   =  5;      // number of columns in delay field
   private int run_cols     =  5;     // number of columns in run field
   private int prob_mode    = -1;     // mode of probability propagation
   private int proc_mode    = -1;     // 0 = manual, 1 = automatic
   private long delay       = 1000 ;
   private int runs = 0;
   private int map_bounds[] = { 0, 0, 400, 400 };
   // Other private data //
   private int edit_id;        // which module    can we edit?
   private static final int SIM_CHOOSEMODE = 0;
   private static final int SIM_WAITSUBMIT = 1;
   private static final int SIM_RUNNING    = 2;
   private static final int SIM_SHUTDOWN   = 3;
   private int current_mode = SIM_SHUTDOWN;
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  DemonGUI    [constructor]
   //
   // Invoker: DemonApplet
   //
   // Purpose: By passing a reference to    itself when calling the
   //          DemonGUI construtor, DemonApplet gives DemonGUI
   //          a    way to invoke the DemonApplet methods, enabling
   //          two-way communication between the    applet and the GUI.
   //
   //        This constructor then creates a    DemonEngine, passing server and  //          port ID,
   //          establishing a similar two-way interface.     It also
   //          creates and adds various graphical components and
   //          performs other needed initialization.
   //
   ///////////////////////////////////////////////////////////////////
   public DemonGUI (DemonApplet parent_applet, String server, String port)
     throws NullException, Exception    {
       current_mode = 0;
       if (parent_applet == null) {
         throw new NullException    ("parent_applet");
       }
        if (server == null) {
         throw new NullException    ("server string");
       }
         if (port == null) {
         throw new NullException    ("port string");
       }
       try {
         applet = parent_applet;
         SetupLayout ();
         ccs = new ClientConnectStatus();
         engine = new DemonEngine (this, server, port);
       }
       catch (Exception e) {
         Warn("Startup Failure: Is the server running? \nClose this applet and restart.");
         ReceiveState(SIM_SHUTDOWN) ;
       }
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Add (private)
   //
   // Purpose: Adds specified component to layout with specified
   //        cell bounds.
   //
   ///////////////////////////////////////////////////////////////////
   private void Add (Component component, int x,    int y, int w, int h)
     throws NullException, Exception    {
       if (component == null) {
         throw new NullException    ("component");
       }
       try {
         constraints.gridx      = x;
         constraints.gridy      = y;
         constraints.gridwidth  = w;
         constraints.gridheight = h;
         layout.setConstraints (component, constraints);
         applet.add (component);
       }
       catch (Exception e) {
         throw e;
       }
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  DisplayMap
   //
   // Invoker: DemonEngine
   //
   // Purpose: This displays the    specified Map on the screen.
   //          The second argument tells the GUI which    Module
   //          "belongs"    to this    particular Demon, since    each
   //          GUI treats its own Module    a little differently
   //          from how it treats other Demons' Modules.
   //
   ///////////////////////////////////////////////////////////////////
   public void DisplayMap (Map new_map)
     throws NullException, Exception    {
       if (new_map == null) {
         throw new NullException    ("new_map");
       }
       try {
         draw_map = new DrawableMap (new_map, map_bounds, edit_id);
         if (!draw_map.Valid ())    {
           Warn ("Map is invalid... you might get errors!");
         }
       }
       catch (Exception e) {
         Error (e);
         throw e;
       }
       applet.repaint ();
   }
   /////////////////////////////////////////////////////////////////////
   //
   // Method:  DisplayModuleDetails
   //
   // Invoker: (private)
   //
   // Purpose: Displays details about specified Module, its contents,
   //        and    its related dependencies.
   //
   ////////////////////////////////////////////////////////////////////
   private  void DisplayModuleDetails (int module_id)
        throws Exception {
     try {
       int num_modules    = draw_map.GetNumModules ();
       String details    = draw_map.GetModule (module_id).Verbose();
       int mids[]    = draw_map.GetDependeeModuleIDs    (module_id);
       details    += "\n"    + "  Depends upon:";
       for (int i = 0;    i < num_modules    && mids[i] >= 0; i++) {
     if (mids[i] == module_id) {
       continue;                   // don't display internal dependencies
     }
     Module dest = draw_map.GetModule (mids[i]);
     int nids[]  = draw_map.GetDependeeNodeIDs (module_id, mids[i]);
     details    += "\n      " + dest.GetName();
     for (int j = 0;    j < dest.GetNumNodes() && nids[j] >= 0;    j++) {
       details    += (j == 0 ? ":    " : ", ") + dest.GetNode(nids[j]).GetName();
     }
       }
       mids = draw_map.GetDependerModuleIDs (module_id);
       details    += "\n\n  Is depended upon by:";
       for (int i = 0;    i < num_modules    && mids[i] >= 0; i++) {
     if (mids[i] == module_id) {
       continue;                   // don't display internal dependencies
     }
     Module source =    draw_map.GetModule (mids[i]);
     int nids[]    =    draw_map.GetDependerNodeIDs (module_id,    mids[i]);
     details    += "\n      " + source.GetName();
     for (int j = 0;    j < source.GetNumNodes() && nids[j] >= 0; j++) {
       details    += (j == 0 ? ":    " : ", ") + source.GetNode(nids[j]).GetName();
     }
       }
       details_area.setText (details);
     }
     catch (Exception e) {
       Error (e);
       throw e;
     }
   }
   /////////////////////////////////////////////////////////////////////
   //
   // Method:  DisplayNodeDetails
   //
   // Invoker: (private)
   //
   // Purpose: Displays details about specified Node and    its related
   //        dependencies.
   //
   ////////////////////////////////////////////////////////////////////
   private void DisplayNodeDetails    (int module_id,    int node_id)
     throws Exception {
     try {
       int num_modules    = draw_map.GetNumModules ();
       String details    = draw_map.GetNode (module_id, node_id).Verbose();
       int mids[]    = draw_map.GetDependeeModuleIDs    (module_id, node_id);
       details    += "\n"    + "  Depends upon:";
       for (int i = 0;    i < num_modules    && mids[i] >= 0; i++) {
     Module dest = draw_map.GetModule (mids[i]);
     int nids[]  = draw_map.GetDependeeNodeIDs (module_id, mids[i]);
     details    += "\n      " + dest.GetName();
     for (int j = 0;    j < dest.GetNumNodes() && nids[j] >= 0;    j++) {
       details    += (j == 0 ? ":    " : ", ") + dest.GetNode(nids[j]).GetName();
     }
       }
       mids = draw_map.GetDependerModuleIDs (module_id, node_id);
       details    += "\n\n  Is depended upon by:";
       for (int i = 0;    i < num_modules    && mids[i] >= 0; i++) {
     Module source =    draw_map.GetModule (mids[i]);
     int nids[]    =    draw_map.GetDependerNodeIDs (module_id,    mids[i]);
     details    += "\n      " + source.GetName();
     for (int j = 0;    j < source.GetNumNodes() && nids[j] >= 0; j++) {
       details    += (j == 0 ? ":    " : ", ") + source.GetNode(nids[j]).GetName();
     }
       }
       details_area.setText (details);
     }
     catch (Exception e) {
       Error (e);
       throw e;
     }
   }
   /////////////////////////////////////////////////////////////////////
   //
   // Method:  DisplayStats
   //
   // Invoker: DemonEngine
   //
   // Purpose: Displays the specified Stats data    structure.
   //
   ////////////////////////////////////////////////////////////////////
   public void DisplayStats (Stats    new_stats)
     throws NullException, Exception    {
       if (new_stats.GetTurn() == 1) {
     stats_area.appendText ("\n\nSTART *****************\n\n" );
       }
       String next_line = new String("Tick: " + new_stats.GetTurn() + "   ");
       try {
     if (new_stats == null) {
       throw new NullException("new_stats");
     }
     next_line += "   Recov: " + new_stats.GetTurnRecoveries() + "/"
                      + new_stats.GetTotalRecoveries() ;
     next_line += "   Destab: " + new_stats.GetTurnDestabilizations() + "/"
                      + new_stats.GetTotalDestabilizations() ;
     next_line += "   Unstable: " + new_stats.GetTurnUnstableNodes() + "/"
                      + new_stats.GetTotalUnstableNodes() ;
     next_line += "\n" ;
     stats_area.appendText (next_line );
       }
       catch (Exception e) {
     Error (e);
     throw e;
       }
   }
 /////////////////////////////////////////////////////////////////////
 // // Method: DisplayClientConnectStatus // // Invoker: DemonEngine //
 // Purpose: Displays the specified ClientConnectStatus data structure.
 //
 ////////////////////////////////////////////////////////////////////
 public void DisplayClientConnectStatus (ClientConnectStatus new_ccs)
        throws NullException, Exception {
      ccs = new ClientConnectStatus(new_ccs);
      String ConStat = "\nConnected: " ;
      try {
        if (new_ccs == null) {
          throw new NullException ("new_ccs");
        }
        for(int i = 0; i < new_ccs.GetNumClients(); i++) {
          if (new_ccs.GetClientConnStatus(i)){
            ConStat += i + " " ;
          }
        }
        ccs_area.appendText (ConStat);
      }
      catch (Exception e) {
        Error (e);
        throw e;
      }
      applet.repaint();
 }
   //////////////////////////////////////////////////////////////////////////
   //
   // Method:  SetupLayout  (private)
   //
   // Purpose: Sets up screen layout by positioning buttons, text areas,    etc.
   //
   //////////////////////////////////////////////////////////////////////////
   private    GridBagLayout       layout;
   private    GridBagConstraints constraints;
   private    void SetupLayout ()
     throws Exception {
       applet.setFont (new Font ("Helvetica", Font.PLAIN, font_size));
       applet.setLayout (layout = new GridBagLayout());
       constraints = new GridBagConstraints ();
       int END    = GridBagConstraints.REMAINDER;
       int REL    = GridBagConstraints.RELATIVE;
       Add (ccs_area = new TextArea (ccs_rows, ccs_cols), 0, 3, 1, END );
       Add (status_area = new TextArea(status_rows, status_cols), 2, 0, END, 1);
       Add(stats_area = new TextArea(stats_rows, stats_cols), 2, 1, END, 1 );
       Panel upper_right = new Panel() ;
       upper_right.add (manual_button = new Button ("Manual"));
       upper_right.add (automatic_button = new Button ("Automatic"));
       upper_right.add (run_field = new TextField("0", run_cols));
       automatic_button.setBackground(Color.gray);
       manual_button.setBackground(Color.gray);
       automatic_button.setForeground(Color.black);
       manual_button.setForeground(Color.black);
       run_field.setEnabled(false);
       upper_right.add (new Label ("# of Runs"));
       Add(upper_right, 2,3,END,1);
       Panel mid_right = new    Panel ();
       mid_right.add    (new Label ("Delay"));
       mid_right.add    (delay_field  = new TextField ("1000", delay_cols));
       mid_right.add    (all_button = new Button ("All"));
       mid_right.add    (sum_button = new Button ("Sum"));
       mid_right.add    (any_button = new Button ("Any"));
       all_button.setBackground(Color.gray);
       sum_button.setBackground(Color.gray);
       any_button.setBackground(Color.gray);
       all_button.setForeground(Color.black);
       sum_button.setForeground(Color.black);
       any_button.setForeground(Color.black);
       Add (mid_right, 2, 4, END, 1);
       Panel lower_right = new Panel() ;
       lower_right.add (submit_button = new Button ("Submit"));
       lower_right.add (quit_button = new Button("Quit"));
       lower_right.add (abort_button = new Button("Abort"));
       Add(lower_right, 2,5,END,1);
       stats_area.setEditable     (false);
       stats_area.setBackground (Color.black);
       stats_area.setForeground (Color.white);
       status_area.setEditable     (false);
       status_area.setBackground (Color.black);
       status_area.setForeground (Color.yellow);
       delay_field.setEnabled (false);
       delay_field.setBackground (Color.white);
       delay_field.setForeground (Color.blue);
       submit_button.disable ();
       all_button.disable() ;
       sum_button.disable() ;
       any_button.disable() ;
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Draw
   //
   // Invoker: DemonApplet
   //
   // Purpose: The main purpose of this method is to enable the
   //          Drawable objects to be displayed in the browser
   //        window.     These objects need access to the applet's
   //          Graphics object.    DemonGUI passes    a reference to
   //          the Graphics object to the DrawableMap class, which
   //          in turn passes it    to the other Drawable classes.
   //
   ///////////////////////////////////////////////////////////////////
   public void Draw (Graphics graphics)
     throws Exception {
       int x_base = 30 ;
       int y_base = 430 ;
       int size = 15 ;
     if (draw_map != null) {
       try {
      draw_map.DrawMatrix (graphics);
       }
       catch (Exception e) {
     Notify("Map is Bad");
     Error (e) ;
     throw e ;
       }
     }
       graphics.setColor(Color.black);
       graphics.fillRect(x_base - 5, y_base - 5, 21 * size, 25);
       if (ccs.GetNumClients() != 0) {
     for ( int i = 0; i < ccs.GetNumClients(); i++) {
       if (!ccs.GetClientConnStatus(i)) {
         graphics.setColor(Color.gray);
       }
       else {
         if (!ccs.GetClientSubStatus(i)) {
           graphics.setColor(Color.yellow);
         }
         else {
           graphics.setColor(Color.blue);
         }
       }
       graphics.fillOval(x_base + (2 * i * size), y_base, size, size);
     }
       }
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  HandleClick
   //
   // Invoker: DemonApplet
   //
   // Purpose: When the user clicks the mouse inside the    applet
   //          window, the browser notifies DemonApplet,    which
   //          then invokes this    method (HandleClick).
   //
   //          HandleClick's job    is to find out which screen object
   //          was clicked, and then inform the DemonEngine.
   //
   ///////////////////////////////////////////////////////////////////
   public void HandleClick (Event event,    int x, int y) {
     if (draw_map ==    null) {
       return;     // No need for    exception; just    ignore click
     }
     try {
       applet.repaint();
     }
     catch (Exception e) {
       Error (e);
     }
   }
   /////////////////////////////////////////////////////////////////////
   //
   // Method:  HandleAction
   //
   // Invoker: DemonApplet
   //
   // Purpose: When the user activates a    component, the browser
   //          notifies DemonApplet, which then invokes this
   //          method (HandleAction).
   //    
   //          HandleAction's job is to find out    which screen
   //          component    was activated, and then    inform the
   //          DemonEngine.
   //
   // Notes:   Currently we don't use the object parameter.
   //
   /////////////////////////////////////////////////////////////////////
   public void HandleAction (Event event, Object    object)
      throws Exception {
     if (event.target.equals(all_button)) {
       prob_mode = 3;
       all_button.setBackground(Color.blue);
       sum_button.setBackground(Color.gray);
       any_button.setBackground(Color.gray);
       all_button.setForeground(Color.white);
       sum_button.setForeground(Color.black);
       any_button.setForeground(Color.black);
       submit_button.enable();
     }
     if (event.target.equals(sum_button)) {
       prob_mode = 2 ;
       all_button.setBackground(Color.gray);
       sum_button.setBackground(Color.blue);
       any_button.setBackground(Color.gray);
       all_button.setForeground(Color.black);
       sum_button.setForeground(Color.white);
       any_button.setForeground(Color.black);
       submit_button.enable();
     }
     if (event.target.equals(any_button)) {
       prob_mode = 1 ;
       all_button.setBackground(Color.gray);
       sum_button.setBackground(Color.gray);
       any_button.setBackground(Color.blue);
       all_button.setForeground(Color.black);
       sum_button.setForeground(Color.black);
       any_button.setForeground(Color.white);
       submit_button.enable();
     }
     if (event.target.equals(manual_button)) {
       automatic_button.setBackground(Color.gray);
       manual_button.setBackground(Color.blue);
       automatic_button.setForeground(Color.black);
       manual_button.setForeground(Color.white);
       run_field.setEnabled(false);
       submit_button.setEnabled(true);
       proc_mode = 1 ;
       runs = 1 ;
     }
     if (event.target.equals(automatic_button)) {
       automatic_button.setBackground(Color.blue);
       manual_button.setBackground(Color.gray);
       automatic_button.setForeground(Color.white);
       manual_button.setForeground(Color.black);
       run_field.setEnabled(true);
       submit_button.setEnabled(true);
       proc_mode = 0 ;
     }
     if    (event.target.equals (submit_button)) {
       if (current_mode == 0) {
     if (proc_mode == 1) {
       Notify("Submitting Manual Mode");
     }
     if (proc_mode == 0) {
       Notify("Submitting Automatic Mode, Runs = " + runs );
     }
     engine.SubmitMode (proc_mode, runs);
       }
       else if (current_mode == 1) {
     Notify(&quot;Submitting delay= &quot; + delay + &quot; prob_mode = &quot; + prob_mode );
     engine.SetParameters (prob_mode, delay);
       }
     }
     if (event.target.equals (run_field)) {
       Notify(&quot;Run entered&quot;);
       String string = null;
       try {
     string = run_field.getText().trim();
     runs = new Integer(string).intValue();
       }
       catch (Exception e) {
     Warn (new ParsingException (&quot;runs field&quot;, string).getMessage());
     runs = -1;
     return;
       }
     }
     if    (event.target.equals (abort_button)) {
       Notify(&quot;Aborting current Run&quot;);
       engine.AbortClicked ();
     }
     if    (event.target.equals (quit_button)) {
       engine.QuitClicked ();
     }
     if (event.target.equals (delay_field)) {
       Notify(&quot;Delay entered&quot;);
       String d_string = null;
       try {
     d_string = delay_field.getText().trim();
     delay = new Integer(d_string).intValue();
       }
       catch (Exception e) {
     Warn (new ParsingException (&quot;delay field&quot;, d_string).getMessage());
     delay = -1;
     return;
       }
     }
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Notify
   //
   // Invoker: DemonEngine
   //
   // Purpose: This displays the    specified string in the    message    box.
   //
   ///////////////////////////////////////////////////////////////////
   public void Notify (String string) {
     status_area.appendText ((string    == null    ? "ooops" : string) + "\n");
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Freeze
   //
   // Invoker: DemonEngine
   //
   // Purpose: This "freezes" the DemonGUI; it disables user input.
   //
   ///////////////////////////////////////////////////////////////////
   public void ReceiveState (int mode) {
     Notify("SetState invoked: mode = " + mode);
   current_mode = mode ;
   if (current_mode == SIM_CHOOSEMODE) {
     // the user needs to select auto or manual first
     automatic_button.setBackground(Color.gray);
     manual_button.setBackground(Color.gray);
     automatic_button.setForeground(Color.black);
     manual_button.setForeground(Color.black);
     all_button.setBackground(Color.gray);
     sum_button.setBackground(Color.gray);
     any_button.setBackground(Color.gray);
     all_button.setForeground(Color.black);
     sum_button.setForeground(Color.black);
     any_button.setForeground(Color.black);
     submit_button.setBackground(Color.gray);
     quit_button.setBackground(Color.gray);
     abort_button.setBackground(Color.gray);
     submit_button.setForeground(Color.black);
     quit_button.setForeground(Color.black);
     abort_button.setForeground(Color.black);
     manual_button.setEnabled(true);
     automatic_button.setEnabled(true) ;
     run_field.setEnabled(false); // only activate after Auto is selected
     all_button.setEnabled(false);
     sum_button.setEnabled(false);
     any_button.setEnabled(false);
     submit_button.setEnabled(false);
     quit_button.setEnabled(true);
     delay_field.setEnabled(false);
     abort_button.setEnabled(false) ;
     prob_mode = -1 ;
     proc_mode = -1 ;
   }
   if (current_mode == SIM_WAITSUBMIT) {
     // now we're waiting for the user to select the propagation and delay
     all_button.setBackground(Color.gray);
     sum_button.setBackground(Color.gray);
     any_button.setBackground(Color.gray);
     all_button.setForeground(Color.black);
     sum_button.setForeground(Color.black);
     any_button.setForeground(Color.black);
     all_button.setEnabled(true);
     submit_button.setBackground(Color.gray);
     quit_button.setBackground(Color.gray);
     abort_button.setBackground(Color.gray);
     submit_button.setForeground(Color.black);
     quit_button.setForeground(Color.black);
     abort_button.setForeground(Color.black);
     all_button.setEnabled(true);
     sum_button.setEnabled(true);
     any_button.setEnabled(true);
     manual_button.setEnabled(false);
     automatic_button.setEnabled(false) ;
     run_field.setEnabled(false);
     submit_button.setEnabled(false);
     quit_button.setEnabled(true);
     delay_field.setEnabled(true);
   }
   if (current_mode == SIM_RUNNING) {
     // while we are running, these buttons are off
     all_button.setEnabled(false);
     sum_button.setEnabled(false);
     any_button.setEnabled(false);
     manual_button.setEnabled(false);
     automatic_button.setEnabled(false) ;
     run_field.setEnabled(false);
     submit_button.setEnabled(false);
     quit_button.setEnabled(false);
     delay_field.setEnabled(false);
     // this guy is only active while we are running
     abort_button.setEnabled(true) ;
   }
   if (current_mode == SIM_SHUTDOWN) {
     // while we are running, these buttons are off
     all_button.setEnabled(false);
     sum_button.setEnabled(false);
     any_button.setEnabled(false);
     manual_button.setEnabled(false);
     automatic_button.setEnabled(false) ;
     run_field.setEnabled(false);
     submit_button.setEnabled(false);
     quit_button.setEnabled(false);
     delay_field.setEnabled(false);
     abort_button.setEnabled(false) ;
   }
 }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Warn
   //
   // Invoker: (private)
   //
   // Purpose: Displays specified warning in message box.
   //
   ///////////////////////////////////////////////////////////////////
   private void Warn (String message) {
     Notify ("WARNING: " + (message == null ? "null"    : message));
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  DEBUG
   //
   // Invoker: (private)
   //
   // Purpose: Displays specified debug message (remove this later).
   //
   ///////////////////////////////////////////////////////////////////
   private    void DEBUG (String message) {
     Notify ("DEBUG:    " + (message ==    null ? "null" :    message));
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Error
   //
   // Invoker: DemonEngine
   //
   // Purpose: Displays the specified error in the message box, and
   //          then tells the applet to dump a stack trace to the
   //          console.  Use this for debugging programming errors.
   //   
   ///////////////////////////////////////////////////////////////////
   public void Error (Exception e) {
     Notify ("ERROR: " + e.getMessage());
     applet.Exit (e);
   }
   ///////////////////////////////////////////////////////////////////
   //
   // Method:  Quit
   //
   // Invoker: ClientApplet
   //
   // Purpose: This tells the engine that the applet has been exited
   //          by the user.
   //
   ///////////////////////////////////////////////////////////////////
   public void Quit () {
     Notify ("Shutting down Demon...");
     if (engine != null) {
       try {
     engine.Quit ();
       }
       catch (Exception e) {
     Error (e);
       }
     }
   }
 } // end of Class
 ////////////////////////////////////////////////////////////////////////