/*** Faces **************************************************
*
*  Neal Ericsson
*  5/14/96
*
*  This is a java applet that creates a user-definable smiley face
*  This is a valuable tool for anyone needing a pick-me-up.
*
*  Input is taken from the four "Choice" menus: complete, leftEye
*	rightEye, and mouth.
*  Function calls in the "action" function implement the switch
*	statements that set the parameters for the face drawing
*	functions.
*
*  Anyone who really feels like copying this code can use it,
*       just give me some credit for it somewhere.  Enjoy.
*
*******************************************************************/

import java.awt.*;
import java.applet.Applet;

// the applet
public class faces extends Applet 
{
	// declare the four Choice menus.
	Choice complete, leftEye, rightEye, mouth; 
	// declare the many variables needed to hold the coordinates of the 
	// components of the faces and give default values.
	int mouthStartAngle = 180, mouthDurationAngle = 180, mouthX = 100,
		mouthY = 165, mouthHeight = 50, mouthWidth = 100,
		leftEyeX = 110, leftEyeY = 105, rightEyeX = 170,
		rightEyeY = 105, leftEyeHeight = 30, rightEyeHeight = 30,
		leftEyeWidth = 20, rightEyeWidth = 20, leftEyeStartAngle = 0,
		rightEyeStartAngle = 0, leftEyeDurationAngle = 360, 
		rightEyeDurationAngle = 360, leftEyeArcX, leftEyeArcY,
		leftEyeArcWidth, leftEyeArcHeight, leftEyeArcStartAngle,
		leftEyeArcDurationAngle, rightEyeArcX, rightEyeArcY,
		rightEyeArcWidth, rightEyeArcHeight, rightEyeArcStartAngle,
		rightEyeArcDurationAngle, extraMouthArcX, extraMouthArcY,
		extraMouthArcWidth, extraMouthArcHeight, 
		extraMouthArcStartAngle, extraMouthArcDurationAngle,
		extraLine1X, extraLine1Y, extraLine1X2, extraLine1Y2,
		extraLine2X, extraLine2Y, extraLine2X2, extraLine2Y2,
		extraLine3X, extraLine3Y, extraLine3X2, extraLine3Y2,
		extraLine4X, extraLine4Y, extraLine4X2, extraLine4Y2;
	// declare the panels to hold the four menus.
	Panel leftEyePanel, rightEyePanel, mouthPanel, completePanel;
	
	public void init()
	{
		// initialize the panel and add a label		
		completePanel = new Panel();
		completePanel.add(new Label("Face Type:"));
		// initialize the Choice and add the menu items to it.
		complete = new Choice();
		complete.addItem("Smiley");
		complete.addItem("Frowny");
		complete.addItem("Contempletive");
		complete.addItem("Stoned");
		complete.addItem("Suprised");
		complete.addItem("Sleepy");
 		complete.addItem("Perplexed");
 		complete.addItem("Dead");
		// add the Choice to the panel.
		completePanel.add(complete);
		// add the panel to the applet.
		add(completePanel);

		// initialize the panel and add a label		
		mouthPanel = new Panel();
		mouthPanel.add(new Label("Mouth Type:"));
		// initialize the Choice and add the menu items to it.
		mouth = new Choice();
		mouth.addItem("Normal");
		mouth.addItem("Smile");
		mouth.addItem("Frown");
		mouth.addItem("Contempletive");
		mouth.addItem("Suprised");
		mouth.addItem("Perplexed");
		mouthPanel.add(mouth);		
		// add the panel to the applet.
		add(mouthPanel);
		
		// initialize the panel and add a label.
		leftEyePanel = new Panel();
		leftEyePanel.add(new Label("Left Eye Type:"));
		// initialize the Choice and add the menu items to it.
		leftEye = new Choice();
		leftEye.addItem("Normal");
		leftEye.addItem("Happy");
		leftEye.addItem("Stoned");
		leftEye.addItem("Sleepy");
		leftEye.addItem("Dead");
		leftEyePanel.add(leftEye);		
		// add the panel to the applet.
		add(leftEyePanel);

		// initialize the panel and add a label		
		rightEyePanel = new Panel();
		rightEyePanel.add(new Label("Right Eye Type:"));
		// initialize the Choice and add the menu items to it.
		rightEye = new Choice();
		rightEye.addItem("Normal");
		rightEye.addItem("Happy");
		rightEye.addItem("Stoned");
		rightEye.addItem("Sleepy");
		rightEye.addItem("Dead");
		rightEyePanel.add(rightEye);		
		// add the panel to the applet.
		add(rightEyePanel);
		
		// validate it.
		validate();
	}

	/* paint. the function that creates the faces.
	 * input: any or all of the integers listed in the variable 
	 *	  declarations at the beginning of the code.
	 * output: the graphic display of the face
	 * update the image on the screen with repaint();.
	 */
	public void paint (Graphics g)
	{
		// color of the face
		g.setColor(Color.yellow);	
		// draw the whole face
		g.fillOval(50, 50, 200, 200);
		// the color of the facial parts
		g.setColor(Color.black);
		// draw the mouth
		g.drawArc(mouthX, mouthY, mouthWidth, mouthHeight,
			mouthStartAngle, mouthDurationAngle);
		// draw the left eye
		g.fillArc(leftEyeX, leftEyeY, leftEyeWidth, leftEyeHeight,
			leftEyeStartAngle, leftEyeDurationAngle);
		// draw the right eye
		g.fillArc(rightEyeX, rightEyeY, rightEyeWidth, rightEyeHeight,
			rightEyeStartAngle, rightEyeDurationAngle);
		// draw an arc for a closed left eye
		g.drawArc(leftEyeArcX, leftEyeArcY, leftEyeArcWidth,
			leftEyeArcHeight, leftEyeArcStartAngle,
			leftEyeArcDurationAngle);
		// draw an arc for a closed right eye
		g.drawArc(rightEyeArcX, rightEyeArcY, rightEyeArcWidth,
			rightEyeArcHeight, rightEyeArcStartAngle,
			rightEyeArcDurationAngle);
		// draw the extra arc sometimes needed for the mouth
		g.drawArc(extraMouthArcX, extraMouthArcY, extraMouthArcWidth, 
			extraMouthArcHeight, extraMouthArcStartAngle,
			extraMouthArcDurationAngle);
		// draw the lines for the dead eyes
		g.drawLine(extraLine1X, extraLine1Y, extraLine1X2, 
			extraLine1Y2);
		g.drawLine(extraLine2X, extraLine2Y, extraLine2X2,
			extraLine2Y2);
		g.drawLine(extraLine3X, extraLine3Y, extraLine3X2,
			extraLine3Y2);
		g.drawLine(extraLine4X, extraLine4Y, extraLine4X2,
			extraLine4Y2);
	}


	/* chooseAFace. the function that sends the criteria to "paint"
	 *		for complete pre-fab faces
	 * input: an int num (determined by the user selection from
	 *	  Choice menu "complete")
	 * result: updates the face on the screen
	 */
	void chooseAFace(int num)
	{
		switch(num)
		{			
			case 0: // smile face
			{
				mouthStartAngle = 180;
				mouthDurationAngle = 180;
				leftEyeArcDurationAngle =
					rightEyeArcDurationAngle =
					extraMouthArcDurationAngle = 0;
				mouthX = 100;
				mouthY = 165;
				mouthHeight = 50;
				mouthWidth = 100;
				leftEyeX = 110;
				leftEyeY = 105;
				rightEyeX = 170;
				rightEyeY = 105;
				leftEyeHeight = rightEyeHeight = 30;
				leftEyeWidth = rightEyeWidth = 20;
				leftEyeStartAngle = rightEyeStartAngle = 0;
				leftEyeDurationAngle = 
					rightEyeDurationAngle = 360;
				extraLine1X = extraLine1Y = extraLine1X2 =
					extraLine1Y2 = extraLine2X =
					extraLine2Y = extraLine2X2 = 
					extraLine2Y2 = extraLine3X =
					extraLine3Y = extraLine3X2 =
					extraLine3Y2 = extraLine4X =
					extraLine4Y = extraLine4X2 = 
					extraLine4Y2 = 0;
				repaint();
				break;
			}
			case 1:  // frown face
			{
				mouthStartAngle = 0;
				mouthDurationAngle = 180;
				leftEyeArcDurationAngle =
					rightEyeArcDurationAngle =
					extraMouthArcDurationAngle = 0;
				mouthX = 100;
				mouthY = 185;
				mouthHeight = 50;
				mouthWidth = 100;
				leftEyeX = 110;
				leftEyeY = 105;
				rightEyeX = 170;
				rightEyeY = 105;
				leftEyeHeight = rightEyeHeight = 30;
				leftEyeWidth = rightEyeWidth = 20;
				leftEyeStartAngle = rightEyeStartAngle = 0;
				leftEyeDurationAngle =
					rightEyeDurationAngle = 360;
				extraLine1X = extraLine1Y = extraLine1X2 =
					extraLine1Y2 = extraLine2X =
					extraLine2Y = extraLine2X2 = 
					extraLine2Y2 = extraLine3X =
					extraLine3Y = extraLine3X2 =
					extraLine3Y2 = extraLine4X = 
					extraLine4Y = extraLine4X2 =
					extraLine4Y2 = 0;
				repaint();
				break;
			}
			case 2:  // contempletive face
			{
				mouthStartAngle = 180;
				mouthDurationAngle = 180;
				leftEyeArcDurationAngle =
					rightEyeArcDurationAngle =
					extraMouthArcDurationAngle = 0;
				mouthX = 100;
				mouthY = 200;
				mouthHeight = 1;
				mouthWidth = 100;
				leftEyeX = 110;
				leftEyeY = 105;
				rightEyeX = 170;
				rightEyeY = 105;
				leftEyeHeight = rightEyeHeight = 30;
				leftEyeWidth = rightEyeWidth = 20;
				leftEyeStartAngle = rightEyeStartAngle = 0;
				leftEyeDurationAngle =
					rightEyeDurationAngle = 360;
				extraLine1X = extraLine1Y = extraLine1X2 =
					extraLine1Y2 = extraLine2X =
					extraLine2Y = extraLine2X2 = 
					extraLine2Y2 = extraLine3X =
					extraLine3Y = extraLine3X2 =
					extraLine3Y2 = extraLine4X = 
					extraLine4Y = extraLine4X2 = 
					extraLine4Y2 = 0;
				repaint();
				break;
			}
			case 3:  // stoned face
			{
				mouthStartAngle = 180;
				mouthDurationAngle = 180;
				leftEyeArcDurationAngle =
					rightEyeArcDurationAngle =
					extraMouthArcDurationAngle = 0;
				mouthX = 100;
				mouthY = 165;
				mouthHeight = 50;
				mouthWidth = 100;
				leftEyeX = 110;
				leftEyeY = 105;
				rightEyeX = 170;
				rightEyeY = 105;
				leftEyeHeight = rightEyeHeight = 30;
				leftEyeWidth = rightEyeWidth = 20;
				leftEyeStartAngle = rightEyeStartAngle = 180;
				leftEyeDurationAngle =
					rightEyeDurationAngle = 180;
				extraLine1X = extraLine1Y = extraLine1X2 =
					extraLine1Y2 = extraLine2X = 
					extraLine2Y = extraLine2X2 = 
					extraLine2Y2 = extraLine3X =
					extraLine3Y = extraLine3X2 =
					extraLine3Y2 = extraLine4X = 
					extraLine4Y = extraLine4X2 =
					extraLine4Y2 = 0;
				repaint();
				break;
			}
			case 4:  // suprised face
			{
				mouthStartAngle =180;
				mouthDurationAngle = 360;
				leftEyeArcDurationAngle =
					rightEyeArcDurationAngle =
					extraMouthArcDurationAngle = 0;
				mouthX = 125;
				mouthY = 160;
				mouthHeight = 50;
				mouthWidth = 50;
				leftEyeX = 110;
				leftEyeY = 105;
				rightEyeX = 170;
				rightEyeY = 105;
				leftEyeHeight = rightEyeHeight = 30;
				leftEyeWidth = rightEyeWidth = 20;
				leftEyeStartAngle = rightEyeStartAngle = 0;
				leftEyeDurationAngle =
					rightEyeDurationAngle = 360;
				extraLine1X = extraLine1Y = extraLine1X2 =
					extraLine1Y2 = extraLine2X =
					extraLine2Y = extraLine2X2 = 
					extraLine2Y2 = extraLine3X =
					extraLine3Y = extraLine3X2 =
					extraLine3Y2 = extraLine4X =
					extraLine4Y = extraLine4X2 =
					extraLine4Y2 = 0;
				repaint();
				break;
			}
			case 5:  // sleepy face
			{
				mouthStartAngle = 180;
				mouthDurationAngle = 180;
				leftEyeArcDurationAngle = 
					rightEyeArcDurationAngle =
					extraMouthArcDurationAngle = 0;
				mouthX = 100;
				mouthY = 165;
				mouthHeight = 50;
				mouthWidth = 100;
				leftEyeArcX = 110;
				leftEyeArcY = 105;
				rightEyeArcX = 170;
				rightEyeArcY = 105;
				leftEyeArcHeight = rightEyeArcHeight = 30;
				leftEyeArcWidth = rightEyeArcWidth = 20;
				leftEyeArcStartAngle =
					rightEyeArcStartAngle = 180;
				leftEyeArcDurationAngle =
					rightEyeArcDurationAngle = 180;
				leftEyeDurationAngle =
					rightEyeDurationAngle = 0;
				extraLine1X = extraLine1Y = extraLine1X2 =
					extraLine1Y2 = extraLine2X =
					extraLine2Y = extraLine2X2 = 
					extraLine2Y2 = extraLine3X =
					extraLine3Y = extraLine3X2 =
					extraLine3Y2 = extraLine4X =
					extraLine4Y = extraLine4X2 =
					extraLine4Y2 = 0;
				repaint();
				break;
			}
			case 6:  // perplexed face
			{
				mouthStartAngle = 180;
				mouthDurationAngle = 180;
				extraMouthArcStartAngle = 0;
				extraMouthArcDurationAngle = 180;
				leftEyeArcDurationAngle =
					rightEyeArcDurationAngle = 0;
				mouthX = 100;
				extraMouthArcX = 150;
				mouthY = extraMouthArcY = 175;
				leftEyeArcX = 150;
				leftEyeArcY = 175;
				mouthHeight = extraMouthArcHeight = 25;
				mouthWidth = extraMouthArcWidth = 50;
				leftEyeX = 110;
				leftEyeY = 105;
				rightEyeX = 170;
				rightEyeY = 105;
				leftEyeHeight = rightEyeHeight = 30;
				leftEyeWidth = rightEyeWidth = 20;
				leftEyeStartAngle = rightEyeStartAngle = 0;
				leftEyeDurationAngle = 
					rightEyeDurationAngle = 360;
				extraLine1X = extraLine1Y = extraLine1X2 =
					extraLine1Y2 = extraLine2X =
					extraLine2Y = extraLine2X2 = 
					extraLine2Y2 = extraLine3X =
					extraLine3Y = extraLine3X2 =
					extraLine3Y2 = extraLine4X =
					extraLine4Y = extraLine4X2 =
					extraLine4Y2 = 0;
				repaint();
				break;
			}
			case 7:  // dead face
			{
				mouthStartAngle = 180;
				mouthDurationAngle = 180;
				leftEyeArcDurationAngle =
					rightEyeArcDurationAngle = 
					extraMouthArcDurationAngle = 0;
				mouthX = 100;
				mouthY = 165;
				mouthHeight = 50;
				mouthWidth = 100;
				leftEyeDurationAngle =
					rightEyeDurationAngle = 0;
				extraLine1X = extraLine2X = 110;
				extraLine1Y = extraLine3Y = extraLine2Y2 =
					extraLine4Y2 = 105;
				extraLine1X2 = extraLine2X2 = 130;
				extraLine1Y2 = extraLine2Y = extraLine3Y2 =
					extraLine4Y = 135;
				extraLine3X = extraLine4X = 170;
				extraLine3X2 = extraLine4X2 = 190;
				repaint();
				break;
			}
			default:  // default -> smile face
			{
				mouthStartAngle = 0;
				mouthDurationAngle = 180;
				leftEyeArcDurationAngle =
					rightEyeArcDurationAngle = 
					extraMouthArcDurationAngle = 0;
				mouthX = 100;
				mouthY = 165;
				mouthHeight = 50;
				mouthWidth = 100;
				leftEyeX = 110;
				leftEyeY = 105;
				rightEyeX = 170;
				rightEyeY = 105;
				leftEyeHeight = rightEyeHeight = 30;
				leftEyeWidth = rightEyeWidth = 20;
				leftEyeStartAngle = rightEyeStartAngle = 0;
				leftEyeDurationAngle =
					leftEyeDurationAngle = 360;
				extraLine1X = extraLine1Y = extraLine1X2 =
					extraLine1Y2 = extraLine2X =
					extraLine2Y = extraLine2X2 = 
					extraLine2Y2 = extraLine3X =
					extraLine3Y = extraLine3X2 =
					extraLine3Y2 = extraLine4X = 
					extraLine4Y = extraLine4X2 =
					extraLine4Y2 = 0;
				repaint();
				break;
			}			
		}
	}	


	/* chooseALeftEye. the function that sends the criteria to "paint"
	 *		   for creating specific eye types
	 * input: an int num (determined by the user selection from "Choice"
	 *	  menu "leftEye")
	 * result: updates the face on the screen
	 */
	void chooseALeftEye(int num)
	{
		switch(num)
		{
			case 0: // normal Eye
			{
				break;
			}	
			case 1: // Happy Left Eye
			{
				leftEyeX = 110;
				leftEyeY = 105;
				leftEyeHeight = 30;
				leftEyeWidth = 20;
				leftEyeStartAngle = 0;
				leftEyeDurationAngle = 360;
				leftEyeArcDurationAngle = 0;
				extraLine1X = extraLine2X = extraLine1Y =
					extraLine2Y2 = extraLine1X2 =
					extraLine2X2 = extraLine1Y2 =
					extraLine2Y = 0;
				repaint();
				break;
			}	
			case 2: // Stoned Left Eye
			{
				leftEyeX = 110;
				leftEyeY = 105;
				leftEyeHeight = 30;
				leftEyeWidth = 20;
				leftEyeStartAngle =180;
				leftEyeDurationAngle = 180;
				leftEyeArcDurationAngle = 0;
				extraLine1X = extraLine2X = extraLine1Y =
					extraLine2Y2 = extraLine1X2 =
					extraLine2X2 = extraLine1Y2 =
					extraLine2Y = 0;
				repaint();
				break;
			}	
			case 3: // Sleepy Left Eye
			{
				leftEyeArcX = 110;
				leftEyeArcY = 105;
				leftEyeArcHeight = 30;
				leftEyeArcWidth = 20;
				leftEyeArcStartAngle = 180;
				leftEyeArcDurationAngle = 180;
				leftEyeDurationAngle = 0;
				extraLine1X = extraLine2X = extraLine1Y =
					extraLine2Y2 = extraLine1X2 =
					extraLine2X2 = extraLine1Y2 =
					extraLine2Y = 0;
				repaint();
				break;
			}	
			case 4: // Dead Left Eye
			{
				extraLine1X = extraLine2X = 110;
				extraLine1Y = extraLine2Y2 = 105;
				extraLine1X2 = extraLine2X2 = 130;
				extraLine1Y2 = extraLine2Y =  135;
				leftEyeArcDurationAngle = 0;
				leftEyeDurationAngle = 0;
				repaint();
				break;
			}	
			default: // default to selection for complete face
			{
				break;
			}
		}
	}		 
       

	/* chooseARightEye. the function that sends the criteria to "paint" 
	 *		    for creating specific eye types
	 * input: an int num (determined by the user selection from Choice
	 *	  menu "rightEye")
	 * result: updates the face on the screen.
	 */
	void chooseARightEye(int num)
	{
		switch(num)
		{
			case 0: // normal Right Eye
			{
				break;
			}	
			case 1: //Happy Right Eye
			{
				rightEyeX = 170;
				rightEyeY = 105;
				rightEyeHeight = 30;
				rightEyeWidth = 20;
				rightEyeStartAngle = 0;
				rightEyeDurationAngle = 360;
				rightEyeArcDurationAngle = 0;
				extraLine3X = extraLine4X = extraLine3Y =
					extraLine4Y2 = extraLine3X2 =
					extraLine4X2 = extraLine3Y2 =
					extraLine4Y = 0;
				repaint();
				break;
			}	
			case 2: // Stoned Right Eye
			{
				rightEyeX = 170;
				rightEyeY = 105;
				rightEyeHeight = 30;
				rightEyeWidth = 20;
				rightEyeStartAngle =180;
				rightEyeDurationAngle = 180;
				rightEyeArcDurationAngle = 0;
				extraLine3X = extraLine4X = extraLine3Y =
					extraLine4Y2 = extraLine3X2 =
					extraLine4X2 = extraLine3Y2 =
					extraLine4Y = 0;
				repaint();
				break;
			}	
			case 3: // Sleepy Right Eye
			{
				rightEyeArcX = 170;
				rightEyeArcY = 105;
				rightEyeArcHeight = 30;
				rightEyeArcWidth = 20;
				rightEyeArcStartAngle = 180;
				rightEyeArcDurationAngle = 180;
				rightEyeDurationAngle = 0;
				extraLine3X = extraLine4X = extraLine3Y =
					extraLine4Y2 = extraLine3X2 =
					extraLine4X2 = extraLine3Y2 =
					extraLine4Y = 0;
				repaint();
				break;
			}	
			case 4: // Dead Right Eye
			{
				rightEyeArcDurationAngle = 0;
				rightEyeDurationAngle = 0;
				extraLine3X = extraLine4X = 170;
				extraLine3Y = extraLine4Y2 = 105;
				extraLine3X2 = extraLine4X2 = 190;
				extraLine3Y2 = extraLine4Y =  135;
				repaint();
				break;
			}	
			default: // default to selection for complete face
			{
				break;
			}
		}
	}		 


	/* chooseAMouth. the function that sends the criteria to "paint"
	 *		 for creating specific mouth types
	 * input: an int num (determined by the user selection from "Choice"
	 *	  menu "mouth")
	 * result: updates the face on the screen
	 */
	void chooseAMouth(int num)
	{
		switch(num)
		{
			case 0: // normal Eye
			{
				break;
			}	
			case 1: // smile mouth
			{
				mouthStartAngle = 180;
				mouthDurationAngle = 180;
				extraMouthArcDurationAngle = 0;
				mouthX = 100;
				mouthY = 165;
				mouthHeight = 50;
				mouthWidth = 100;
				repaint();
				break;
			}
			case 2: // frown mouth
			{
				mouthStartAngle = 0;
				mouthDurationAngle = 180;
				extraMouthArcDurationAngle = 0;
				mouthX = 100;
				mouthY = 185;
				mouthHeight = 50;
				mouthWidth = 100;
				repaint();
				break;
			}
			case 3: // contempletive mouth
			{
				mouthStartAngle = 180;
				mouthDurationAngle = 180;
				extraMouthArcDurationAngle = 0;
				mouthX = 100;
				mouthY = 200;
				mouthHeight = 1;
				mouthWidth = 100;
				repaint();
				break;
			}
			case 4: // suprised mouth
			{
				mouthStartAngle =180;
				mouthDurationAngle = 360;
				extraMouthArcDurationAngle = 0;
				mouthX = 125;
				mouthY = 160;
				mouthHeight = 50;
				mouthWidth = 50;
				repaint();
				break;
			}
			case 5: // perplexed mouth
			{
				mouthStartAngle = 180;
				mouthDurationAngle = 180;
				extraMouthArcStartAngle = 0;
				extraMouthArcDurationAngle = 180;
				mouthX = 100;
				extraMouthArcX = 150;
				mouthY = extraMouthArcY = 175;
				mouthHeight = extraMouthArcHeight = 25;
				mouthWidth = extraMouthArcWidth = 50;
				repaint();
				break;
			}
			default: // default to selection for complete face
			{
				break;
			}
		}
	}
			

	// action. the function that does the work
	public boolean action(Event e, Object arg) 
	{
		if (e.target instanceof Choice)
		{
			chooseAFace(complete.getSelectedIndex());
			chooseALeftEye(leftEye.getSelectedIndex());
			chooseARightEye(rightEye.getSelectedIndex());
			chooseAMouth(mouth.getSelectedIndex());
			return true;
		}
		return false;
	}
}