/*
	Newton.java - A gravity simulation applet.

	©1996-1997 by Michael J. Webb
*/

// Imports.

import java.applet.Applet;

import java.awt.*;

import java.lang.Math;
import java.lang.Thread;

import java.util.Random;

import IdleTask;
import TickerThread;

/** A gravity simulation applet.
 */

public class Newton extends Applet
	implements IdleTask
{

	/** Applet info.
	 */
	public String getAppletInfo()
	{
		return ("Newton 0.0d0, ©1996-1997 by Mike Webb");
	}

	/** Applet parameter info.
	 */
	public String[][] getParameterInfo()
	{
		String[][] theInfo =
		{
			{	pBodies,		"int",		"number of initial bodies"			},
			{	pRockColor,		"Color",	"display color of bodies"			},
		};
		return (theInfo);
	}

	/** Initialize the graphics elements of the gravity simulation.
	 */
	public void init()
	{
		GridBagLayout gridBagLayout;
		gridBagLayout = new GridBagLayout();
		setLayout(gridBagLayout);
		addNotify();
		resize(insets().left + insets().right + 558,insets().top + insets().bottom + 441);
		panel1 = new java.awt.Panel();
		panel1.setLayout(null);
		panel1.reshape(insets().left + 0,insets().top + 0,125,441);
		panel1.setBackground(new Color(12632256));
		GridBagConstraints gbc;
		gbc = new GridBagConstraints();
		gbc.gridx = 0;
		gbc.gridy = 0;
		gbc.weighty = 1;
		gbc.anchor = GridBagConstraints.NORTHWEST;
		gbc.fill = GridBagConstraints.VERTICAL;
		gbc.insets = new Insets(0,0,0,0);
		gridBagLayout.setConstraints(panel1, gbc);
		add(panel1);
		button3 = new java.awt.Button("Start");
		button3.reshape(10,10,80,23);
		button3.setBackground(new Color(16777215));
		panel1.add(button3);
		button4 = new java.awt.Button("Reseed");
		button4.reshape(10,70,80,23);
		button4.setBackground(new Color(16777215));
		panel1.add(button4);
		checkbox1 = new java.awt.Checkbox("Be Naughty");
		checkbox1.reshape(10,120,100,25);
		panel1.add(checkbox1);
		label1 = new java.awt.Label("Frames:");
		label1.reshape(10,165,50,15);
		label1.setFont(new Font("Dialog", Font.PLAIN, 10));
		panel1.add(label1);
		textField1 = new java.awt.TextField();
		textField1.setEditable(false);
		textField1.setText("0");
		textField1.reshape(60,165,50,16);
		textField1.setFont(new Font("Courier", Font.PLAIN, 10));
		panel1.add(textField1);
		label2 = new java.awt.Label("Rate:");
		label2.reshape(10,180,50,15);
		label2.setFont(new Font("Dialog", Font.PLAIN, 10));
		panel1.add(label2);
		textField2 = new java.awt.TextField();
		textField2.setEditable(false);
		textField2.setText("0");
		textField2.reshape(60,180,50,16);
		textField2.setFont(new Font("Courier", Font.PLAIN, 10));
		panel1.add(textField2);
		button5 = new java.awt.Button("Stop");
		button5.reshape(10,40,80,23);
		button5.setBackground(new Color(16777215));
		panel1.add(button5);
		newtonPanel1 = new java.awt.Panel();
		newtonPanel1.setLayout(new BorderLayout(0,0));
		newtonPanel1.reshape(insets().left + 125,insets().top + 0,433,441);
		newtonPanel1.setForeground(new Color(16777215));
		newtonPanel1.setBackground(new Color(0));
		gbc = new GridBagConstraints();
		gbc.gridx = 2;
		gbc.gridy = 0;
		gbc.weightx = 1;
		gbc.weighty = 1;
		gbc.anchor = GridBagConstraints.NORTHEAST;
		gbc.fill = GridBagConstraints.BOTH;
		gbc.insets = new Insets(0,0,0,0);
		gridBagLayout.setConstraints(newtonPanel1, gbc);
		add(newtonPanel1);
		newtonCanvas1 = new NewtonCanvas();
		newtonCanvas1.reshape(0,41,433,400);
		newtonCanvas1.setForeground(new Color(16777215));
		newtonCanvas1.setBackground(new Color(0));
		newtonPanel1.add("Center", newtonCanvas1);
	}

	/** Start the applet.
	 */
	public void start()
	{
		startTask();
	}

	/** Stop the applet.
	 */
	public void stop()
	{
		stopTask();
	}

	/** Start the simulation.
	 */
	public void startTask()
	{
		fTicker = new TickerThread(this, 100);
		fTicker.start();

		newtonCanvas1.startTask();
	}

	/** Stop the simulation.
	 */
	public void stopTask()
	{
		newtonCanvas1.stopTask();

		if (fTicker != null)
		{
			fTicker.stop();
			fTicker = null;
		}
	}

	/** Periodically update the frame count and frame rate displays.
	 */
	public void idle()
	{
		long frameCount = 0;

		frameCount = newtonCanvas1.getFrames();

		if (fOldFrames != frameCount)
		{
			double frameRate = newtonCanvas1.getFrameRate();
			textField1.setText(Long.toString(frameCount));
			textField2.setText((Double.toString(frameRate)).substring(0,5));
		}

		fOldFrames = frameCount;
	}

	/** Specific event handler.
	 */
	public boolean handleEvent(Event event)
	{
		if (event.target == button3 && event.id == Event.ACTION_EVENT)
		{
			button3_Clicked(event);
			return true;
		}

		if (event.target == button4 && event.id == Event.ACTION_EVENT)
		{
			button4_Clicked(event);
			return true;
		}

		if (event.target == checkbox1 && event.id == Event.ACTION_EVENT)
		{
			checkbox1_Action(event);
			return true;
		}

		if (event.target == button5 && event.id == Event.ACTION_EVENT)
		{
			button5_Clicked(event);
			return true;
		}

		if (event.id == Event.WINDOW_DESTROY)
		{
			newtonCanvas1.stopTask();
		}

		return super.handleEvent(event);
	}

	/** Put a random population of rocks in the simulation.
	 */
	public void reseed()
	{
		newtonCanvas1.reseed();
	}

	/** Handle Start actions.
	 */
	public void Start_Action(Event event)
	{
		newtonCanvas1.resume();
	}

	/** Handle Stop actions.
	 */
	public void Stop_Action(Event event)
	{
		newtonCanvas1.pause();
	}

	/** Handle reseed actions.
	 */
	public void Reseed_Action(Event event)
	{
		reseed();
	}

	/** Handle naughty actions.
	 */
	public void Naughty_Action(Event event)
	{
		boolean naughty = checkbox1.getState();
		newtonCanvas1.setNaughty(naughty);
	}

// Private static variables.

	// Names of parameters.

	private final static String pBodies = "NumBodies";
	private final static String pRockColor = "RockColor";

// Private instance variables.

	//{{DECLARE_CONTROLS
	java.awt.Panel panel1;
	java.awt.Button button1;
	java.awt.Button button2;
	java.awt.Button button3;
	java.awt.Button button4;
	java.awt.Checkbox checkbox1;
	java.awt.Label label1;
	java.awt.TextField textField1;
	java.awt.Label label2;
	java.awt.TextField textField2;
	java.awt.Button button5;
	java.awt.Panel newtonPanel1;
	NewtonCanvas newtonCanvas1;
	//}}

	TickerThread	fTicker = null;
	long			fOldFrames = 0;

// Private methods.

	/** Start button event handler.
	 */
	void button3_Clicked(Event event)
	{
		Start_Action(event);
	}

	/** Reseed button event handler.
	 */
	void button4_Clicked(Event event)
	{
		Reseed_Action(event);
	}	

	/** Naughty button event handler.
	 */
	void checkbox1_Action(Event event)
	{
		Naughty_Action(event);
	}

	/** Stop button event handler.
	 */
	void button5_Clicked(Event event)
	{
		Stop_Action(event);
	}

	/** Utility method to fetch an int from a parameter.
	 */
	private int fetchInt(String pName, int defaultValue)
	{
		String spec;
		int value;

		spec = getParameter(pName);

		if (spec != null)
		{
			try
			{
				value = Integer.parseInt(spec);
			}
			catch (NumberFormatException e)
			{
				value = defaultValue;
			}
		}
		else
		{
			value = defaultValue;
		}

		return (value);
	}

	/** Utility method to fetch a double from a parameter.
	 */
	private double fetchDouble(String pName, double defaultValue)
	{
		String spec;
		double value;

		spec = getParameter(pName);

		if (spec != null)
		{
			try
			{
				value = (Double.valueOf(spec)).doubleValue();
			}
			catch (NumberFormatException e)
			{
				value = defaultValue;
			}
		}
		else
		{
			value = defaultValue;
		}

		return (value);
	}

	/** Utility method to fetch a String from a parameter.
	 */
	private String fetchString(String pName, String defaultValue)
	{
		String spec;
		String value;

		spec = getParameter(pName);

		if (spec != null)
		{
			value = spec;
		}
		else
		{
			value = defaultValue;
		}

		return (value);
	}

	/** Utility method to fetch a Color from a parameter.
	 */
	private Color fetchColor(String pName, Color defaultValue)
	{
		String spec;
		Color value;

		spec = getParameter(pName);

		if (spec != null)
		{
			try
			{
				int r = Integer.parseInt(spec.substring(0,2));
				int g = Integer.parseInt(spec.substring(2,4));
				int b = Integer.parseInt(spec.substring(4,6));
				value =
					new Color
					(
						(float)((double)r / 99.0),
						(float)((double)g / 99.0),
						(float)((double)b / 99.0)
					);
			}
			catch (NumberFormatException e)
			{
				value = defaultValue;
			}
			catch (StringIndexOutOfBoundsException e)
			{
				value = defaultValue;
			}
		}
		else
		{
			value = defaultValue;
		}

		return (value);
	}

}
