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

import myutil.*;

public class Calculator extends Applet
{
    private static final int n = 50;
    private int sp;
    private double val[];
    CFNumberField X;
    TextField P;

    public static void main(String[] args)
    {
        new AppletFrame(new Calculator(), 600, 250);
    }

    public void init()
    {
	sp = 0;
        val = new double[n];

	GridPanel gp = new GridPanel("TimesRoman", 24);

	Button EXP    = new Button("e^x"); 	gp.add(EXP,    1,4);
	Button PI     = new Button("PI");     	gp.add(PI,     1,3);
	Button SIN    = new Button("sin");	gp.add(SIN,    2,3);
	Button COS    = new Button("cos");	gp.add(COS,    3,3);
	Button TAN    = new Button("tan");	gp.add(TAN,    4,3);
	Button RECIP  = new Button("1/x");	gp.add(RECIP,  5,3);
	Button SQUARE = new Button("x^2");	gp.add(SQUARE, 5,4);
	Button ROOT   = new Button("sqrt");	gp.add(ROOT,   4,4);
	Button LOG    = new Button("log");	gp.add(LOG,    2,4);
	Button POWER  = new Button("y^x");	gp.add(POWER,  3,4);
	Button ADD    = new Button("+");	gp.add(ADD,    1,2);
	Button SUBTR  = new Button("-");	gp.add(SUBTR,  2,2);
	Button MULT   = new Button("*");	gp.add(MULT,   3,2);
	Button DIV    = new Button("/");	gp.add(DIV,    4,2);
	Button ENTER  = new Button("Enter");	gp.add(ENTER,  5,1);

	Choice FMT = new Choice();
	FMT.addItem("Decimal");
	FMT.addItem("Fraction");
	gp.add(FMT, 6,1);

	X = new CFNumberField("0.0", 15, this); gp.add(X, 1,1,4,1);

	gp.add(new Label("Precision"), 6,2);
	P = new TextField(" 5", 4); gp.add(P, 7,2);

	add(gp);
    }

    public boolean action(Event evt, Object arg)
    {
	if (arg.equals("e^x")) {
	    exp();
	} else 
	if (arg.equals("PI")) {
	    pi();
	} else 
	if (arg.equals("sin")) {
	    sin();
	} else 
	if (arg.equals("cos")) {
	    cos();
	} else 
	if (arg.equals("tan")) {
	    tan();
	} else 
	if (arg.equals("1/x")) {
	    recip();
	} else 
	if (arg.equals("x^2")) {
	    square();
	} else 
	if (arg.equals("sqrt")) {
	    sqrt();
	} else 
	if (arg.equals("log")) {
	    log();
	} else 
	if (arg.equals("y^x")) {
	    power();
	} else 
	if (arg.equals("+")) {
	    add();
	} else 
	if (arg.equals("-")) {
	    subtr();
	} else 
	if (arg.equals("*")) {
	    mult();
	} else 
	if (arg.equals("/")) {
	    div();
	} else 
	if (arg.equals("Enter")) {
	    enter();
	} else 
	if (arg.equals("Decimal")) {
	    int p = SL.atoi(P.getText().trim());
	    X.setPrecision(p);
	    double x = X.fromNumberField();
	    X.setFormat("Decimal");
	    X.toNumberField(x);
	} else 
	if (arg.equals("Fraction")) {
	    int p = SL.atoi(P.getText().trim());
	    X.setPrecision(p);
	    double x = X.fromNumberField();
	    X.setFormat("Fraction");
	    X.toNumberField(x);
	} else {
		return super.action(evt, arg);
	}
	return true;
    }

    void showstack()
    {
	for (int j=0; j<sp; j++) {
	    System.out.println(val[j]);
	}
	System.out.println();
    }

    void push(double x)
    {
        if (sp<n) {
	    val[sp] = x;
	    sp++;
	}
    }

    double pop()
    {
	if (sp > 0) {
	    sp--;
	    return val[sp];
	} else {
	    return 0;
	}
    }

    void exp()
    {
	double x = X.fromNumberField();
	x = Math.exp(x);
	X.toNumberField(x);
    }

    void pi()
    {
	double x = X.fromNumberField();
	push(x);
	x = Math.PI;
	X.toNumberField(x);
    }

    void sin()
    {
	double x = X.fromNumberField();
	x = Math.sin(x);
	X.toNumberField(x);
    }

    void cos()
    {
	double x = X.fromNumberField();
	x = Math.cos(x);
	X.toNumberField(x);
    }

    void tan()
    {
	double x = X.fromNumberField();
	x = Math.tan(x);
	X.toNumberField(x);
    }

    void recip()
    {
	double x = X.fromNumberField();
	if (x != 0.0) {
	    x = 1/x;
	} else {
	    x = 0;
	}
	X.toNumberField(x);
    }

    void square()
    {
	double x = X.fromNumberField();
	x = x*x;
	X.toNumberField(x);
    }

    void sqrt()
    {
	double x = X.fromNumberField();
	x = Math.sqrt(Math.abs(x));
	X.toNumberField(x);
    }

    void log()
    {
	double x = X.fromNumberField();
	x = Math.log(Math.abs(x));
	X.toNumberField(x);
    }

    void power()
    {
	double x = X.fromNumberField();
	double y = pop();
	x = Math.pow(y,x);
	X.toNumberField(x);
    }

    void add()
    {
	double x = X.fromNumberField();
	double y = pop();
	x = x+y;
	X.toNumberField(x);
    }

    void subtr()
    {
	double x = X.fromNumberField();
	double y = pop();
	x = y-x;
	X.toNumberField(x);
    }

    void mult()
    {
	double x = X.fromNumberField();
	double y = pop();
	x = x*y;
	X.toNumberField(x);
    }

    void div()
    {
	double x = X.fromNumberField();
	double y = pop();
	x = y/x;
	X.toNumberField(x);
    }

    void enter()
    {
	double x = X.fromNumberField();
	push(x);
    }


    public boolean handleEvent(Event evt)
    {
	if (evt.id == Event.WINDOW_DESTROY) System.exit(0);
	return super.handleEvent(evt);
    }
}

class CFNumberField extends NumberField
{
    Calculator c;

    public CFNumberField(String label, int width, Calculator c)
    {
	super(label, width);
	this.c = c;
    }

    public boolean gotFocus(Event e, Object w)
    {
	c.enter();
	return super.gotFocus(e,w);
    }
}
