//******************************************************************************
// DLSim.java:	Applet
//
//******************************************************************************
import java.applet.*;
import java.awt.*;
import java.util.*;
import java.io.*;
import DLSimFrame;

//==============================================================================
// Main Class for applet DLSim
//
//==============================================================================
public class DLSim extends Applet implements Runnable
{
  final static int WID = 700;
  final static int HT = 500;
  DLobj[] objlst;
  CPanel cpanel;
  DCanvas pegboard;
  Frame myFrame;
  final static int SIMOFF = 0;
  final static int SIMON = 1;
  int simmode = SIMOFF;

  // THREAD SUPPORT:
  //		m_DLSim	is the Thread object for the applet
  //--------------------------------------------------------------------------
  Thread	 m_DLSim = null;

  // STANDALONE APPLICATION SUPPORT:
  //		m_fStandAlone will be set to true if applet is run standalone
  //--------------------------------------------------------------------------
  boolean m_fStandAlone = false;

  // STANDALONE APPLICATION SUPPORT
  // 	The main() method acts as the applet's entry point when it is run
  // as a standalone application. It is ignored if the applet is run from
  // within an HTML page.
  //--------------------------------------------------------------------------
  public static void main(String args[])
  {
    // Create Toplevel Window to contain applet DLSim
    //----------------------------------------------------------------------
    DLSimFrame frame = new DLSimFrame("DLSim");

    // Must show Frame before we size it so insets() will return valid values
    //----------------------------------------------------------------------
    frame.show();
    frame.hide();

    // The following code starts the applet running within the frame window.
    // It also calls GetParameters() to retrieve parameter values from the
    // command line, and sets m_fStandAlone to true to prevent init() from
    // trying to get them from the HTML page.
    //----------------------------------------------------------------------
    DLMenu menu = new DLMenu(frame);
    menu.CreateMenu();
    frame.resize(frame.insets().left + frame.insets().right  + WID,
		 frame.insets().top  + frame.insets().bottom + HT + 20);
    DLSim applet_DLSim = new DLSim();
    frame.add("Center", applet_DLSim);
    applet_DLSim.m_fStandAlone = true;
    applet_DLSim.init();
    applet_DLSim.start();
    frame.show();
  }

  // DLSim Class Constructor
  //--------------------------------------------------------------------------
  public DLSim()
  {
    // TODO: Add constructor code here
  }

  // APPLET INFO SUPPORT:
  //		The getAppletInfo() method returns a string describing the applet's
  // author, copyright date, or miscellaneous information.
  //--------------------------------------------------------------------------
  public String getAppletInfo()
  {
    return "Name: DLSim\r\n" +
      "Author: Richard Salter\r\n" +
      "Created with Microsoft Visual J++ Version 1.0";
  }


  // The init() method is called by the AWT when an applet is first loaded or
  // reloaded.  Override this method to perform whatever initialization your
  // applet needs, such as initializing data structures, loading images or
  // fonts, creating frame windows, setting the layout manager, or adding UI
  // components.
  //--------------------------------------------------------------------------
  public void init()
  {
    int WID = DLSim.WID, HT = DLSim.HT;

    // If you use a ResourceWizard-generated "control creator" class to
    // arrange controls in your applet, you may want to call its
    // CreateControls() method from within this method. Remove the following
    // call to resize() before adding the call to CreateControls();
    // CreateControls() does its own resizing.
    //----------------------------------------------------------------------
    if (!m_fStandAlone) {
      String height = getParameter("height");
      String width = getParameter("width");
      if (height != null) HT = Integer.parseInt(height);
      if (width != null) WID = Integer.parseInt(width);
    }
    resize(WID, HT);
    setLayout(new FlowLayout(FlowLayout.LEFT));
    Component tmp = this;
    while (!(tmp instanceof Frame)) tmp = tmp.getParent();
    myFrame = (Frame)tmp;
    if (myFrame instanceof DLSimFrame) ((DLSimFrame)myFrame).theApplet = this;
    pegboard = new DCanvas(this);
    objlst = new DLobj[21];
    objlst[0] = new DLand(this);
    objlst[1] = new DLand3(this);
    objlst[2] = new DLor(this);
    objlst[3] = new DLor3(this);
    objlst[4] = new DLnot(this);
    objlst[5] = new DLnand(this);
    objlst[6] = new DLnor(this);
    objlst[7] = new DLxor(this);
    objlst[8] = new DLext(this);
    objlst[9] = new DLbext(this);
    objlst[10] = new DLutee(this);
    objlst[11] = new DLdtee(this);
    objlst[12] = new DLrtee(this);
    objlst[13] = new DLrdtee(this);
    objlst[14] = new DLswitch(this);
    objlst[15] = new DLbulb(this);
    objlst[16] = new DLone(this);		
    objlst[17] = new DLzero(this);				
    objlst[18] = new DLlabel(this);
    objlst[19] = new DLclock(this);
    objlst[20] = new DLadd(this);

    SButton sbut = new SButton("L Off", this);
    Panel spacer = new Panel();
    spacer.resize(DLobj.IWID, 2*DLobj.IHT);

    cpanel = new CPanel();
    cpanel.setLayout(new GridLayout(objlst.length+2,1));
    cpanel.add(sbut);
    cpanel.add(spacer);
    for (int i = 0; i < objlst.length; i++) {
      cpanel.add(objlst[i]);
      objlst[i].resize(DLobj.IWID, DLobj.IHT);
    }
    add(cpanel);
    add(pegboard);
    cpanel.resize(50,120);
    pegboard.resize(WID-70, HT-10);
	pegboard.doImage();
    repaint();
    if (m_fStandAlone) return;
    if (getParameter("obj0") != null) {
      Vector sobjlist = new Vector();
      String val;
      for (int n = 0; (val = getParameter("obj"+Integer.toString(n))) != null;
	   n++)
	sobjlist.addElement(val);
      pegboard.objlist = pegboard.unserialize(sobjlist, "");
      pegboard.repaint();
    }
  }

  // Place additional applet clean up code here.  destroy() is called when
  // when you applet is terminating and being unloaded.
  //-------------------------------------------------------------------------
  public void destroy()
  {
    // TODO: Place applet cleanup code here
  }

  // DLSim Paint Handler
  //--------------------------------------------------------------------------
  public void paint(Graphics g)
  {
  }

  //		The start() method is called when the page containing the applet
  // first appears on the screen. The AppletWizard's initial implementation
  // of this method starts execution of the applet's thread.
  //--------------------------------------------------------------------------
  public void start()
  {
    if (m_DLSim == null)
      {
	m_DLSim = new Thread(this);
	m_DLSim.start();
      }
  }
	
  public void stop()
  {
    if (m_DLSim != null)
      {
	m_DLSim.stop();
	m_DLSim = null;
      }
  }

  public void run()
  {
    repaint();
  }
}

class Simulate implements Runnable 
{
  DLSim theApplet;
  DCanvas theCanvas;

  Simulate(DLSim theApplet)
  {this.theApplet = theApplet; this.theCanvas = theApplet.pegboard;}

  public void run()
  {
    evalLoop(theCanvas);
    if (theApplet.simmode == theApplet.SIMON) theCanvas.repaint();
  }

  static void evalLoop(Vector objlist){evalLoop(objlist, null);}
  static void evalLoop(DCanvas theCanvas)
  {evalLoop(theCanvas.objlist, theCanvas);}
  static void evalLoop(Vector objlist, DCanvas theCanvas)
  {
    boolean done, foundabs = false;
    for (int j = 0; j < 2; j++) {
      do {
	done = true;
	for (int i = 0; i < objlist.size(); i++) {
	  DLobj theobj = (DLobj)objlist.elementAt(i);
	  if (j == 0 && theobj instanceof DLabs) {
	    foundabs = true;
	    continue;
	  }
	  boolean v = theobj.eval();
	  done = done && !v;
	  if (theCanvas == null) continue;
	  if (v && (theobj instanceof DLswitch || theobj instanceof DLbulb))
	    theCanvas.repaint(theobj.bx, theobj.by, theobj.WIDTH, theobj.HTH);
	}
      } while (!done);
      if (!foundabs) break;
    }
  }
}

class SButton extends Button
{
  DLSim theApplet;

  SButton(String label, DLSim theApplet) 
  {super(label); this.theApplet = theApplet;}
	
  public boolean action(Event evt, Object what)
  {
    switch (theApplet.simmode) {
    case theApplet.SIMOFF:
      theApplet.simmode = theApplet.SIMON;
      setLabel("L On");
      theApplet.pegboard.setBackground(DCanvas.SBKCOL);
      break;
    case theApplet.SIMON:
      theApplet.simmode = theApplet.SIMOFF;
      setLabel("L Off");
      theApplet.pegboard.setBackground(DCanvas.BKCOL);
      break;
    }
    theApplet.pegboard.repaint();
    return true;
  }
}
