import java.util.*;
import java.io.*;
import java.awt.*;
import java.applet.Applet;
import java.awt.event.*;


//************************************** CLASS  GRAPH ****************************************)
public class Graph extends Applet
{
   Graph_GUI gui = new Graph_GUI(this);
   public Bag polies = new Bag(); 
   public Stack zoom_stack = new Stack();
   public Color linecolor = Color.black; 
   
//Eq_entry variables
   public int link_status = 0;
   public Link eq_link;
   public Function func1;
   public Function func2;
   
//viewing range variables
   private double x_left = -10;
   private double x_right = 10;
   private double y_minimum = -10;
   private double y_maximum = 10;
   
//evaluation range variables
   private double x_start = -10;
   private double x_end = 10;

//zoom control variable
   public boolean zoom_enable = false;
   
//getPoint control variable
   public boolean get_point_enable = false;
 
 
//++++++++++++++++++++++++++++++++++++++ GRAPH METHODS +++++++++++++++++++++++++++++++++++++++)
 

//____________________________________GUI related methods_____________________________________)
   
//init method calls init in Graph_GUI class   
   public void init() 
   {  
     gui.init(); 
   }
   
//repaint calls repaint in Graph_GUI class
   public void repaint()
   {   gui.repaint();
   }

   
		
//update_textfield calls update_textfield in Graph_GUI class
  public void update_textfield(String text)
  {   gui.update_textfield(text);
  }
 
  public void set_EQ_text(String newtext)
  {	  gui.set_EQ_text(newtext);
  }
  
//methods to retrieve data from GUI
   
   //viewing range window  
   
   public double retrieve_x_left()
   {  return gui.retrieve_x_left();
   }
   
   public double retrieve_x_right()
   {  return gui.retrieve_x_right();
   }
   
   public double retrieve_y_min()
   {  return gui.retrieve_y_min();
   }
   
   public double retrieve_y_max()
   {  return gui.retrieve_y_max();
   }  
       
//equation entry window
   
   public double get_range_min()
   {  return gui.get_range_min();
   }
   
   public double get_range_max()
   {  return gui.get_range_max();
   }
   
   public double get_coef1()
   {   return gui.get_coef1();
   }
   
   public double get_pow1()
   {   return gui.get_pow1();
   }
   
   public double get_coef2()
   {   return gui.get_coef2();
   }
   
   public double get_pow2()
   {   return gui.get_pow2();
   }
   
   public double get_coef3()
   {   return gui.get_coef3();
   }
   
   public double get_pow3()
   {   return gui.get_pow3();
   }
   
   public double get_pow4()
   {   return gui.get_pow4();
   }
   
   public double get_coef4()
   {   return gui.get_coef4();
   }
   
   public double get_pow5()
   {   return gui.get_pow5();
   }
   
   public double get_coef5()
   {   return gui.get_coef5();
   }
    
   public double retrieve_x_start()
   {   return gui.retrieve_x_start();
   }
   
   public double retrieve_x_end()
   {   return gui.retrieve_x_end();
   }
   
//trig methods access
   
   public double retrieve_sincoef()
   {   return gui.retrieve_sincoef();
   }
   
   public double retrieve_sin_xcoef()
   {   return gui.retrieve_sin_xcoef();
   }
   
   public double retrieve_coscoef()
   {   return gui.retrieve_coscoef();
   }
   
   public double retrieve_cos_xcoef()
   {   return gui.retrieve_cos_xcoef();
   }
   
   public double retrieve_tancoef()
   {   return gui.retrieve_tancoef();
   }
   
   public double retrieve_tan_xcoef()
   {   return gui.retrieve_tan_xcoef();
   }   
   
   public int get_canvas_height()
   {	return gui.canvas_height();
   }
   
   public int get_canvas_width()
   {  	return gui.canvas_width();
   }

//exp methods access
   public double retrieve_expcoef()
   {   return gui.retrieve_expcoef();
   }
   
   public double retrieve_exp_xcoef()
   {   return gui.retrieve_exp_xcoef();
   }   
  

//window visibility and accessability control methods
   
   public void make_EQ_entry_visible()
   {   gui.make_eq_entry_visible();
   }
   
   public void make_EQ_entry_invisible()
   {   gui.make_eq_entry_invisible();
   }
   
   public void make_range_entry_visible()
   {   gui.make_range_entry_visible();
   }
   
   public void make_range_entry_invisible()
   {   gui.make_range_entry_invisible();
   }
   
   public void make_Main_visible()
   {   gui.make_Main_visible();
   }

   public void make_Main_invisible()
   {   gui.make_Main_invisible();
   }
   
   public void make_5term_visible()
   {   gui.make_5term_visible();
   }

   public void make_5term_invisible()
   {   gui.make_5term_invisible();
   }
   
   public void make_SIN_visible()
   {   gui.make_SIN_visible();
   }
   
   public void make_SIN_invisible()
   {   gui.make_SIN_invisible();
   }
   
   public void make_COS_visible()
   {   gui.make_COS_visible();
   }
   
   public void make_COS_invisible()
   {   gui.make_COS_invisible();
   }
   public void make_TAN_visible()
   {   gui.make_TAN_visible();
   }
   
   public void make_TAN_invisible()
   {   gui.make_TAN_invisible();
   }   

   public void make_EXP_visible()
   {   gui.make_EXP_visible();
   }
   
   public void make_EXP_invisible()
   {   gui.make_EXP_invisible();
   }   
    
   public void make_help_visible()
   {   gui.make_help_visible();
   }

   public void make_help_invisible()
   {   gui.make_help_invisible();
   }
   
   
   public void enable_submit()
   {   gui.enable_submit();
   }
   
   public void disable_submit()
   {   gui.disable_submit();
   }
	
   public void enable_composites()
   {   gui.enable_composites();
   }
   
   public void disbable_composites()
   {   gui.disable_composites();
   }


//____________________________________graphing related methods____________________________)
                
//methods for controlling range
   
   public void restore_view_range_defaults()
   {   x_left = -10;
       x_right = 10;
       y_minimum = -10;
       y_maximum = 10;
	   zoom_stack.removeAllElements();
       gui.restore_view_range_defaults();
   }

   
   public void set_x_left(double new_x)
   {   x_left = new_x;
	   gui.set_x_left( new_x);
   }
   
   public void set_x_right(double new_x)
   {   x_right = new_x;
	   gui.set_x_right( new_x);
   }
   
   public void set_y_minimum(double new_y)
   {   y_minimum = new_y;
	   gui.set_y_min( new_y);
   }
   
   public void set_y_maximum(double new_y)
   {   y_maximum = new_y;
	   gui.set_y_max( new_y);
   }
   
   public void set_x_start(double new_x)
   {   x_start = new_x;
   }
   
   public void set_x_end(double new_x)
   {   x_end = new_x;
   }
   
   public double get_x_right()
   {   return x_right;
   }
   
   public double get_x_left()
   {   return x_left;
   }
   
   public double get_y_minimum()
   {   return y_minimum;
   }
   
   public double get_y_maximum()
   {   return y_maximum;
   }
   
   public double get_x_start()
   {   return x_start;
   }
   
   public double get_x_end()
   {   return x_end;
   }


   
   
//getPoint takes as input xy coordinates on the drawarea and computes the relative
// x,y coordinates for the graph
   public Point getPoint(int x, int y)
   {
	double a = gui.canvas_width();
	double b = gui.canvas_height();
	double x_dist = Math.abs(x_right - x_left);
	double y_dist = Math.abs(y_maximum - y_minimum);
	double x_zero =  a*(1-x_right/x_dist);
    	double y_zero =  b*y_maximum/y_dist;
	double newX = x - x_zero;
	double newY = y_zero - y;
	newX = newX*(x_dist/a);
	newY = newY*(y_dist/b);
	Point temp = new Point(newX, newY);
	return temp;
   }	

//zoom method
//accepts as input the x,y coordinates of a point relative to the graph where the user 
//clicked.  The original point was translated using the apple.getPoint method. 

   public void zoom_in_at(Point temp)
   {    
	double x_dist = Math.abs(x_right - x_left);
	double y_dist = Math.abs(y_maximum - y_minimum);

	//we know relative to graph, where the click occured.
	//so calculate a new viewing range for the graph to be redrawn.
	//the blow up is X2.  so new x_left is newX - 1/4 x_dist
	//new x_right is newX + 1/4 x_dist...etc.
	
	double X = temp.getX();
	double Y = temp.getY();
	
	double newxl = (X - (1/4.0) * x_dist);
	double newxr = (X + (1/4.0) * x_dist); 
	double newymin = (Y - (1/4.0) * y_dist);
	double newymax = (Y + (1/4.0) * y_dist);
	

	//save old viewing range
	Zoom_Record old_zoom = new Zoom_Record(x_left,x_right,y_minimum,y_maximum);
	zoom_stack.push(old_zoom);

	//set new viewing range

	set_x_left(newxl);
	set_x_right(newxr);
	set_y_minimum(newymin);
	set_y_maximum(newymax);
	repaint();
   }
   
   
   public void zoom_out_at(Point temp)
   {   
	double x_dist = Math.abs(x_right - x_left);
	double y_dist = Math.abs(y_maximum - y_minimum);
	
	double X = temp.getX();
	double Y = temp.getY();
		
	//know relative to graph, where the click occured.
	//so calculate a new viewing range for the graph to be redrawn.
	//the range is X2.  so new x_left is newX - x_dist
	//new x_right is newX + x_dist...etc.
	
	double newxl = (X - x_dist);
	double newxr = (X + x_dist); 
	double newymin = (Y - y_dist);
	double newymax = (Y + y_dist);
	

	//save old viewing range
	Zoom_Record old_zoom = new Zoom_Record(x_left,x_right,y_minimum,y_maximum);
	zoom_stack.push(old_zoom);

	//set new viewing range

	set_x_left(newxl);
	set_x_right(newxr);
	set_y_minimum(newymin);
	set_y_maximum(newymax);
	repaint();
    }
    
    
   
   public void zoom_back()
	   //assumes that zoom_stack is not empty.

   {   Zoom_Record old = (Zoom_Record) zoom_stack.pop();
	   set_x_left( old.get_xl());
	   set_x_right( old.get_xr());
	   set_y_minimum( old.get_yb());
	   set_y_maximum( old.get_yt());
	   gui.set_x_left( old.get_xl());
	   gui.set_x_right( old.get_xr());
	   gui.set_y_min( old.get_yb());
	   gui.set_y_max( old.get_yt());
	   repaint();
   }
   

   //clears polynomial factor and coefficients text areas.
   //just calls method in GUI.
   public void reset_poly_fields()
   {   gui.reset_poly_fields();
   }
   

//methods for generating graphs
   

   // Step is used in determining the step used in evaluating the equations.
   // i.e it designates the number of points to be used in the vector representing the equations.
   public double step()
   {   return (x_end - x_start)/5000;	//5,000 points in each equation.
   }
   
    
   public void generate_5_term_polynomial(double acoef,double apow, double bcoef, double bpow,double ccoef,
                                           double cpow, double dcoef,double dpow, double ecoef, double epow)
   {   Polyline tempPoly = new Polyline();   
       for (double x = x_start; x<x_end; x = x + step() )
       {   //look for negative x values inputted into a power less then 1
       if ( !( (x<0)&&( (apow<1)&&(apow!=0)||(bpow<1)&&(bpow!=0)||(cpow<1)&&(cpow!=0)||(dpow<1)&&(dpow!=0)||(epow<1)&&(epow!=0) ) ) )       
          {  Point temp;   
             double y = (acoef * Math.pow(x,apow) + bcoef * Math.pow(x,bpow) + ccoef * Math.pow(x,cpow)
                      + dcoef * Math.pow(x,dpow) + ecoef * Math.pow(x,epow) );
             temp = new Point(x,y);
             tempPoly.addPoint(temp);
          }   
          
       }
       polies.add_poly(tempPoly);
   }
   
   public void generate_function(Function obj)
   {   Polyline tempPoly = new Polyline();
	   for (double x = x_start; x <= x_end; x = x + step())
	   {   Point temp;
	       double y = obj.evaluate(x);
		   temp = new Point(x,y);
		   tempPoly.addPoint(temp);
	   }
	   polies.add_poly(tempPoly);
   }

   public void setup_link(char linktype)
   {	eq_link = new Link(linktype);
		gui.disable_composites();
		link_status = 1;
   }

   public void generate_link()
   {	Polyline tempPoly = new Polyline();
		for (double x = x_start; x<=x_end; x = x + step())
		{	double y = eq_link.evaluate_link(func1,func2,x);
			Point temp = new Point(x,y);
			tempPoly.addPoint(temp);
		}		
		polies.add_poly(tempPoly);
   }
   
   
   public void clear_graph()
   {  polies.remove_all_polies();
   }
 


//_______________________________HELP FUNCTIONS___________________________________________)


	public void help_on_Eq()
	{   gui.help_on_Eq();
	}

	public void help_on_Range()
	{   gui.help_on_Range();
	}

	public void help_on_Clear()
	{	gui.help_on_Clear();
	}
	
	public void help_on_Zoom()
	{	gui.help_on_Zoom();
	}

	public void help_on_getpoint()
	{	gui.help_on_getpoint();
	}



}  //Graph

class Zoom_Record{
	private double xl;
	private double xr;
	private double yt;
	private double yb;

	public Zoom_Record(double XL, double XR, double YB, double YT)
	{  xl = XL;  xr = XR; yt = YT; yb = YB;
	}

	public void set_xl(double new_xl)
	{  xl = new_xl;
	}

	public void set_xr(double new_xr)
	{  xr = new_xr;
	}

	public void set_yt(double new_yt)
	{  yt = new_yt;
	}

	public void set_yb(double new_yb)
	{  yb = new_yb;
	}

	public double get_xl()
	{  return xl;
	}

	public double get_xr()
	{  return xr;
	}

	public double get_yt()
	{  return yt;
	}

	public double get_yb()
	{  return yb;
	}
}

class Point { 
    private double x,y;	//coordinates
     
    //default constructor
    public Point () { setPoint(0,0);}
    
    //Constructor 
    public Point(double a, double b) { setPoint (a,b);}	 
	
	//copy constructor 
	public Point(Point source)	
	{ double a = source.getX();
	  double b = source.getY();
	  setPoint(a,b);
	}

    //get x-coordinate
    public double getX()  { return x;}
    
    //get y-coordinate
    public double getY()  { return y;}
    
    //set x and y coordinates of a point.
    public void setPoint(double a, double b) 
    {    
       x = a;
       y = b;
    }
    
    
    //following method takes a point and scales it to fit into the graphing area.
    //a is the horizontol pixel size of viewing area
    //b is the vertical pixel size of the viewing area
    //x_dist is the viewing range accross the x axis
    //y_dist is the viewing range accross the y axis
    //x_right is the maximum of the viewing range
    //y_max is the maximum of the viewing range.
    
    public void scale(double a , double b,double x_dist,double y_dist,double x_right, double y_max) 
    {   double c;
        double d;
        
       
        //scale onto the a graph 
        
        x = x * a/x_dist;
        y = y * b/y_dist;
        
       
        //orient curve onto axis
        
        double x_zero =  (a * (1 - x_right / x_dist)) ;
        double y_zero =  (b *  y_max / y_dist );
   
        c = x + x_zero;    
        d = (y_zero - y );  
        x = c;
        y = d;
         
        
       
    }
        
}



class Polyline{ 
	
   public static Color linecolor = Color.black;
	
   public Vector points ;  //vector to hold collection of points.
   public Color color = Color.black;
   private int current = 0;      //keeps track of the next point to be outputted.
   
   
   //default constructor
   public Polyline()
   { points = new Vector();
     current = 0;
	 color = nextColor();
   }

   //constructor with initial point
   public Polyline( Point a)
   {   points = new Vector();
       points.addElement(a);
	   current = 0;
	   color = nextColor();
   }
   //copy constructor

   public Polyline( Polyline source)
   {    color = source.color;
	    points = new Vector();
        while (source.has_another())	
	{  Point temp = new Point(source.get_next());
	   addPoint(temp);
	}
	source.reset_current();
	reset_current();
   }
   
   
   public Color nextColor()
   {   if (linecolor == Color.black) 
	   {	linecolor = Color.cyan;
			return Color.cyan;
	   }
	   
	   else if (linecolor == Color.cyan)
	   {	linecolor = Color.gray;
			return Color.gray;
	   }
	   else if (linecolor == Color.gray)
	   {	linecolor = Color.green;
			return Color.green;
	   }
	   else if (linecolor == Color.green)
	   {	linecolor = Color.magenta;
			return Color.magenta;
	   }
	  
	   else  
	   {	linecolor = Color.black;
			return Color.black;
	   }
   }
	
	   
   public boolean isEmpty()
   {   return points.isEmpty();
   }
	   
   public boolean has_another()
   {   return (current <points.size());
   }
   
   public void reset_current()
   {   current = 0;
   }
   
   //add new point to Polyline
   public void addPoint( Point a)
   {   points.addElement(a);
   }
   
   //get next point
   public Point get_next()
   {  Point temp = (Point) points.elementAt(current);
      current ++; 
      return  temp;
   }
   
   public void remove_all_points()
   {   points.removeAllElements();
   }
   
   //scale and orient collection of points to the graph.
   //int x = horizontal size of drawing area.
   //int y = vertical size of drawing area.
   
   public void scale(int x,int y,double x_dist, double y_dist,double x_right, double y_max)
   {   
       if (!points.isEmpty())
       while (has_another())
       {   get_next().scale(x,y,x_dist,y_dist,x_right,y_max);
       }
       current = 0;
   }
   
   
}


class Bag
{   public Vector poly_collection;
    private int counter = 0;
   
    public Bag()
    {   poly_collection = new Vector(10);
    }

    //copy constructor
	public Bag(Bag source)
    {  poly_collection = new Vector(10); 
       while (source.has_another())
		{	Polyline temp = new Polyline(source.get_next());		       
			add_poly(temp);
		}
			source.reset_counter();	//reset counter of source bag.
			reset_counter();	//ensure counter of new bag is at 0
		
				
	}

    public Polyline get_next()
    {   Polyline temp =  (Polyline) poly_collection.elementAt(counter); 
        counter ++;
        return temp;
    }
    
    public void reset_counter()
    {   counter = 0;
    }
    
    public void add_poly(Polyline a)
    {   poly_collection.addElement(a);
    }
    
    public boolean isEmpty()
    {   return poly_collection.isEmpty();
    }
    
    public void remove_all_polies()
    {   poly_collection.removeAllElements();
    }
    
    public boolean has_another()
    {   return counter < poly_collection.size();
    }
    
    public void scale(int x,int y,double x_dist, double y_dist,double x_right,double y_max)
    { 
       if (!poly_collection.isEmpty())
          while (has_another())
          {   get_next().scale(x,y,x_dist,y_dist,x_right,y_max);
          }
       counter = 0;
    }    
    
 }
 
class Function
{   String functype;
    double A;
	double B;
    
    public Function()
    {   functype = "";
	}
 
	public double evaluate(double x)
	{	//child method will override to evaluate it self
     return 0;
	}  
}

class SINE extends Function
{   	
	public SINE(double a, double b)
	{	super();
	    A = a;
		B = b;
		functype = "SINE";
	}

    public double evaluate(double x)
	{   return (A * Math.sin(B * x));
	}
}

class COSINE extends Function
{   
	public COSINE(double a, double b)
	{	super();
	    A = a;
		B = b;
		functype = "COSINE";
	}

    public double evaluate(double x)
	{   return (A * Math.cos(B * x));
	}
}

class TAN extends Function
{   
	public TAN(double a, double b)
	{	super();
	    A = a;
		B = b;
		functype = "TAN";
	}

    public double evaluate(double x)
	{   return (A * Math.tan(B * x));
	}
}

class EXP extends Function
{   
	public EXP(double a, double b)
	{	super();
	    A = a;
		B = b;
	    functype = "EXP";
	}

    public double evaluate(double x)
	{   return (A*Math.pow( 2.718281828,(B*x)));
	}
}

class CONSTANT extends Function
{
	public CONSTANT(double x)
	{	super();
		A = x;
		functype = "CONSTANT";
	}

	public double evaluate(double x)
	{	return A;
	}
}


class POLYTERM extends Function
{	
	double C,D,E,F,G,H,I,J;	
	
   	public POLYTERM(double a, double b, double c, double d, double e, double f,
					double g, double h, double i, double j)
	{	super();
        A = a; B = b; C = c; D = d; E = e; F = f; G = g; H = h; I = i; J = j;
	    functype = "POLYTERM";
	}

    public double evaluate(double x)
	{   return (A*Math.pow(x,B) + C*Math.pow(x,D) + E*Math.pow(x,F) + 
				G*Math.pow(x,H) + I*Math.pow(x,J) );
	}
}

class Link
{   char linktype;
    
    public Link(char x)
	{	linktype = x;
	}

	public double evaluate_link(Function a, Function b, double x)
    {   if (linktype == '+')
			return (a.evaluate(x) + b. evaluate(x));

	    else if (linktype == '-')
			return (a.evaluate(x) - b. evaluate(x));

		else if (linktype == '*')
			return (a.evaluate(x) * b.evaluate(x));

		else if (linktype == '/')
			return (a.evaluate(x) / b.evaluate(x));

		else if (linktype == 'o')
		{	double temp = b.evaluate(x);
		    return a.evaluate(temp);
		}
		else return 0;   //default case 
	}
}

class Expression
{	private Stack functionstack;
    private Stack linkstack;
	private String Name;

	public Expression()
	{	functionstack = new Stack();
	    linkstack = new Stack();
		Name = "";
	}

	public String get_expression_name()
	{	return Name;
	}

	public Function get_func()
	{   return (Function) functionstack.pop();
	}

	public Link get_link()
	{	return (Link) linkstack.pop();
	}

/*	public double evaluate_expression(double x)
	{	if (functionstack.empty())
			return 0;		//there is no expression.

		//NOT VALID FUNCTION YET

		Function A = get_func();
		if (linkstack.empty())	//no composite functions.
		{	return A.evaluate(x);
		}

		Stack tempfunc = new Stack();
		Stack tempLink = new Stack();
		Function B = get_func();
		Link L = get_link();	
		double a = L.evaluate_link(B,A,x);	//change order to account for stack
		CONSTANT C = new CONSTANT(a);
		tempfunc.push(A);
		tempfunc.push(B);

		while (! functionstack.empty() && !linkstack.empty())
		A = get_func();
		a = evaluate_link(A,B,x);
		return 0;
	}
	*/
}

class DrawArea extends Canvas implements MouseListener
{   
    public Graph applet;
    
    public DrawArea()
    {   super();
		addMouseListener(this);
    }

    public void repaint()
    {   super.repaint();
    }
    
    public void paint( Graphics g)
    {  
		//draw coordinate system
    		
	g.setColor(Color.blue);	
    int x_zero = (int) (size().width * (1 - applet.retrieve_x_right() / (applet.retrieve_x_right() - applet.retrieve_x_left())) );
    int y_zero = (int) (size().height *  applet.retrieve_y_max() / (applet.retrieve_y_max() - applet.retrieve_y_min()) );
    g.drawLine(0,y_zero,size().width,y_zero);
    g.drawLine(x_zero,0,x_zero,size().height);
    g.drawString("" + applet.get_x_left(), 0,y_zero - 5);
    g.drawString("" + applet.get_x_right(), size().width - 45, y_zero - 5);
    g.drawString("" + applet.get_y_minimum(), x_zero + 5, size().height - 10);
    g.drawString("" + applet.get_y_maximum(), x_zero + 5, 15);
    g.setColor(applet.linecolor);    
        //to avoid altering the original data use copy of Bag polies to scale.
        //this is necesary to view equation on multiple viewing ranges.
        //and to view more than one equation.
        
        Bag temp = new Bag(applet.polies);
        temp.reset_counter();
        
        
        temp.scale(size().width, 
                   size().height,
                   applet.get_x_right()-applet.get_x_left(),
                   applet.get_y_maximum() - applet.get_y_minimum(), 
                   applet.get_x_right(),
                   applet.get_y_maximum() 
                   );   
        Point a;
        Point b;
        Polyline poly1;
        
        if (! temp.isEmpty())
        while (temp.has_another())
        {  poly1 = temp.get_next();
		   g.setColor(poly1.color);
           if (! poly1.isEmpty())
           {   a = poly1.get_next();
              while( poly1.has_another())
              {    b = poly1.get_next();
                   int xstart = (int) a.getX();
                   int ystart = (int) a.getY();
                   int xfin = (int)  b.getX();
                   int yfin = (int)  b.getY();
                
				   if ((ystart>=0) && (ystart<=size().width)&&
					  (yfin>=0) && (yfin<=size().width))
                   g.drawLine(xstart, ystart,xfin,yfin);
                   a=b;
              }
           }  
        }            
    }//end paint

          
	
	
	public void mousePressed(MouseEvent evt)
	{	
	}


	public void mouseReleased(MouseEvent evt)
	{	
	}


	public void mouseEntered(MouseEvent evt)
	{
	}
	 
	public void mouseExited(MouseEvent evt)
	{
	}
	
	public void mouseClicked(MouseEvent evt)
	{	if (applet.zoom_enable == true)			
		{   int x = evt.getX();
		    int y = evt.getY();
		    applet.zoom_in_at(applet.getPoint(x,y));
		    applet.zoom_enable = false;
		}
		else if (applet.get_point_enable == true)
		{   
		    Point converted = applet.getPoint(evt.getX(), evt.getY());
		    applet.update_textfield("X = " + converted.getX() + "\nY = " + converted.getY());
			applet.get_point_enable = false;
		}
	}
	
}//end class

class Graph_GUI
{
  private Graph applet;

//contructor
  public Graph_GUI(Graph graph_applet)
  {     applet = graph_applet;
        graphlistener2 = new Graph_Action_Listener2(applet);
        equation_entry_listener = new Equation_Entry_Listener(applet);
        range_entry_listener = new Range_Entry_Listener(applet);
		five_term_poly_listener = new Five_Term_Poly_Listener(applet);
	    sin_listener = new Sin_Listener(applet);
        cos_listener = new Cos_Listener(applet);
        tan_listener = new Tan_Listener(applet);
		exp_listener = new Exp_Listener(applet);
		help_listener = new Help_Listener(applet);
        grapharea.applet = graph_applet;
  }
  
  //setup for main window

  public DrawArea grapharea  = new DrawArea();  
  private Panel textpanel = new Panel();
  private Label ilabel = new Label("Instructions");
  private Panel graphpanel = new Panel();
  private TextArea instructiontext = new TextArea("You may enter a new equation or change the viewing area at any time."
                                                  + "\n\nTo zoom in about center of graph press the zoom in button.\n\nTo zoom in " +
                                                   "about a point click zoom in at:,  then click on center of area to be viewed." +
                                                   "\n\nZoom back restores the last viewing area before selecting zoom in or out.");
                                          
  private Label title = new Label("Graph ");
  
  private Panel graphcontrolpanel = new Panel();
  private Button enterEquation = new Button ("Enter Equation");
  private Button selectRange = new Button ("Select Viewing Range");
  private Button zoom = new Button ("Zoom in");
  private Button zoom_about = new Button ("Zoom in at:");
  private Button zoom_back = new Button("Zoom back");
  private Button zoom_out = new Button("Zoom out");
  private Button clearGraph = new Button ("Clear Graph");
  private Button quit = new Button ("Exit");
  private Button getpoint = new Button ("Get Point");
  private Button help = new Button ("Help");
  
  //setup for equation entry window
 
  private Frame equation_entry = new Frame("Equation Entry");
  private Button selCOS = new Button ("aCOS(bX)");
  private Button selSIN = new Button ("aSIN(bX)");
  private Button selTAN = new Button ("aTAN(bX)");
  private Button selEXP = new Button ("a*e^(bX)");
  private Button selPoly = new Button("5 Term Polynomial in X");
  private Button help_eq = new Button("HELP");
  private Button plus = new Button ("f(x) + g(x)");
  private Button minus = new Button ("f(x) - g(x)");
  private Button times = new Button ("f(x) * g(x)");
  private Button divide = new Button ("f(x) / g(x)");
  private Button compose = new Button ("f(g(x))"); 
  private Button cancel = new Button("Cancel");
  private TextField instructions = new TextField("CHOOSE EQUATION\nAND EVALUATION RANGE");
  private Label RangeOnX = new Label("RANGE ON X ");
  private Label range1 = new Label("START");
  private Label range2 = new Label("END");
  private TextField xrange1 = new TextField("-10");
  private TextField xrange2 = new TextField("10");
  
//setup  for five term polynomial frame.
  
  private Frame fiveTermPoly = new Frame("Five term polynomial");
  private Button resetFields = new Button("Reset Poly fields");
  private TextField coef1 = new TextField("0");
  private TextField coef2 = new TextField("0");
  private TextField coef3 = new TextField("0");
  private TextField coef4 = new TextField("0");
  private TextField coef5 = new TextField("0");
  private TextField pow1 = new TextField("0");
  private TextField pow2 = new TextField("0");
  private TextField pow3 = new TextField("0");
  private TextField pow4 = new TextField("0");
  private TextField pow5 = new TextField("0");
  private Label Lcoef = new Label("COEFFICIENT");
  private Label LPow = new Label ("POWER");
  private Label t1 = new Label("1ST Term");
  private Label t2 = new Label("2ND Term");
  private Label t3 = new Label("3RD Term");
  private Label t4 = new Label("4TH Term");
  private Label t5 = new Label("5TH Term");
  private Label takeupspace2 = new Label("    ");
  private Label takeupspace3 = new Label("    "); 
  private Button submit = new Button("Submit Polynomial");
  private Button cancelPoly = new Button("Cancel");
  private Button helpPoly = new Button("Help");
						  
  
  //setup for range entry window
  
  private Frame range_entry = new Frame("Range Entry");
  private Label x_min = new Label("X min");
  private Label x_max = new Label("X max");
  private Label y_min = new Label("Y min");
  private Label y_max = new Label("Y max");
  private TextField X_min = new TextField("-10");
  private TextField X_max = new TextField("10");
  private TextField Y_min = new TextField("-10");
  private TextField Y_max = new TextField("10");
  private Button enter_range = new Button ("Enter range");
  private Button default_range = new Button ("Restore Defaults");
  private Button cancel2 = new Button("Cancel");
  private Button help_range = new Button("HELP");


  //setup for SIN modifiers
  
  private Frame sin_modifier = new Frame("aSIN(bX");
  private TextField sincoef = new TextField("1");
  private TextField x1coef = new TextField("1");
  private Label a1 = new Label("a = ");
  private Label b1 = new Label("b = ");
  private Button Enter1 = new Button("Enter");
  private Button sinecancel = new Button("Cancel");
  
  
  //setup for COS modifiers
  
  private Frame cos_modifier = new Frame("aCOS(bX)");
  private TextField coscoef = new TextField("1");
  private TextField x2coef = new TextField("1");
  private Label a2 = new Label("a = ");
  private Label b2 = new Label("b = ");
  private Button Enter2 = new Button("Enter");
  private Button cosinecancel = new Button("Cancel");
 
  
  //setup for the TAN modifiers
  
  private Frame tan_modifier = new Frame("aTAN(bX)");
  private TextField tancoef = new TextField("1");
  private TextField x3coef = new TextField("1");
  private Label a3 = new Label("a = ");
  private Label b3 = new Label("b = ");
  private Button Enter3 = new Button("Enter");  
  private Button tangentcancel = new Button ("Cancel");

//setup for the EXP modifiers.

  private Frame exp_modifier = new Frame("aEXP(bX)");
  private TextField expcoef = new TextField("1");
  private TextField x4coef = new TextField("1");
  private Label a4 = new Label("a = ");
  private Label b4 = new Label("b = ");
  private Button Enter4 = new Button("Enter");  
  private Button expcancel = new Button ("Cancel");

  
  //setup for the help frame
  
  private Frame helpFrame = new Frame("Help");
  private Panel helpButtons = new Panel();
  private Button helpEnterEq = new Button("Entering Equations");
  private Button helpEnterRange = new Button("Changing Range");
  private Button helpZoom = new Button ("Zooming");
  private Button helpClear = new Button ("Cleargraph");
  private Button quithelp = new Button ("Exit");
  private Button helpgetpoint = new Button ("Get Point");
  private TextArea helpText = new TextArea("PLEASE CHOOSE TOPIC FOR HELP");
  
          
  
  

  //actionlisteners for main window
  private Graph_Action_Listener2 graphlistener2;
    
  //actionlisteners for enterequation window.
  private Equation_Entry_Listener equation_entry_listener;
  
  //actionlistener for range_entry window  
  private Range_Entry_Listener range_entry_listener;
  
  //actionlistener for 5termPoly window
  private Five_Term_Poly_Listener five_term_poly_listener;
  
  //actionlistener for sin_modifier window
  private Sin_Listener sin_listener;
  
  //actionlistener for cos_modifier window
  private Cos_Listener cos_listener;
  
  //actionlistener for tan_modifier window
  private Tan_Listener tan_listener;

  private Exp_Listener exp_listener;
  
  //actionlistener for helpFrame window
  private Help_Listener help_listener;


  public void init()
  {   
      applet.setLayout (new BorderLayout());   //layout for applet
      applet.setSize(401,401);
      textpanel.setLayout(new BorderLayout());
      textpanel.add(ilabel,"North");
      instructiontext.setEditable(false);
      textpanel.add(instructiontext,"Center");
      
      graphpanel.setLayout (new BorderLayout());
      graphpanel.add(title, "North");
      graphpanel.add(grapharea,"Center");
	 
      
      graphcontrolpanel.setLayout( new GridLayout(10,1));
      graphcontrolpanel.add(enterEquation);
      graphcontrolpanel.add(selectRange);
      graphcontrolpanel.add(getpoint);
      graphcontrolpanel.add(zoom);
      graphcontrolpanel.add(zoom_out);
      graphcontrolpanel.add(zoom_back);
      graphcontrolpanel.add(zoom_about);    
      graphcontrolpanel.add(clearGraph);
      graphcontrolpanel.add(help);
//    graphcontrolpanel.add(quit);
      graphpanel.add(graphcontrolpanel,"West");
      applet.add (textpanel, "North");
      applet.add (graphpanel, "Center");
      
      
  // init for equation_entry frame

      equation_entry.setLayout(new GridLayout(6,3,5,5));
      equation_entry.setSize(500,300);
      equation_entry.setVisible(false);
	  equation_entry.add(selCOS);
      equation_entry.add(selSIN);
      equation_entry.add(selTAN);
      equation_entry.add(selEXP);
      equation_entry.add(selPoly);
	  equation_entry.add(plus);
	  equation_entry.add(minus);
      equation_entry.add(times);
	  equation_entry.add(divide);
	  equation_entry.add(compose);
      equation_entry.add(cancel); 
      equation_entry.add(help_eq);
	  RangeOnX.setAlignment(Label.CENTER);
      instructions.setEditable(false);
	  instructions.setBackground(Color.pink);
      equation_entry.add(instructions);
      range1.setAlignment(Label.CENTER);
      equation_entry.add(range1);      
      range2.setAlignment(Label.CENTER);      
      equation_entry.add(range2);
	  equation_entry.add(RangeOnX);
      equation_entry.add(xrange1);
      equation_entry.add(xrange2);
      
  

  //init for 5 term poly frame
	  fiveTermPoly.setLayout(new GridLayout(8,3,10,10));
	  fiveTermPoly.setSize(300,500);
	  fiveTermPoly.setVisible(false);										
	  fiveTermPoly.add(takeupspace3);
      Lcoef.setAlignment(Label.CENTER);
      fiveTermPoly.add(Lcoef);
      LPow.setAlignment(Label.CENTER);
      fiveTermPoly.add(LPow); 
      t1.setAlignment(Label.RIGHT);     
      fiveTermPoly.add(t1);
      fiveTermPoly.add(coef1);      
      fiveTermPoly.add(pow1);
      t2.setAlignment(Label.RIGHT); 
      fiveTermPoly.add(t2);
      fiveTermPoly.add(coef2);      
      fiveTermPoly.add(pow2);
      t3.setAlignment(Label.RIGHT);  
      fiveTermPoly.add(t3);
      fiveTermPoly.add(coef3);      
      fiveTermPoly.add(pow3);
      t4.setAlignment(Label.RIGHT);  
      fiveTermPoly.add(t4);
      fiveTermPoly.add(coef4);      
      fiveTermPoly.add(pow4);
      t5.setAlignment(Label.RIGHT);  
      fiveTermPoly.add(t5);
      fiveTermPoly.add(coef5);      
      fiveTermPoly.add(pow5);
      fiveTermPoly.add(resetFields);
      fiveTermPoly.add(submit);
	  fiveTermPoly.add(cancelPoly);
	  fiveTermPoly.add(helpPoly);
   
  //init for range_entry frame

      range_entry.setLayout(new GridLayout(6,2,10,10));
      range_entry.setSize(400,300);
      range_entry.setVisible(false);
      range_entry.add(x_min);
      range_entry.add(X_min);
      range_entry.add(x_max);
      range_entry.add(X_max);
      range_entry.add(y_min);
      range_entry.add(Y_min);
      range_entry.add(y_max);
      range_entry.add(Y_max);
      range_entry.add(enter_range);
      range_entry.add(default_range);
      range_entry.add(cancel2);
	  range_entry.add(help_range);
      
  //init for sin_modifier frame
  
      sin_modifier.setSize(300,200);
      sin_modifier.setLayout(new GridLayout(3,2));
      a1.setAlignment(Label.RIGHT);
      sin_modifier.add(a1);
      sin_modifier.add(sincoef);
      b1.setAlignment(Label.RIGHT);
      sin_modifier.add(b1);
      sin_modifier.add(x1coef); 
      sin_modifier.add(Enter1);
      sin_modifier.add(sinecancel);       
      sin_modifier.setVisible(false);  
      
  //init for cos_modifier frame
  
      cos_modifier.setSize(300,200);
      cos_modifier.setLayout(new GridLayout(3,2));
      a2.setAlignment(Label.RIGHT);
      cos_modifier.add(a2);
      cos_modifier.add(coscoef);
      b2.setAlignment(Label.RIGHT);
      cos_modifier.add(b2);
      cos_modifier.add(x2coef); 
      cos_modifier.add(Enter2); 
      cos_modifier.add(cosinecancel);      
      cos_modifier.setVisible(false);  
      
     
   //init for tan_modifier frame
  
      tan_modifier.setSize(300,200);
      tan_modifier.setLayout(new GridLayout(3,2));
      a3.setAlignment(Label.RIGHT);
      tan_modifier.add(a3);
      tan_modifier.add(tancoef);
      b3.setAlignment(Label.RIGHT);
      tan_modifier.add(b3);
      tan_modifier.add(x3coef); 
      tan_modifier.add(Enter3);
      tan_modifier.add(tangentcancel);       
      tan_modifier.setVisible(false);       

   //init for exp_modifier frame.
	  exp_modifier.setSize(300,200);
      exp_modifier.setLayout(new GridLayout(3,2));
      a4.setAlignment(Label.RIGHT);
      exp_modifier.add(a4);
      exp_modifier.add(expcoef);
      b4.setAlignment(Label.RIGHT);
      exp_modifier.add(b4);
      exp_modifier.add(x4coef); 
      exp_modifier.add(Enter4);
      exp_modifier.add(expcancel);       
      exp_modifier.setVisible(false);       
	  

  //init for helpFrame frame
	  GridBagLayout gridbag = new GridBagLayout();
	  GridBagConstraints c = new GridBagConstraints();
	  helpFrame.setLayout(gridbag);
	  c.fill = GridBagConstraints.NONE;
	  c.gridwidth = 1;
      helpFrame.add(helpButtons);
	  c.fill=GridBagConstraints.BOTH;
	  c.weightx = 1.0;
	  c.gridwidth = GridBagConstraints.REMAINDER;
	  helpFrame.add(helpText);
	  helpFrame.setSize(500,250);
	  helpFrame.setVisible(false);
	  helpButtons.setLayout(new GridLayout(6,1));
	  helpButtons.add(helpEnterEq);
	  helpButtons.add(helpEnterRange);
	  helpButtons.add(helpZoom);
	  helpButtons.add(helpClear);
	  helpButtons.add(helpgetpoint);
	  helpButtons.add(quithelp);


//listeners get assigned here
  
   //listeners for main window
   
      enterEquation.addActionListener(graphlistener2);
      selectRange.addActionListener(graphlistener2);
      zoom.addActionListener(graphlistener2);
      zoom_about.addActionListener(graphlistener2);
      zoom_back.addActionListener(graphlistener2);
      zoom_out.addActionListener(graphlistener2);
      clearGraph.addActionListener(graphlistener2);
      quit.addActionListener(graphlistener2);
      getpoint.addActionListener(graphlistener2);
      help.addActionListener(graphlistener2);
      
   //listener for enter equation frame
   
      
      selCOS.addActionListener(equation_entry_listener);
      selSIN.addActionListener(equation_entry_listener);
      selTAN.addActionListener(equation_entry_listener);
      selEXP.addActionListener(equation_entry_listener);
      selPoly.addActionListener(equation_entry_listener);
	  plus.addActionListener(equation_entry_listener);
      minus.addActionListener(equation_entry_listener);
      times.addActionListener(equation_entry_listener);
      divide.addActionListener(equation_entry_listener);
      compose.addActionListener(equation_entry_listener);
      cancel.addActionListener(equation_entry_listener);
	  help_eq.addActionListener(equation_entry_listener);
      
   //listeners for fiveTermPoly frame
	  resetFields.addActionListener(five_term_poly_listener);
      submit.addActionListener(five_term_poly_listener);
	  helpPoly.addActionListener(five_term_poly_listener);
	  cancelPoly.addActionListener(five_term_poly_listener);
	 
	  
		  
   //listener for enter range frame
   
      enter_range.addActionListener(range_entry_listener);
      default_range.addActionListener(range_entry_listener);
      cancel2.addActionListener(range_entry_listener);
      help_range.addActionListener(range_entry_listener);
   //listener for trig modifier frames
   
      Enter1.addActionListener(sin_listener);
      sinecancel.addActionListener(sin_listener);
      
      Enter2.addActionListener(cos_listener);
      cosinecancel.addActionListener(cos_listener);
      
      Enter3.addActionListener(tan_listener);
      tangentcancel.addActionListener(tan_listener);

   //listener for the exp_modifier frame
	  Enter4.addActionListener(exp_listener);
      expcancel.addActionListener(exp_listener);

   //listener for the help frame
	  helpEnterEq.addActionListener(help_listener);
	  helpZoom.addActionListener(help_listener);
	  helpClear.addActionListener(help_listener);
	  helpEnterRange.addActionListener(help_listener);
	  quithelp.addActionListener(help_listener);
	  helpgetpoint.addActionListener(help_listener);

      
  }//end of init

//data retrieving methods
  
  public double get_range_min()
  {  return Double.valueOf(xrange1.getText()).doubleValue();
  }
   
  public double get_range_max()
  {  return Double.valueOf(xrange2.getText()).doubleValue();
  }
   
  public double get_coef1()
  {  return Double.valueOf(coef1.getText()).doubleValue();
  }
  
  public double get_pow1()
  {  return Double.valueOf(pow1.getText()).doubleValue();
  }
  
  public double get_coef2()
  {  return Double.valueOf(coef2.getText()).doubleValue();
  }
  
  public double get_pow2()
  {  return Double.valueOf(pow2.getText()).doubleValue();
  }
  
  public double get_coef3()
  {  return Double.valueOf(coef3.getText()).doubleValue();
  }
  
  public double get_pow3()
  {  return Double.valueOf(pow3.getText()).doubleValue();
  }
  
  public double get_coef4()
  {  return Double.valueOf(coef4.getText()).doubleValue();
  }
  
  public double get_pow4()
  {  return Double.valueOf(pow4.getText()).doubleValue();
  }
  
  public double get_coef5()
  {  return Double.valueOf(coef5.getText()).doubleValue();
  }
  
  public double get_pow5()
  {  return Double.valueOf(pow5.getText()).doubleValue();
  }
  
  public double retrieve_x_left()
  {  return Double.valueOf(X_min.getText()).doubleValue();
  }
  
  public double retrieve_x_right()
  {  return Double.valueOf(X_max.getText()).doubleValue();
  }
  
  public double retrieve_y_min()
  {  return Double.valueOf(Y_min.getText()).doubleValue();
  }
  
  public double retrieve_y_max()
  {  return Double.valueOf(Y_max.getText()).doubleValue();
  }
  
  public double retrieve_x_start()
  {  return Double.valueOf(xrange1.getText()).doubleValue();
  }
  
  public double retrieve_x_end()
  {  return Double.valueOf(xrange2.getText()).doubleValue();
  }
  
//trig functions
  
  public double retrieve_sincoef()
  {   return Double.valueOf(sincoef.getText()).doubleValue();
  }
  
  public double retrieve_sin_xcoef()
  {   return Double.valueOf(x1coef.getText()).doubleValue();
  }
  
  public double retrieve_coscoef()
  {   return Double.valueOf(coscoef.getText()).doubleValue();
  }
  
  public double retrieve_cos_xcoef()
  {   return Double.valueOf(x2coef.getText()).doubleValue();
  }
  
  public double retrieve_tancoef()
  {   return Double.valueOf(tancoef.getText()).doubleValue();
  }
  
  public double retrieve_tan_xcoef()
  {   return Double.valueOf(x3coef.getText()).doubleValue();
  }

  public double retrieve_expcoef()
  {   return Double.valueOf(expcoef.getText()).doubleValue();
  }
  
  public double retrieve_exp_xcoef()
  {   return Double.valueOf(x4coef.getText()).doubleValue();
  }





   
  public void restore_view_range_defaults()
  {   X_min.setText("-10");
      X_max.setText("10");
      Y_min.setText("-10");
      Y_max.setText("10");
      applet.make_range_entry_invisible();
      applet.make_Main_visible();
  }  

  public int canvas_height()
  {   return grapharea.size().height;
  }

  public int canvas_width()
  {   return grapharea.size().width;
  }
  
//GUI update methods write to text fields.

   public void update_textfield(String text)
   {  instructiontext.setText(text);
   } 

   public void set_EQ_text(String newtext)
   {  instructions.setText(newtext);
   }
   
   public void set_x_left(double new_x)
   {   X_min.setText(""+new_x);
   }
   
   public void set_x_right(double new_x)
   {   X_max.setText(""+new_x); 
   }
   
   public void set_y_min(double new_y)
   {   Y_min.setText(""+new_y);
   }
   
   public void set_y_max(double new_y)
   {   Y_max.setText(""+new_y);
   }
   
   public void reset_poly_fields()
   {   coef1.setText(""+0);
       coef2.setText(""+0);
       coef3.setText(""+0);
       coef4.setText(""+0);
       coef5.setText(""+0);
       pow1.setText(""+0);
       pow2.setText(""+0);
       pow3.setText(""+0);
       pow4.setText(""+0);
       pow5.setText(""+0);
   }
   
//visibility methods
  
  public void make_Main_visible()
  {   applet.show(); 
  }
  
  public void make_Main_invisible()
  {   applet.hide();
  }
  
  
  
  public void make_eq_entry_visible()
  {   equation_entry.setVisible(true);
  }

  public void make_eq_entry_invisible()
  {   equation_entry.setVisible(false);
  }
  public void make_range_entry_visible()
  {   range_entry.setVisible(true);
  }
  
  public void make_range_entry_invisible()
  {   range_entry.setVisible(false);
  }
  
  public void make_5term_visible()
  {   fiveTermPoly.setVisible(true);
  }

  public void make_5term_invisible()
  {   fiveTermPoly.setVisible(false);
  }
  
  public void make_SIN_visible()
  {   sin_modifier.setVisible(true);
  }
   
  public void make_SIN_invisible()
  {   sin_modifier.setVisible(false);
  }
  
  public void make_COS_visible()
  {   cos_modifier.setVisible(true);
  }
   
  public void make_COS_invisible()
  {   cos_modifier.setVisible(false);
  }
  
  public void make_TAN_visible()
  {   tan_modifier.setVisible(true);
  }
   
  public void make_TAN_invisible()
  {   tan_modifier.setVisible(false);
  }

  public void make_EXP_invisible()
  {   exp_modifier.setVisible(false);
  }

  public void make_EXP_visible()
  {   exp_modifier.setVisible(true);
  }
   
  public void make_help_visible()
  {   helpFrame.setVisible(true);
  }

  public void make_help_invisible()
  {   helpFrame.setVisible(false);
  }
   
  public void disable_composites()
  {	  plus.setEnabled(false);
	  minus.setEnabled(false);
	  times.setEnabled(false);
	  divide.setEnabled(false);
	  compose.setEnabled(false);
  }
  
  public void enable_composites()
  {	plus.setEnabled(true);
	  minus.setEnabled(true);
	  times.setEnabled(true);
	  divide.setEnabled(true);
	  compose.setEnabled(true);
  }

  public void enable_submit()
  {   submit.setEnabled(true);
  }
  
  public void disable_submit()
  {   submit.setEnabled(false);
  }
  

//zoom methods
 
  public void repaint()
  {   grapharea.repaint();
  }
 
  
//help functions

  public void help_on_Eq()
  {   helpText.setText("ENTERING EQUATIONS\n\n" +
                       "To enter an equation the first step is to click on button\n" +
                       "Enter equation.  Next at the bottem of the pop up window there\n" +
					   "is a place to enter the range on which you wish to evaluate the\n" +
					   "function.  This is not the same as the viewing range.  This range\n" + 
					   "is used in selecting the points to evaluate and plot the graph.\n" +
					   "If you wish to zoom in very closely onto a graph you may want to\n" +
					   "evaluate the function on a narrower interval to get a smoother curve\n" +
					   "*Note*  If you zoom in about 5 times the graph will get distorted\n" +
					   "and this can be fixed by choosing a smaller evaluation range.  The\n" +
					   "problem is that the distance between two points can become larger\n" +
					   "then the viewing area.\n\n" +
					   "The second step is to choose the type of equation that you wish to\n" +
					   "graph.  You can choose from one of the given Trig functions, the\n" +
					   "exponential function, or a 5 term polynomial.\n\nTRIG FUNCTIONS\n\n" +
					   "For the trigonometric functions a window will pop up in which you can\n" +
					   "enter a and b, two paramters, where in 5Sin(6x) a would be 5 and b\n"+
					   "would be 6.\n\nEXPONENTIAL FUNCTION\n\n" +
					   "As in the trig functions there are two parameters for Exponential.\n"+
					   "function.  a is a constant coefficient and b is a factor of bX, the\n" +
					   "power to which the base e is raised.  Note due to overflow error\n" +
					   "it is recommended to evaluated on a smaller range or to view on a \n" +
					   "larger range than is customary for the other functions.\n" +
					   "\nExample: in 5(e^(4x)), a is 5 and b is 4. \n\n" +
					   "\n5 TERM POLYNOMIAL\n\n" +
					   "For the 5 term polynomial, each term requires a coefficient and a\n" +
					   "power.  For example 5x^2 would require 5 in the coefficient and 2\n" +
					   "in the power column.  The functions will accept decimal coefficients\n" +
					   "as well as decimal powers.  However, for non-integer powers the\n " +
					   "function will be undefined for x < 0.\n" +
					   "Once each of the terms have been entered, click on submit polynomial\n" +
					   "For any terms not needed zeroes should be left or placed into the\n" +
					   "boxes");
						


	}

	public void help_on_Range()
	{   helpText.setText("VIEWING RANGES\n\n" +
	                     "To select a specific viewing range first you must click on the\n" +
						 "Select viewing range button.  This brings up a window where you\n" +
						 "can enter the size of the viewing window.  Uneven viewing windows\n" +
						 "are allowed, however make sure that xmin is less then xmax and\n" +
						 "ymin is less then ymax\n\n"+
						 "You can restore the 20 by 20 window by selecting restore defaults");
	}

	public void help_on_Clear()
	{	helpText.setText("CLEAR GRAPH\n\n" +
	                     "This button just removes all equations from the graph.");	
	}
	
	public void help_on_Zoom()
	{	helpText.setText("ZOOMING BUTTONS\n\n" +
	                     "ZOOM IN:\n" +
						 "Zoom In zooms about the very center of the graph.  This zoom\n" +
						 "is by a factor of 2, that is it cuts the viewing range in half\n\n" +
						 "ZOOM IN AT::\n" +
						 "Zoom in at zooms in about a point selected by a mouse click on the\n" +
						 "graph.  Just click on the button followed by a location on the\n" +
						 "graph that you wish to center the zoom.  Again the factor is by 2\n\n"+
						 "ZOOM OUT::\n" +
						 "Zoom out zooms out from the center of the graph.  It doubles the\n" +
						 "size of the viewing range.\n\n"+
						 "ZOOM BACK::\n" +
						 "The program keeps track of the previous viewing ranges.  Each time\n"+
						 "Zoom back is selected it restores the range that was one previous.\n" +
						 "When there are no previous ranges, Zoom back sets the viewing range\n" +
						 "to the defaults.\n");                     
	}

	public void help_on_getpoint()
	{	helpText.setText("GET POINT::\n\n" +
	                     "Get Point returns the x,y coordinates of a point on the graph\n" +
						 "relative to the current viewing range.  Just click on the button\n" +
						 "and then click on any point of the graph.  The x,y coordinates are\n"+
						 "provided above the graph in the two boxes labeled as such");
	}



}//end class Graph_GUI

    

class Graph_Action_Listener2 implements ActionListener
{   private Graph applet;

    public Graph_Action_Listener2(Graph listening_applet)
    {   applet = listening_applet;
    }
    
    public void actionPerformed(ActionEvent event)
    {  String command = event.getActionCommand();
    
       if (command.equals("Exit"))
       {   System.exit(0);
       }       
    
       else if (command.equals("Enter Equation"))
       {   applet.make_EQ_entry_visible();
           applet.make_Main_invisible();
       } 
       
       else if (command.equals("Get Point"))
       {   applet.get_point_enable = true;
       }	
       
       else if (command.equals("Select Viewing Range"))
       {   applet.make_range_entry_visible();
       }
         
       else if (command.equals("Zoom in"))
       {  applet.zoom_in_at(applet.getPoint(applet.get_canvas_width()/2, applet.get_canvas_height()/2));
       }

       else if (command.equals("Zoom back"))
       {	if (applet.zoom_stack.empty())
			{   applet.restore_view_range_defaults();
   				applet.repaint();
			}
			else 
			applet.zoom_back();			
       }
       
       else if (command.equals("Zoom out"))
       {	applet.zoom_out_at(applet.getPoint(applet.get_canvas_width()/2, applet.get_canvas_height()/2));
       }
       
       else if (command.equals("Clear Graph"))
       {	applet.clear_graph();
			applet.repaint();
       }
       
       else if (command.equals("Zoom in at:"))
	   {	applet.zoom_enable = true;
	   }
	   else if (command.equals("Help"))
       {	applet.make_help_visible();
	
	   }



    }
}


class Range_Entry_Listener implements ActionListener
{   private Graph applet;
    
    public Range_Entry_Listener(Graph listening_applet)
    {   applet = listening_applet;
    }
    
    public void actionPerformed(ActionEvent event)
    {  String command = event.getActionCommand();
       if (command.equals("Restore Defaults"))
       {   applet.restore_view_range_defaults();
       } 
       else if (command.equals("Cancel"))
       {   applet.make_range_entry_invisible();
       } 
	   else if (command.equals("HELP"))
       {	applet.make_help_visible();
	        applet.help_on_Range();
	   }
       else if (command.equals("Enter range"))
       {   double newxl = applet.retrieve_x_left();
           double newxr = applet.retrieve_x_right();           
           double newyl = applet.retrieve_y_min();
           double newyr = applet.retrieve_y_max();
           applet.set_x_left(newxl);
           applet.set_x_right(newxr);
           applet.set_y_minimum(newyl);
           applet.set_y_maximum(newyr);
           applet.make_range_entry_invisible();
       } 
       applet.repaint();
	}
}


class Equation_Entry_Listener implements ActionListener
{   private Graph applet;

    public Equation_Entry_Listener(Graph listening_applet)
    {  applet = listening_applet;
    }

    public void actionPerformed(ActionEvent event)
    {  String command = event.getActionCommand();
    
       applet.set_x_start(applet.retrieve_x_start());
       applet.set_x_end(applet.retrieve_x_end());
       
       		if (command.equals("f(x) + g(x)"))
			{	
				applet.setup_link('+');
				applet.set_EQ_text("Choose f(x)");
			}
	 
			else if (command.equals("f(x) - g(x)"))
			{	
				applet.setup_link('-');
				applet.set_EQ_text("Choose f(x)");
			}
	   
			else if (command.equals("f(x) * g(x)"))
			{	
				applet.setup_link('*');
				applet.set_EQ_text("Choose f(x)");
			}
			else if (command.equals("f(x) / g(x)"))
			{	
				applet.setup_link('/');
				applet.set_EQ_text("Choose f(x)");
			}
			else if (command.equals("f(g(x))"))
			{	
				applet.setup_link('o');
				applet.set_EQ_text("Choose f(x)");
			}
	   
			if (command.equals("5 Term Polynomial in X"))    
			{   applet.make_5term_visible();
			}           
			else if (command.equals( "aCOS(bX)"))
            { 
                applet.make_COS_visible();       
            }
                    
			else if (command.equals( "aSIN(bX)"))
			{ 
			    applet.make_SIN_visible();            
			}
			     
			else if (command.equals( "aTAN(bX)"))
			{ 
			    applet.make_TAN_visible();
			}
			       
			else if (command.equals( "a*e^(bX)"))
			{   applet.make_EXP_visible();
			}
			     
			else if (command.equals("HELP"))
			{	applet.make_help_visible();
				applet.help_on_Eq();
			}

			else if (command.equals("Cancel"))
            {   applet.make_EQ_entry_invisible();
                applet.make_Main_visible();
            }
	   
    
    }//end actionPerformed
}                         

class Five_Term_Poly_Listener implements ActionListener
	
{	private Graph applet;

	public Five_Term_Poly_Listener(Graph listening_applet)
    {  applet = listening_applet;
    }

    public void actionPerformed(ActionEvent event)
    {   String command = event.getActionCommand();
    	if (command.equals("Cancel"))
    	{   applet.make_5term_invisible();
    	}		
		
		else if (command.equals( "Reset Poly fields"))
        {   applet.reset_poly_fields();
        }       
        
  		else if (command.equals("Help"))
		{	applet.make_help_visible();
			applet.help_on_Eq();
		}
		
		else if (command.equals( "Submit Polynomial"))
		{	
			POLYTERM newPoly = new POLYTERM(applet.get_coef1(),applet.get_pow1(),
											applet.get_coef2(),applet.get_pow2(),
											applet.get_coef3(),applet.get_pow3(),
											applet.get_coef4(),applet.get_pow4(),
											applet.get_coef5(),applet.get_pow5());
			    
			if (applet.link_status == 0)
			{   applet.generate_function(newPoly);
				applet.make_Main_visible();
			    applet.make_EQ_entry_invisible(); 
				applet.make_5term_invisible();
			}//if
			else if (applet.link_status==1)
			{	applet.func1 = newPoly;
				applet.link_status = 2;
				applet.make_5term_invisible();
				applet.set_EQ_text("enter g(x)");
			}
			
			else if (applet.link_status==2)
			{	applet.func2 = newPoly;
				applet.link_status=0;
				applet.enable_composites();
				applet.set_EQ_text("choose function");
				applet.make_5term_invisible();
				applet.make_EQ_entry_invisible();
				applet.generate_link();
				applet.make_Main_visible();
			}//else if	
			{//TODO change 5 term polynomial into a subclass of function	
			}//else if
		}//else if
	}//action performed
}//class

		
class Sin_Listener implements ActionListener
{   private Graph applet;
   
    public Sin_Listener(Graph listening_applet)
    {  applet = listening_applet;
    }
    
    public void actionPerformed(ActionEvent event)
    {   String command = event.getActionCommand();
    	if (command.equals("Cancel"))
    	{   applet.make_SIN_invisible();
    	}
  		else
  		{   double a,b;	   
            a = applet.retrieve_sincoef();
            b = applet.retrieve_sin_xcoef();
			SINE newSINE = new SINE(a,b);
			if (applet.link_status == 0)
			{	applet.generate_function(newSINE);
				applet.make_SIN_invisible();
				applet.make_EQ_entry_invisible();
				applet.make_Main_visible();   
			}
			else if (applet.link_status==1)
			{	applet.func1 = newSINE;
				applet.link_status = 2;
				applet.make_SIN_invisible();
				applet.set_EQ_text("enter g(x)");
			}
			
			else if (applet.link_status==2)
			{	applet.func2 = newSINE;
				applet.link_status=0;
				applet.enable_composites();
				applet.set_EQ_text("choose function");
				applet.make_SIN_invisible();
				applet.make_EQ_entry_invisible();
				applet.generate_link();
				applet.make_Main_visible();
			}//else if
							  
	    }//else
    }//action performed
}//class

class Cos_Listener implements ActionListener
{   private Graph applet;
   
    public Cos_Listener(Graph listening_applet)
    {  applet = listening_applet;
    }
    
    public void actionPerformed(ActionEvent event)
    {   String command = event.getActionCommand();
        if (command.equals("Cancel"))
    	{   applet.make_COS_invisible();
    	}
  		else
    	{   double a,b;
            a =  applet.retrieve_coscoef();
            b = applet.retrieve_cos_xcoef();
			COSINE newCOS = new COSINE(a,b);
			if (applet.link_status==0)
			{
				applet.generate_function(newCOS);
				applet.make_EQ_entry_invisible();
				applet.make_COS_invisible();
				applet.make_Main_visible();
			}
			else if (applet.link_status==1)
			{	applet.func1 = newCOS;
				applet.link_status = 2;
				applet.make_COS_invisible();
				applet.set_EQ_text("enter g(x)");
			}
				
			else if (applet.link_status==2)
			{	applet.func2 = newCOS;
				applet.link_status=0;
				applet.enable_composites();
				applet.set_EQ_text("choose function");
				applet.make_COS_invisible();
				applet.make_EQ_entry_invisible();
				applet.generate_link();
				applet.make_Main_visible();
			}//else if					
        }
    }
}

class Tan_Listener implements ActionListener
{   private Graph applet;
   
    public Tan_Listener(Graph listening_applet)
    {  applet = listening_applet;
    }
    
    public void actionPerformed(ActionEvent event)
    {   String command = event.getActionCommand();
        if (command.equals("Cancel"))
    	{   applet.make_TAN_invisible();
    	}
	 	else
	 	{   double a,b;
	        a =  applet.retrieve_tancoef();
	        b = applet.retrieve_tan_xcoef();
			TAN newTAN = new TAN(a,b);
			if (applet.link_status==0)
			{
				applet.generate_function(newTAN);
				applet.make_EQ_entry_invisible();
				applet.make_TAN_invisible();
				applet.make_Main_visible();
			}
			else if (applet.link_status==1)
			{	applet.func1 = newTAN;
				applet.link_status = 2;
				applet.make_TAN_invisible();
				applet.set_EQ_text("enter g(x)");
			}
				
			else if (applet.link_status==2)
			{	applet.func2 = newTAN;
				applet.link_status=0;
				applet.enable_composites();
				applet.set_EQ_text("choose function");
				applet.make_TAN_invisible();
				applet.make_EQ_entry_invisible();
				applet.generate_link();
				applet.make_Main_visible();
			}//else if			
			
        }
    }
}

class Exp_Listener implements ActionListener
{   private Graph applet;
   
    public Exp_Listener(Graph listening_applet)
    {  applet = listening_applet;
    }
    
    public void actionPerformed(ActionEvent event)
    {   String command = event.getActionCommand();
        if (command.equals("Cancel"))
    	{   applet.make_EXP_invisible();
    	}
	 	else
	 	{   double a,b;
	        a =  applet.retrieve_expcoef();
	        b = applet.retrieve_exp_xcoef();
			EXP newEXP = new EXP(a,b);
			if (applet.link_status==0)
			{
				applet.generate_function(newEXP);
				applet.make_EQ_entry_invisible();
				applet.make_EXP_invisible();
				applet.make_Main_visible();
			}
			
			else if (applet.link_status==1)
			{	applet.func1 = newEXP;
				applet.link_status = 2;
				applet.make_EXP_invisible();
				applet.set_EQ_text("enter g(x)");
			}
				
			else if (applet.link_status==2)
			{	applet.func2 = newEXP;
				applet.link_status=0;
				applet.enable_composites();
				applet.set_EQ_text("choose function");
				applet.make_EXP_invisible();
				applet.make_EQ_entry_invisible();
				applet.generate_link();
				applet.make_Main_visible();
			}//else if	
			
        }
    }
}

class Help_Listener implements ActionListener
{	private Graph applet;

	public Help_Listener(Graph listening_applet)
	{	applet = listening_applet;
	}

	public void actionPerformed(ActionEvent event)
	{	String command = event.getActionCommand();
		if (command.equals("Entering Equations"))
			applet.help_on_Eq();
		else if (command.equals("Changing Range"))
			applet.help_on_Range();
		else if (command.equals("Zooming"))
			applet.help_on_Zoom();
		else if (command.equals("Cleargraph"))
			applet.help_on_Clear();
		else if (command.equals("Get Point"))
			applet.help_on_getpoint();
		else if (command.equals("Exit"))
		{	applet.make_help_invisible();
			applet.make_Main_visible();
		}

	}
}
