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

public class TestMatrixGUI extends Applet {
  Matrix3D matrix;
  MatrixDisplay matDisp;
  
  Panel controlPanel;


  BorderedPanel loadIdPanel;
  BorderedPanel translatePanel;
  BorderedPanel scalePanel;
  BorderedPanel skewPanel;
  BorderedPanel rotatePanel;
  BorderedPanel lookAtPanel;
  BorderedPanel perspectPanel;
  BorderedPanel orthoPanel;
  BorderedPanel setPanel;

  Button loadIdButton;
  Button translateButton;
  Button scaleButton;
  Button skewButton;
  Button rotateButton;
  Button lookAtButton;
  Button perspectButton;
  Button orthoButton;
  Button setButton;

  TextField[] fields;

  public boolean action(Event ev, Object arg) {

    if (ev.target == loadIdButton) {
      matrix.loadIdentity();
      matDisp.updateMatrix();
      return true;
    } else if (ev.target == translateButton) {
      float f0 = getFloat(fields[0]);
      float f1 = getFloat(fields[1]);
      float f2 = getFloat(fields[2]);
      matrix.translate(f0, f1, f2);
      matDisp.updateMatrix();
      return true;
    } else if (ev.target == scaleButton) {
      float f0 = getFloat(fields[3]);
      float f1 = getFloat(fields[4]);
      float f2 = getFloat(fields[5]);
      matrix.scale(f0, f1, f2);
      matDisp.updateMatrix();
      return true;
    } else if (ev.target == skewButton) {
      float f0 = getFloat(fields[6]);
      float f1 = getFloat(fields[7]);
      float f2 = getFloat(fields[8]);
      matrix.skew(f0, f1, f2);
      matDisp.updateMatrix();
      return true;
    } else if (ev.target == rotateButton) {
      float f0 = getFloat(fields[9]);
      float f1 = getFloat(fields[10]);
      float f2 = getFloat(fields[11]);
      float f3 = getFloat(fields[12]);
      matrix.rotate(f0, f1, f2, f3);
      matDisp.updateMatrix();
      return true;
    } else if (ev.target == lookAtButton) {
      float f0 = getFloat(fields[13]);
      float f1 = getFloat(fields[14]);
      float f2 = getFloat(fields[15]);
      float f3 = getFloat(fields[16]);
      float f4 = getFloat(fields[17]);
      float f5 = getFloat(fields[18]);
      float f6 = getFloat(fields[19]);
      float f7 = getFloat(fields[20]);
      float f8 = getFloat(fields[21]);
      matrix.lookAt(f0, f1, f2, f3, f4, f5, f6, f7, f8);
      matDisp.updateMatrix();
      return true;
    } else if (ev.target == perspectButton) {
      float f0 = getFloat(fields[22]);
      float f1 = getFloat(fields[23]);
      float f2 = getFloat(fields[24]);
      float f3 = getFloat(fields[25]);
      float f4 = getFloat(fields[26]);
      float f5 = getFloat(fields[27]);
      matrix.perspective(f0, f1, f2, f3, f4, f5);
      matDisp.updateMatrix();
      return true;
    } else if (ev.target == orthoButton) {
      float f0 = getFloat(fields[30]);
      float f1 = getFloat(fields[31]);
      float f2 = getFloat(fields[32]);
      float f3 = getFloat(fields[33]);
      float f4 = getFloat(fields[34]);
      float f5 = getFloat(fields[35]); 
      matrix.orthographic(f0, f1, f2, f3, f4, f5);
      matDisp.updateMatrix();
      return true;
    } else if (ev.target == setButton) {
      int f0 = getInt(fields[38]);
      int f1 = getInt(fields[39]);
      float f2 = getFloat(fields[40]);
      
      if (f0 > 0 && f1 > 0 && f0 <= 4 && f1 <= 4) {
	matrix.set(f0-1, f1-1, f2);	
	matDisp.updateMatrix();
      } else {
	showError("Locations indicated by set must be between " + 
		  "(1,1) and (4,4), inclusive");
      }
      return true;
    }
    
    return false;
  }

  private void initPanels() {
    controlPanel = new Panel();
    //controlPanel.setLayout(new GridLayout(9,1,3,3));
    GridBagLayout gbl = new GridBagLayout();
    controlPanel.setLayout(gbl);
    GridBagConstraints c = new GridBagConstraints();
    c.fill = GridBagConstraints.HORIZONTAL;
    c.gridwidth = GridBagConstraints.REMAINDER;
    
    
    loadIdPanel = new BorderedPanel();
    translatePanel = new BorderedPanel();
    scalePanel = new BorderedPanel();
    skewPanel = new BorderedPanel();
    rotatePanel = new BorderedPanel();
    lookAtPanel = new BorderedPanel();
    perspectPanel = new BorderedPanel();
    orthoPanel = new BorderedPanel();
    setPanel = new BorderedPanel();
    

    loadIdButton = new Button("Load Identity Matrix");
    translateButton = new Button("Translate Matrix");
    scaleButton = new Button("Scale Matrix");
    skewButton = new Button("Skew Matrix");
    rotateButton = new Button("Rotate Matrix");
    lookAtButton = new Button("LookAt Matrix"); 
    perspectButton = new Button("Perspective Transform Matrix");
    orthoButton = new Button("Orthographic Transform Matrix");
    setButton = new Button("Set element value");

    fields = new TextField[41];

    for (int i=0; i<fields.length; i++) {
      fields[i] = new TextField("0");
    }
    
    Panel sub;

    loadIdPanel.add(loadIdButton);

    translatePanel.add(translateButton);
    sub = new Panel();
    sub.setLayout(new GridLayout(1, 3));
    sub.add(fields[0]);
    sub.add(fields[1]);
    sub.add(fields[2]);
    translatePanel.add(sub);

    scalePanel.add(scaleButton);
    sub = new Panel();
    sub.setLayout(new GridLayout(1, 3));
    sub.add(fields[3]);
    sub.add(fields[4]);
    sub.add(fields[5]);
    scalePanel.add(sub);

    skewPanel.add(skewButton);
    sub = new Panel();
    sub.setLayout(new GridLayout(1, 3));
    sub.add(fields[6]);
    sub.add(fields[7]);
    sub.add(fields[8]);
    skewPanel.add(sub);

    rotatePanel.add(rotateButton);
    sub = new Panel();
    sub.setLayout(new GridLayout(1, 4));
    sub.add(fields[9]);
    sub.add(fields[10]);
    sub.add(fields[11]);
    sub.add(fields[12]);
    rotatePanel.add(sub);

    
    lookAtPanel.add(lookAtButton);
    sub = new Panel();
    sub.setLayout(new GridLayout(3, 3));
    sub.add(fields[13]);
    sub.add(fields[14]);
    sub.add(fields[15]);
    sub.add(fields[16]);
    sub.add(fields[17]);
    sub.add(fields[18]);
    sub.add(fields[19]);
    sub.add(fields[20]);
    sub.add(fields[21]);
    lookAtPanel.add(sub);

    perspectPanel.add(perspectButton);
    sub = new Panel();
    sub.setLayout(new GridLayout(2, 3));
    sub.add(fields[22]);
    sub.add(fields[23]);
    sub.add(fields[24]);
    sub.add(fields[25]);
    sub.add(fields[26]);
    sub.add(fields[27]);
    perspectPanel.add(sub);
    
    orthoPanel.add(orthoButton);
    sub = new Panel();
    sub.setLayout(new GridLayout(2, 3));
    sub.add(fields[30]);
    sub.add(fields[31]);
    sub.add(fields[32]);
    sub.add(fields[33]);
    sub.add(fields[34]);
    sub.add(fields[35]);
    orthoPanel.add(sub);

    setPanel.add(setButton);
    sub = new Panel();
    sub.setLayout(new GridLayout(1, 3));
    sub.add(fields[38]);
    sub.add(fields[39]);
    sub.add(fields[40]);
    setPanel.add(sub);
    
    controlPanel.add(loadIdPanel);
    controlPanel.add(translatePanel);
    controlPanel.add(scalePanel);
    controlPanel.add(skewPanel);
    controlPanel.add(rotatePanel);
    controlPanel.add(lookAtPanel);
    controlPanel.add(perspectPanel);
    controlPanel.add(orthoPanel);
    controlPanel.add(setPanel);

    gbl.setConstraints(loadIdPanel, c);
    gbl.setConstraints(translatePanel, c);
    gbl.setConstraints(scalePanel, c);
    gbl.setConstraints(skewPanel, c);
    gbl.setConstraints(rotatePanel, c);
    gbl.setConstraints(lookAtPanel, c);
    gbl.setConstraints(perspectPanel, c);
    gbl.setConstraints(orthoPanel, c);
    gbl.setConstraints(setPanel, c);


    add(controlPanel);
  }

  private void showError(String err) {
    
    ErrorDialog d = new ErrorDialog(err);
    d.resize(440, 200);
    d.show();
  }

  private float getFloat(TextField field) {
    
    float val;
    String s = field.getText();
    try {
      Float f = Float.valueOf(s);
      val = f.floatValue();
    } catch (NumberFormatException e) {
      showError("Please input a float instead of " + s);
      val = 1f;
    }	
    return val;

  }		

  private int getInt(TextField field) {
    
    int val;
    String s = field.getText();
    try {
      Integer f = Integer.valueOf(s);
      val = f.intValue();
    } catch (NumberFormatException e) {
      showError("Please input an integer instead of " + s);
      val = 1;
    }	
    return val;

  }		


  public void init() {
    matrix = new Matrix3D();		
    matDisp = new MatrixDisplay(matrix);
    add(matDisp);
    
    initPanels();
    
    repaint();
  }
  
}

class MatrixDisplay extends Panel {
  Matrix3D matrix;

  Label[] readout;

  MatrixDisplay(Matrix3D m) {
    matrix = m;
    setLayout( new GridLayout( 4, 4, 4, 4 ));
    readout = new Label[16];

    for (int i=0; i<4; i++) {
      for (int j=0; j<4; j++) {
	readout[i*4+j] = new Label(""+matrix.get(i,j));
	add(readout[i*4+j]);
      }
    }

    repaint();
  }

  void updateMatrix() {
    for (int i=0; i<4; i++) {
      for (int j=0; j<4; j++) {
	readout[i*4+j].setText(""+matrix.get(i,j));
	readout[i*4+j].invalidate();
      }
    }
    repaint();
  }	

  
}
