//******************************************************************************
// DLSim.java:	Applet
//
//******************************************************************************
import java.applet.*;
import java.awt.*;
import java.util.*;
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();
		frame.resize(frame.insets().left + frame.insets().right  + WID,
					 frame.insets().top  + frame.insets().bottom + HT);

		// 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.
		//----------------------------------------------------------------------
		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()
	{
        // 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.
        //----------------------------------------------------------------------
		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;
		objlst = new DLobj[12];
		objlst[0] = new DLand(this);
		objlst[1] = new DLor(this);
		objlst[2] = new DLnot(this);
		objlst[3] = new DLnand(this);
		objlst[4] = new DLnor(this);
		objlst[5] = new DLext(this);
		objlst[6] = new DLbext(this);
		objlst[7] = new DLutee(this);
		objlst[8] = new DLdtee(this);
		objlst[9] = new DLswitch(this);
		objlst[10] = new DLbulb(this);
		objlst[11] = new DLlabel(this);
		SButton sbut = new SButton("S On", this);
		Panel spacer = new Panel();
		spacer.resize(DLobj.IWID, 2*DLobj.IHT);
		pegboard = new DCanvas(this);
		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);
		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();
		}
		// TODO: Place additional applet start code here
	}
	
	//		The stop() method is called when the page containing the applet is
	// no longer on the screen. The AppletWizard's initial implementation of
	// this method stops execution of the applet's thread.
	//--------------------------------------------------------------------------
	public void stop()
	{
		if (m_DLSim != null)
		{
			m_DLSim.stop();
			m_DLSim = null;
		}

		// TODO: Place additional applet stop code here
	}

	// THREAD SUPPORT
	//		The run() method is called when the applet's thread is started. If
	// your applet performs any ongoing activities without waiting for user
	// input, the code for implementing that behavior typically goes here. For
	// example, for an applet that performs animation, the run() method controls
	// the display of images.
	//--------------------------------------------------------------------------
	public void run()
	{
/*		while (true)
		{
			try
			{
				repaint();
				// TODO:  Add additional thread-specific code here
				Thread.sleep(50);
			}
			catch (InterruptedException e)
			{
				// TODO: Place exception-handling code here in case an
				//       InterruptedException is thrown by Thread.sleep(),
				//		 meaning that another thread has interrupted this one
				stop();
			}
		}
*/		repaint();
	}
}

class Simulate implements Runnable 
{
	DLSim theApplet;
	DCanvas theCanvas;

	Simulate(DLSim theApplet){this.theApplet = theApplet; this.theCanvas = theApplet.pegboard;}

	public void run()
	{
		Vector objlist = theCanvas.objlist;

		boolean done;
		do {
			done = true;
			for (int i = 0; i < objlist.size(); i++) {
				DLobj theobj = (DLobj)objlist.elementAt(i);
				boolean v = theobj.eval();
				done = done && !v;
				if (v && (theobj instanceof DLswitch || theobj instanceof DLbulb))
					theCanvas.repaint(theobj.bx, theobj.by, DLobj.WID, DLobj.HT);
			}
		} while (!done);
		if (theApplet.simmode == theApplet.SIMON) theCanvas.repaint();
	}
}

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("S Off");
			theApplet.pegboard.setBackground(DCanvas.SBKCOL);
			break;
		case theApplet.SIMON:
			theApplet.simmode = theApplet.SIMOFF;
			setLabel("S On");
			theApplet.pegboard.setBackground(DCanvas.BKCOL);
			break;
		}
		theApplet.pegboard.repaint();
		return true;
	}
}