/*
 * This is the CurveControl class for the Famous Curves applet.
 * It controls the actions of a CurvePanel object (and also the
 * CurvePanel's Curve).
 * Author: Ben Soares < bs@st-and.ac.uk >
 *
 */

import java.awt.*;
import java.applet.*;
import java.util.Vector;

public class CurveControls extends Panel {
  
  // member variables
  
  CurvePanel curvepanel;
  Panel cards;
  Panel textcard;
  Panel controlcard;
  int cardposx = 0;
  int cardposy = 0;
  int showing;
  Choice curvechoice;
  TextPanel textpanel;
  final static String TEXTCARD = "textcard";
  final static String CONTROLCARD = "controlcard";
  Choice show;
  Choice reset;
  Button zoomin;
  Button zoomout;
  Button nozoom;
  PointButton up;
  PointButton down;
  PointButton left;
  PointButton right;
  PointButton centre;
  boolean parameters;
  boolean ap = false;
  boolean bp = false;
  boolean cp = false;
  boolean dp = false;
  boolean ep = false;
  boolean fp = false;
  boolean hp = false;
  boolean kp = false;
  boolean mp = false;
  boolean np = false;
  boolean pp = false;
  PointButton aleft = new PointButton("West", 10); Label alabel = new Label("a", Label.LEFT); PointButton aright = new PointButton("East", 10);
  PointButton bleft = new PointButton("West", 10); Label blabel = new Label("b", Label.LEFT); PointButton bright = new PointButton("East", 10);
  PointButton cleft = new PointButton("West", 10); Label clabel = new Label("c", Label.LEFT); PointButton cright = new PointButton("East", 10);
  PointButton dleft = new PointButton("West", 10); Label dlabel = new Label("d", Label.LEFT); PointButton dright = new PointButton("East", 10);
  PointButton eleft = new PointButton("West", 10); Label elabel = new Label("e", Label.LEFT); PointButton eright = new PointButton("East", 10);
  PointButton fleft = new PointButton("West", 10); Label flabel = new Label("f", Label.LEFT); PointButton fright = new PointButton("East", 10);
  PointButton hleft = new PointButton("West", 10); Label hlabel = new Label("h", Label.LEFT); PointButton hright = new PointButton("East", 10);
  PointButton kleft = new PointButton("West", 10); Label klabel = new Label("k", Label.LEFT); PointButton kright = new PointButton("East", 10);
  PointButton mleft = new PointButton("West", 10); Label mlabel = new Label("m", Label.LEFT); PointButton mright = new PointButton("East", 10);
  PointButton nleft = new PointButton("West", 10); Label nlabel = new Label("n", Label.LEFT); PointButton nright = new PointButton("East", 10);
  PointButton pleft = new PointButton("West", 10); Label plabel = new Label("p", Label.LEFT); PointButton pright = new PointButton("East", 10);
  double paramincrement = 0.1;			// parameter increment
  PointButton piup = new PointButton("North", 10); Label pilabel = new Label("inc", Label.CENTER); PointButton pidown = new PointButton("South", 10);
  
  // CurveControls constructor methods (2)
  
public CurveControls(CurvePanel curvepanel) {
  
  this.parameters = false;
  this.curvepanel = curvepanel;
  this.showing = 0;
  
  setBackground(Color.lightGray);
  
  GridBagLayout gb = new GridBagLayout();
  setFont(new Font("Helvetica", Font.PLAIN, 10));
  setLayout(gb);
  
  this.curvechoice = new Choice();
  curvechoice.addItem("Curve");
  curvechoice.addItem("Evolute");
  curvechoice.addItem("Involute");
  curvechoice.addItem("Inverse");
  curvechoice.addItem("Pedal");
  curvechoice.addItem("Negative Pedal");
  curvechoice.addItem("Caustic (radial)");
  curvechoice.addItem("Caustic (parallel)");
  
  GridBagConstraints c = new GridBagConstraints();
  
  c.gridx = 0;
  c.gridy = 0;
  c.gridwidth = 1;
  c.gridheight = 1;
  c.fill = GridBagConstraints.HORIZONTAL;
  gb.setConstraints(curvechoice, c);
  add(curvechoice);
  
  this.show = new Choice();
  show.addItem("Controls");
  show.addItem("Instructions");
  show.addItem("Definition");
  c.weightx = 0.0;
  c.weighty = 0.0;
  c.gridx = 1;
  c.gridy = 1;
  c.gridwidth = 1;
  gb.setConstraints(show, c);
  add(show);
  
  this.reset = new Choice();
  reset.addItem("Slow");
  reset.addItem("Medium");
  reset.addItem("Fast");
  reset.addItem("RESET");
  c.gridx = 0;
  c.gridy = 2;
  c.gridwidth = 1;
  gb.setConstraints(reset, c);
  add(reset);  
  
  Vector temp = new Vector(2);
  temp.addElement("Choose an associated curve");
  temp.addElement("from the list on the left.");
  this.textpanel = new TextPanel(temp);
  c.fill = GridBagConstraints.BOTH;
  c.weightx = 1.0;
  c.weighty = 1.0;
  c.gridx = 1;
  c.gridy = 0;
  c.gridwidth = 1;
  c.gridheight = 3;
  gb.setConstraints(textpanel, c);
  add(textpanel);
  
  this.zoomin = new Button("+10%");
  c.fill = GridBagConstraints.NONE;
  c.weightx = 0.0;
  c.weighty = 0.0;
  c.gridx = 2;
  c.gridy = 0;
  c.gridwidth = 1;
  c.gridheight = 1;
  gb.setConstraints(zoomin, c);
  add(zoomin);
  
  this.nozoom = new Button("100%");
  c.gridy = 1;
  gb.setConstraints(nozoom, c);
  add(nozoom);
  
  this.zoomout = new Button("-10%");
  c.gridy = 2;
  gb.setConstraints(zoomout, c);
  add(zoomout);
  
  this.up = new PointButton("North", 10);
  c.gridx = 4;
  c.gridy = 0;
  c.fill = GridBagConstraints.NONE;
  gb.setConstraints(up, c);
  add(up);
  
  this.left = new PointButton("West", 10);
  c.gridx = 3;
  c.gridy = 1;
  gb.setConstraints(left, c);
  add(left);
  
  this.right = new PointButton("East", 10);
  c.gridx = 5;
  gb.setConstraints(right, c);
  add(right);
  
  this.down = new PointButton("South", 10);
  c.gridx = 4;
  c.gridy = 2;
  gb.setConstraints(down, c);
  add(down);
  
  this.centre = new PointButton("Square", 10);
  c.gridy = 1;
  gb.setConstraints(centre, c);
  add(centre);
  
  validate();
  
} /* end of constructor method 1 */
  
  // beginning of constructor method 2 (recommended use)
  
public CurveControls(CurvePanel curvepanel, boolean ap, boolean bp, boolean cp, boolean dp, boolean ep, boolean fp, boolean hp, boolean kp, boolean mp, boolean np, boolean pp) {
  
  this.curvepanel = curvepanel;
  this.showing = 0;
  this.ap = ap;
  this.bp = bp;
  this.cp = cp;
  this.dp = dp;
  this.ep = ep;
  this.fp = fp;
  this.hp = hp;
  this.kp = kp;
  this.mp = mp;
  this.np = np;
  this.pp = pp;
  this.parameters = true;
  int numberofparameters = 0;
  if (ap) { numberofparameters++; }
  if (bp) { numberofparameters++; }
  if (cp) { numberofparameters++; }
  if (dp) { numberofparameters++; }
  if (ep) { numberofparameters++; }
  if (fp) { numberofparameters++; }
  if (hp) { numberofparameters++; }
  if (kp) { numberofparameters++; }
  if (mp) { numberofparameters++; }
  if (np) { numberofparameters++; }
  if (pp) { numberofparameters++; }
  
  setBackground(Color.lightGray);
  
  GridBagLayout gb = new GridBagLayout();
  setFont(new Font("Helvetica", Font.PLAIN, 10));
  setLayout(gb);
  
  this.cards = new Panel();
  cards.setLayout(new CardLayout());
  this.textcard = new Panel();
  GridBagLayout tcgb = new GridBagLayout();
  textcard.setLayout(tcgb);
  this.controlcard = new Panel();
  GridBagLayout ccgb = new GridBagLayout();
  controlcard.setLayout(ccgb);
  
  this.curvechoice = new Choice();
  curvechoice.addItem("Curve");
  curvechoice.addItem("Evolute");
  curvechoice.addItem("Involute");
  curvechoice.addItem("Inverse");
  curvechoice.addItem("Pedal");
  curvechoice.addItem("Negative Pedal");
  curvechoice.addItem("Caustic (radial)");
  curvechoice.addItem("Caustic (parallel)");
  
  GridBagConstraints c = new GridBagConstraints();
  
  c.gridx = 1;
  c.gridy = 0;
  c.weightx = 1;
  c.gridwidth = 1;
  c.gridheight = 1;
  c.fill = GridBagConstraints.HORIZONTAL;
  gb.setConstraints(curvechoice, c);
  add(curvechoice);
  
  Label blank0 = new Label("       ");
  c.gridx = 0;
  gb.setConstraints(blank0, c);
  add(blank0);
  
  Label blank1 = new Label("         ");
  c.gridx = 2;
  gb.setConstraints(blank1, c);
  add(blank1);
  
  this.show = new Choice();
  show.addItem("Controls");
  show.addItem("Instructions");
  show.addItem("Definition");
  c.gridx = 3;
  c.gridwidth = 1;
  gb.setConstraints(show, c);
  add(show);
  
  Label blank2 = new Label("         ");
  c.gridx = 4;
  gb.setConstraints(blank2, c);
  add(blank2);
  
  this.reset = new Choice();
  reset.addItem("Slow");
  reset.addItem("Medium");
  reset.addItem("Fast");
  reset.addItem("RESET");
  c.gridx = 5;
  c.gridwidth = 1;
  gb.setConstraints(reset, c);
  add(reset);
  reset.select(1);
  
  Label blankr = new Label("        ");
  c.gridx = 6;
  gb.setConstraints(blankr, c);
  add(blankr);
  
  Vector temp = new Vector(2);
  temp.addElement("Choose an associated curve");
  temp.addElement("from the list above left.");
  this.textpanel = new TextPanel(temp);
  c = new GridBagConstraints();
  c.gridx = 0;
  c.gridy = 0;
  c.weightx = 1;
  c.weighty = 1;
  c.fill = GridBagConstraints.BOTH;
  tcgb.setConstraints(textpanel, c);
  textcard.add(textpanel);
  textcard.validate();
  
  c = new GridBagConstraints();
  c.anchor = GridBagConstraints.CENTER;
  c.insets = new Insets(1, 1, 1, 1);
  c.weightx = 1;
  c.weighty = 1;
  Label blank3 = new Label("   ");
  c.gridx = 4;
  c.gridy = 1;
  c.fill = GridBagConstraints.HORIZONTAL;
  ccgb.setConstraints(blank3, c);
  controlcard.add(blank3);
  Label blank4 = new Label("      ");
  c.gridx = c.gridx+2;
  ccgb.setConstraints(blank4, c);
  controlcard.add(blank4);
  c.fill = GridBagConstraints.NONE;
  
  this.zoomin = new Button("+10%");
  c.gridx = c.gridx-1;
  c.gridy = Math.max(1, numberofparameters-2);
  ccgb.setConstraints(zoomin, c);
  controlcard.add(zoomin);
  
  this.nozoom = new Button("100%");
  c.gridy = c.gridy+1;
  ccgb.setConstraints(nozoom, c);
  controlcard.add(nozoom);
  
  this.zoomout = new Button("-10%");
  c.gridy = c.gridy+1;
  ccgb.setConstraints(zoomout, c);
  controlcard.add(zoomout);
  
  this.up = new PointButton("North", 10);
  c.gridx = c.gridx+3;
  c.gridy = c.gridy-2;
  ccgb.setConstraints(up, c);
  controlcard.add(up);
  
  this.left = new PointButton("West", 10);
  c.gridx = c.gridx-1;
  c.gridy = c.gridy+1;
  ccgb.setConstraints(left, c);
  controlcard.add(left);
  
  this.right = new PointButton("East", 10);
  c.gridx = c.gridx+2;
  ccgb.setConstraints(right, c);
  controlcard.add(right);
  
  this.down = new PointButton("South", 10);
  c.gridx = c.gridx-1;
  c.gridy = c.gridy+1;
  ccgb.setConstraints(down, c);
  controlcard.add(down);
  
  this.centre = new PointButton("Square", 10);
  c.gridy = c.gridy-1;
  ccgb.setConstraints(centre, c);
  controlcard.add(centre);
  
  c.gridy = Math.max(3, numberofparameters);
  c.gridwidth = 1;
  c.gridheight = 1;
  c.fill = GridBagConstraints.NONE;
  
  // next three items are the parameter increment controls and label
  if (numberofparameters>0) {
    c.anchor = GridBagConstraints.CENTER;
    c.gridx = 3;
    ccgb.setConstraints(pidown, c);
    controlcard.add(pidown);
    c.gridy -= 2;
    ccgb.setConstraints(piup, c);
    controlcard.add(piup);
    c.gridy++;
    c.fill = GridBagConstraints.HORIZONTAL;
    pilabel.setText("  inc="+paramincrement+"  ");
    ccgb.setConstraints(pilabel, c);
    controlcard.add(pilabel);
    c.gridy++;
  }
  // next lot of ifs adds the parameter control buttons (starting at the bottom)
  if (pp) {
    plabel.setText("  p="+curvepanel.curve.p+"  ");
    c.gridx = 0;
    ccgb.setConstraints(pleft, c);
    controlcard.add(pleft);
    c.gridx = 1;
    ccgb.setConstraints(plabel, c);
    controlcard.add(plabel);
    c.gridx = 2;
    ccgb.setConstraints(pright, c);
    controlcard.add(pright);
    c.gridy--;
  }
  if (np) {
    nlabel.setText("  n="+curvepanel.curve.n+"  ");
    c.gridx = 0;
    ccgb.setConstraints(nleft, c);
    controlcard.add(nleft);
    c.gridx = 1;
    ccgb.setConstraints(nlabel, c);
    controlcard.add(nlabel);
    c.gridx = 2;
    ccgb.setConstraints(nright, c);
    controlcard.add(nright);
    c.gridy--;
  }
  if (mp) {
    mlabel.setText("  m="+curvepanel.curve.m+"  ");
    c.gridx = 0;
    ccgb.setConstraints(mleft, c);
    controlcard.add(mleft);
    c.gridx = 1;
    ccgb.setConstraints(mlabel, c);
    controlcard.add(mlabel);
    c.gridx = 2;
    ccgb.setConstraints(mright, c);
    controlcard.add(mright);
    c.gridy--;
  }
  if (kp) {
    klabel.setText("  k="+curvepanel.curve.k+"  ");
    c.gridx = 0;
    ccgb.setConstraints(kleft, c);
    controlcard.add(kleft);
    c.gridx = 1;
    ccgb.setConstraints(klabel, c);
    controlcard.add(klabel);
    c.gridx = 2;
    ccgb.setConstraints(kright, c);
    controlcard.add(kright);
    c.gridy--;
  }
  if (hp) {
    hlabel.setText("  h="+curvepanel.curve.h+"  ");
    c.gridx = 0;
    ccgb.setConstraints(hleft, c);
    controlcard.add(hleft);
    c.gridx = 1;
    ccgb.setConstraints(hlabel, c);
    controlcard.add(hlabel);
    c.gridx = 2;
    ccgb.setConstraints(hright, c);
    controlcard.add(hright);
    c.gridy--;
  }
  if (fp) {
    flabel.setText("  f="+curvepanel.curve.f+"  ");
    c.gridx = 0;
    ccgb.setConstraints(fleft, c);
    controlcard.add(fleft);
    c.gridx = 1;
    ccgb.setConstraints(flabel, c);
    controlcard.add(flabel);
    c.gridx = 2;
    ccgb.setConstraints(fright, c);
    controlcard.add(fright);
    c.gridy--;
  }
  if (ep) {
    elabel.setText("  e="+curvepanel.curve.e+"  ");
    c.gridx = 0;
    ccgb.setConstraints(eleft, c);
    controlcard.add(eleft);
    c.gridx = 1;
    ccgb.setConstraints(elabel, c);
    controlcard.add(elabel);
    c.gridx = 2;
    ccgb.setConstraints(eright, c);
    controlcard.add(eright);
    c.gridy--;
  }
  if (dp) {
    dlabel.setText("  d="+curvepanel.curve.d+"  ");
    c.gridx = 0;
    ccgb.setConstraints(dleft, c);
    controlcard.add(dleft);
    c.gridx = 1;
    ccgb.setConstraints(dlabel, c);
    controlcard.add(dlabel);
    c.gridx = 2;
    ccgb.setConstraints(dright, c);
    controlcard.add(dright);
    c.gridy--;
  }
  if (cp) {
    clabel.setText("  c="+curvepanel.curve.c+"  ");
    c.gridx = 0;
    ccgb.setConstraints(cleft, c);
    controlcard.add(cleft);
    c.gridx = 1;
    ccgb.setConstraints(clabel, c);
    controlcard.add(clabel);
    c.gridx = 2;
    ccgb.setConstraints(cright, c);
    controlcard.add(cright);
    c.gridy--;
  }
  if (bp) {
    blabel.setText("  b="+curvepanel.curve.b+"  ");
    c.gridx = 0;
    ccgb.setConstraints(bleft, c);
    controlcard.add(bleft);
    c.gridx = 1;
    ccgb.setConstraints(blabel, c);
    controlcard.add(blabel);
    c.gridx = 2;
    ccgb.setConstraints(bright, c);
    controlcard.add(bright);
    c.gridy--;
  }
  if (ap) {
    alabel.setText("  a="+curvepanel.curve.a+"  ");
    c.gridx = 0;
    ccgb.setConstraints(aleft, c);
    controlcard.add(aleft);
    c.gridx = 1;
    ccgb.setConstraints(alabel, c);
    controlcard.add(alabel);
    c.gridx = 2;
    ccgb.setConstraints(aright, c);
    controlcard.add(aright);
  }
  
  controlcard.validate();
  
  cards.add(CONTROLCARD, controlcard);
  cards.add(TEXTCARD, textcard);
  cards.validate();
  
  c = new GridBagConstraints();
  c.gridx = 1;
  c.gridy = 1;
  c.gridwidth = 5;
  c.gridheight = 2;
  c.fill = GridBagConstraints.BOTH;
  gb.setConstraints(cards, c);
  add(cards);
  
  validate();
  
  
} /* end of constructor methods */
  
  // beginning of paint method
  
public void paint(Graphics g) {
  
  
} /* end of paint method */
  
  // beginning of action method
  
public boolean action(Event e, Object arg) {
  
  if (e.target instanceof Choice) {
    if (e.target == curvechoice) {
      int i = curvechoice.getSelectedIndex();
      switch (i) {
      case 0:     
	break;
      case 1:
	curvepanel.associatedcurve = curvepanel.curve.evolutePixels();
	break;
      case 2:
	break;
      case 3:
	break;
      case 4:
	break;
      case 5:
	break;
      case 6:
	break;
      case 7:
	break;
      }
      if (showing==0) {
	printcontrols();
      } else if (showing==1) {
	printinstructions(i);
      } else if (showing==2) {
	printdefinition(i);
      }
      curvepanel.associatedcurveindex = i;
      curvepanel.pointstage = 0;
      curvepanel.circlestage = 0;
      curvepanel.clear = true;
    } else if (e.target == show) {
      showing = show.getSelectedIndex();
      switch (showing) {
      case 0:
	printcontrols();
	break;
      case 1:
	printinstructions(curvechoice.getSelectedIndex());
	break;
      case 2:
	printdefinition(curvechoice.getSelectedIndex());
	break;
      }
    } else if (e.target == reset) {
      switch(reset.getSelectedIndex()) {
      case 0:
	curvepanel.steps = 1;
	break;
      case 1:
	curvepanel.steps = 2;
	break;
      case 2:
	curvepanel.steps = 4;
	break;
      case 3:
	curvepanel.resetCurveParameters();
	this.alabel.setText("a="+curvepanel.curve.a);
	this.blabel.setText("b="+curvepanel.curve.b);
	this.clabel.setText("c="+curvepanel.curve.c);
	this.dlabel.setText("d="+curvepanel.curve.d);
	this.elabel.setText("e="+curvepanel.curve.e);
	this.flabel.setText("f="+curvepanel.curve.f);
	this.hlabel.setText("h="+curvepanel.curve.h);
	this.klabel.setText("k="+curvepanel.curve.k);
	this.mlabel.setText("m="+curvepanel.curve.m);
	this.nlabel.setText("n="+curvepanel.curve.n);
	this.plabel.setText("p="+curvepanel.curve.p);
	curvepanel.curve.setCurve();
	curvepanel.pointstage = 0;
	curvepanel.circlestage = 0;
	curvepanel.pointX = 0;
	curvepanel.pointY = 0;
	curvepanel.circleX = 0;
	curvepanel.circleY = 0;
	curvepanel.circleCX = 0;
	curvepanel.circleCY = 0;
	curvepanel.circleR = 0;
	curvepanel.associatedcurveindex = 0;
	curvepanel.clear = false;
	curvepanel.setaxis = false;
	curvepanel.steps = 1;
	this.reset.select(1);
	this.showing = 0;
	this.show.select(0);
	this.curvechoice.select(0);
	this.printcontrols();
	break;
      }
    }   	
  } else if (e.target instanceof Button) {
    if (e.target == zoomin) {
      curvepanel.curve.scale(1.10);
      curvepanel.scale(1.10);
    } else if (e.target == zoomout) {
      curvepanel.curve.scale(0.90);
      curvepanel.scale(0.90);
    } else if (e.target == nozoom) {
      int sc = (int)(curvepanel.size().height/curvepanel.curve.yrange);
      double oldsc = curvepanel.curve.xsc;
      curvepanel.scale(sc/oldsc);
      curvepanel.curve.scale(sc/oldsc);
    }
  }
  if (e.target != show)  {
    curvepanel.recalculate();
    curvepanel.repaint();
  }
  return true;
  
} /* end of action method */
  
  // mouseUp, mouseDrag and mouseDown methods (required to detect a PointButton depression)
public boolean mouseDown(Event e, int mx, int my) {
  // these are the translation buttons
  if (e.target == up) {
    up.fill = true;
    up.repaint();
  } else if (e.target == down) {
    down.fill = true;
    down.repaint();
  } else if (e.target == left) {
    left.fill = true;
    left.repaint();
  } else if (e.target == right) {
    right.fill = true;
    right.repaint();
  } else if (e.target == centre) {
    centre.fill = true;
    centre.repaint();
    // these are the parameter increment adjustment buttons
  } else if (e.target == piup) {
    piup.fill = true;
    piup.repaint();
  } else if (e.target == pidown) {
    pidown.fill = true;
    pidown.repaint();
    // these are the parameter adjustment buttons
  } else if (e.target == aleft) {
    aleft.fill = true;
    aleft.repaint();
  } else if (e.target == aright) {
    aright.fill = true;
    aright.repaint();
  } else if (e.target == bleft) {
    bleft.fill = true;
    bleft.repaint();
  } else if (e.target == bright) {
    bright.fill = true;
    bright.repaint();
  } else if (e.target == cleft) {
    cleft.fill = true;
    cleft.repaint();
  } else if (e.target == cright) {
    cright.fill = true;
    cright.repaint();
  } else if (e.target == dleft) {
    dleft.fill = true;
    dleft.repaint();
  } else if (e.target == dright) {
    dright.fill = true;
    dright.repaint();
  } else if (e.target == eleft) {
    eleft.fill = true;
    eleft.repaint();
  } else if (e.target == eright) {
    eright.fill = true;
    eright.repaint();
  } else if (e.target == fleft) {
    fleft.fill = true;
    fleft.repaint();
  } else if (e.target == fright) {
    fright.fill = true;
    fright.repaint();
  } else if (e.target == hleft) {
    hleft.fill = true;
    hleft.repaint();
  } else if (e.target == hright) {
    hright.fill = true;
    hright.repaint();
  } else if (e.target == kleft) {
    kleft.fill = true;
    kleft.repaint();
  } else if (e.target == kright) {
    kright.fill = true;
    kright.repaint();
  } else if (e.target == mleft) {
    mleft.fill = true;
    mleft.repaint();
  } else if (e.target == mright) {
    mright.fill = true;
    mright.repaint();
  } else if (e.target == nleft) {
    nleft.fill = true;
    nleft.repaint();
  } else if (e.target == nright) {
    nright.fill = true;
    nright.repaint();
  } else if (e.target == pleft) {
    pleft.fill = true;
    pleft.repaint();
  } else if (e.target == pright) {
    pright.fill = true;
    pright.repaint();
  }
  return true;
}
public boolean mouseDrag(Event e, int mx1, int my1) {
  int mx = mx1;
  int my = my1;
  // these are the translation buttons
  if (e.target == up) {
    if (up.inside(mx, my)) { up.fill = true; } else { up.fill = true; }
    up.repaint();
  } else if (e.target == down) {
    if (down.inside(mx, my) ) { down.fill = false; } else { down.fill = true; }
    down.repaint();
  } else if (e.target == left) {
    if (left.inside(mx, my) ) { left.fill = false; } else { left.fill = true; }
    left.repaint();
  } else if (e.target == right) {
    if (right.inside(mx, my) ) { right.fill = false; } else { right.fill = true; }
    right.repaint();
  } else if (e.target == centre) {
    if (centre.inside(mx, my) ) { centre.fill = false; } else { centre.fill = true; }
    centre.repaint();
    // these are the parameter increment adjustment buttons
  } else if (e.target == piup) {
    if (piup.inside(mx, my) ) { piup.fill = false; } else { piup.fill = true; }
    piup.repaint();
  } else if (e.target == pidown) {
    if (pidown.inside(mx, my) ) { pidown.fill = false; } else { pidown.fill = true; }
    pidown.repaint();
    // these are the parameter adjustment buttons
  } else if (e.target == aleft) {
    if (aleft.inside(mx, my) ) { aleft.fill = false; } else { aleft.fill = true; }
    aleft.repaint();
  } else if (e.target == aright) {
    if (aright.inside(mx, my) ) { aright.fill = false; } else { aright.fill = true; }
    aright.repaint();
  } else if (e.target == bleft) {
    if (bleft.inside(mx, my) ) { bleft.fill = false; } else { bleft.fill = true; }
    bleft.repaint();
  } else if (e.target == bright) {
    if (bright.inside(mx, my) ) { bright.fill = false; } else { bright.fill = true; }
    bright.repaint();
  } else if (e.target == cleft) {
    if (cleft.inside(mx, my) ) { cleft.fill = false; } else { cleft.fill = true; }
    cleft.repaint();
  } else if (e.target == cright) {
    if (cright.inside(mx, my) ) { cright.fill = false; } else { cright.fill = true; }
    cright.repaint();
  } else if (e.target == dleft) {
    if (dleft.inside(mx, my) ) { dleft.fill = false; } else { dleft.fill = true; }
    dleft.repaint();
  } else if (e.target == dright) {
    if (dright.inside(mx, my) ) { dright.fill = false; } else { dright.fill = true; }
    dright.repaint();
  } else if (e.target == eleft) {
    if (eleft.inside(mx, my) ) { eleft.fill = false; } else { eleft.fill = true; }
    eleft.repaint();
  } else if (e.target == eright) {
    if (eright.inside(mx, my) ) { eright.fill = false; } else { eright.fill = true; }
    eright.repaint();
  } else if (e.target == fleft) {
    if (fleft.inside(mx, my) ) { fleft.fill = false; } else { fleft.fill = true; }
    fleft.repaint();
  } else if (e.target == fright) {
    if (fright.inside(mx, my) ) { fright.fill = false; } else { fright.fill = true; }
    fright.repaint();
  } else if (e.target == hleft) {
    if (hleft.inside(mx, my) ) { hleft.fill = false; } else { hleft.fill = true; }
    hleft.repaint();
  } else if (e.target == hright) {
    if (hright.inside(mx, my) ) { hright.fill = false; } else { hright.fill = true; }
    hright.repaint();
  } else if (e.target == kleft) {
    if (kleft.inside(mx, my) ) { kleft.fill = false; } else { kleft.fill = true; }
    kleft.repaint();
  } else if (e.target == kright) {
    if (kright.inside(mx, my) ) { kright.fill = false; } else { kright.fill = true; }
    kright.repaint();
  } else if (e.target == mleft) {
    if (mleft.inside(mx, my) ) { mleft.fill = false; } else { mleft.fill = true; }
    mleft.repaint();
  } else if (e.target == mright) {
    if (mright.inside(mx, my) ) { mright.fill = false; } else { mright.fill = true; }
    mright.repaint();
  } else if (e.target == nleft) {
    if (nleft.inside(mx, my) ) { nleft.fill = false; } else { nleft.fill = true; }
    nleft.repaint();
  } else if (e.target == nright) {
    if (nright.inside(mx, my) ) { nright.fill = false; } else { nright.fill = true; }
    nright.repaint();
  } else if (e.target == pleft) {
    if (pleft.inside(mx, my) ) { pleft.fill = false; } else { pleft.fill = true; }
    pleft.repaint();
  } else if (e.target == pright) {
    if (pright.inside(mx, my) ) { pright.fill = false; } else { pright.fill = true; }
    pright.repaint();
  }
  return true;
}
public boolean mouseUp(Event e, int mx, int my)  {
  boolean redraw = true;
  // these are the translation buttons
  if (up.fill && e.target == up) {
    up.fill = false;
    curvepanel.curve.translate(0, -5);
    curvepanel.translate(0, -5);
    up.repaint();
  } else if (down.fill && e.target == down) {
    down.fill = false;
    curvepanel.curve.translate(0, 5);
    curvepanel.translate(0, 5);
    down.repaint();
  } else if (left.fill && e.target == left) {
    left.fill = false;
    curvepanel.curve.translate(-5, 0);
    curvepanel.translate(-5, 0);
    left.repaint();
  } else if (right.fill && e.target == right) {
    right.fill = false;
    curvepanel.curve.translate(5, 0);
    curvepanel.translate(5, 0);
    right.repaint();
  } else if (centre.fill && e.target == centre) {
    centre.fill = false;
    int tx = curvepanel.curve.Ox;
    int ty = curvepanel.curve.Oy;
    curvepanel.curve.translate((int)(curvepanel.size().width/2 - tx), (int)(curvepanel.size().height/2 - ty));
    curvepanel.translate((int)(curvepanel.size().width/2 - tx), (int)(curvepanel.size().height/2 - ty));
    centre.repaint();
  }
  // these are the parameter incremenet adjustment buttons
  if (pidown.fill && e.target == pidown) {
    pidown.fill = false;
    if (Math.abs(paramincrement)>10) {
      paramincrement -= 10;
    } else if (Math.abs(paramincrement)>1) {
      paramincrement -= 1;
    } else if (Math.abs(paramincrement)>0) {
      paramincrement -= 0.1;
    }
    if (Math.abs(paramincrement)<0.05) { paramincrement = 0.0; }
    this.pilabel.setText("inc="+paramincrement);
    pidown.repaint();
    redraw = false;
  } else if (piup.fill && e.target == piup) {
    piup.fill = false;
    if (Math.abs(paramincrement)>9) {
      paramincrement += 10;
    } else if (Math.abs(paramincrement)>=0.9) {
      paramincrement += 1;
    } else {
      paramincrement += 0.1;
    }
    if (Math.abs(paramincrement)<0.05) { paramincrement = 0.0; }
    this.pilabel.setText("inc="+paramincrement);
    piup.repaint();
    redraw = false;
  }
  // these are the parameter adjustment buttons
  if (aleft.fill && e.target == aleft) {
    aleft.fill = false;
    curvepanel.curve.a -= paramincrement;
    if (Math.abs(curvepanel.curve.a)<0.05) { curvepanel.curve.a = 0.0; }
    curvepanel.curve.setCurve();
    this.alabel.setText("a="+curvepanel.curve.a);
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    aleft.repaint();
  } else if (aright.fill && e.target == aright) {
    aright.fill = false;
    curvepanel.curve.a += paramincrement;
    if (Math.abs(curvepanel.curve.a)<0.05) { curvepanel.curve.a = 0.0; }
    curvepanel.curve.setCurve();
    this.alabel.setText("a="+curvepanel.curve.a); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    aright.repaint();
  } else if (bleft.fill && e.target == bleft) {
    bleft.fill = false;
    curvepanel.curve.b -= paramincrement;
    if (Math.abs(curvepanel.curve.b)<0.05) { curvepanel.curve.b = 0.0; }
    curvepanel.curve.setCurve();
    this.blabel.setText("b="+curvepanel.curve.b); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    bleft.repaint();
  } else if (bright.fill && e.target == bright) {
    bright.fill = false;
    curvepanel.curve.b += paramincrement;
    if (Math.abs(curvepanel.curve.b)<0.05) { curvepanel.curve.b = 0.0; }
    curvepanel.curve.setCurve();
    this.blabel.setText("b="+curvepanel.curve.b); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    bright.repaint();
  } else if (cleft.fill && e.target == cleft) {
    cleft.fill = false;
    curvepanel.curve.c -= paramincrement;
    if (Math.abs(curvepanel.curve.c)<0.05) { curvepanel.curve.c = 0.0; }
    curvepanel.curve.setCurve();
    this.clabel.setText("c="+curvepanel.curve.c); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    cleft.repaint();
  } else if (cright.fill && e.target == cright) {
    cright.fill = false;
    curvepanel.curve.c += paramincrement;
    if (Math.abs(curvepanel.curve.c)<0.05) { curvepanel.curve.c = 0.0; }
    curvepanel.curve.setCurve();
    this.clabel.setText("c="+curvepanel.curve.c); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    cright.repaint();
  } else if (dleft.fill && e.target == dleft) {
    dleft.fill = false;
    curvepanel.curve.d -= paramincrement;
    if (Math.abs(curvepanel.curve.d)<0.05) { curvepanel.curve.d = 0.0; }
    curvepanel.curve.setCurve();
    this.dlabel.setText("d="+curvepanel.curve.d); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    dleft.repaint();
  } else if (dright.fill && e.target == dright) {
    dright.fill = false;
    curvepanel.curve.d += paramincrement;
    if (Math.abs(curvepanel.curve.d)<0.05) { curvepanel.curve.d = 0.0; }
    curvepanel.curve.setCurve();
    this.dlabel.setText("d="+curvepanel.curve.d); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    dright.repaint();
  } else if (eleft.fill && e.target == eleft) {
    eleft.fill = false;
    curvepanel.curve.e -= paramincrement;
    if (Math.abs(curvepanel.curve.e)<0.05) { curvepanel.curve.e = 0.0; }
    curvepanel.curve.setCurve();
    this.elabel.setText("e="+curvepanel.curve.e); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    eleft.repaint();
  } else if (eright.fill && e.target == eright) {
    eright.fill = false;
    curvepanel.curve.e += paramincrement;
    if (Math.abs(curvepanel.curve.e)<0.05) { curvepanel.curve.e = 0.0; }
    curvepanel.curve.setCurve();
    this.elabel.setText("e="+curvepanel.curve.e); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    eright.repaint();
  } else if (fleft.fill && e.target == fleft) {
    fleft.fill = false;
    curvepanel.curve.f -= paramincrement;
    if (Math.abs(curvepanel.curve.f)<0.05) { curvepanel.curve.f = 0.0; }
    curvepanel.curve.setCurve();
    this.flabel.setText("f="+curvepanel.curve.f); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    fleft.repaint();
  } else if (fright.fill && e.target == fright) {
    fright.fill = false;
    curvepanel.curve.f += paramincrement;
    if (Math.abs(curvepanel.curve.f)<0.05) { curvepanel.curve.f = 0.0; }
    curvepanel.curve.setCurve();
    this.flabel.setText("f="+curvepanel.curve.f); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    fright.repaint();
  } else if (hleft.fill && e.target == hleft) {
    hleft.fill = false;
    curvepanel.curve.h -= paramincrement;
    if (Math.abs(curvepanel.curve.h)<0.05) { curvepanel.curve.h = 0.0; }
    curvepanel.curve.setCurve();
    this.hlabel.setText("h="+curvepanel.curve.h); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    hleft.repaint();
  } else if (hright.fill && e.target == hright) {
    hright.fill = false;
    curvepanel.curve.h += paramincrement;
    if (Math.abs(curvepanel.curve.h)<0.05) { curvepanel.curve.h = 0.0; }
    curvepanel.curve.setCurve();
    this.hlabel.setText("h="+curvepanel.curve.h); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    hright.repaint();
  } else if (kleft.fill && e.target == kleft) {
    kleft.fill = false;
    curvepanel.curve.k -= paramincrement;
    if (Math.abs(curvepanel.curve.k)<0.05) { curvepanel.curve.k = 0.0; }
    curvepanel.curve.setCurve();
    this.klabel.setText("k="+curvepanel.curve.k); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    kleft.repaint();
  } else if (kright.fill && e.target == kright) {
    kright.fill = false;
    curvepanel.curve.k += paramincrement;
    if (Math.abs(curvepanel.curve.k)<0.05) { curvepanel.curve.k = 0.0; }
    curvepanel.curve.setCurve();
    this.klabel.setText("k="+curvepanel.curve.k); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    kright.repaint();
  } else if (mleft.fill && e.target == mleft) {
    mleft.fill = false;
    curvepanel.curve.m -= paramincrement;
    if (Math.abs(curvepanel.curve.m)<0.05) { curvepanel.curve.m = 0.0; }
    curvepanel.curve.setCurve();
    this.mlabel.setText("m="+curvepanel.curve.m); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    mleft.repaint();
  } else if (mright.fill && e.target == mright) {
    mright.fill = false;
    curvepanel.curve.m += paramincrement;
    if (Math.abs(curvepanel.curve.m)<0.05) { curvepanel.curve.m = 0.0; }
    curvepanel.curve.setCurve();
    this.mlabel.setText("m="+curvepanel.curve.m); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    mright.repaint();
  } else if (nleft.fill && e.target == nleft) {
    nleft.fill = false;
    curvepanel.curve.n -= paramincrement;
    if (Math.abs(curvepanel.curve.n)<0.05) { curvepanel.curve.n = 0.0; }
    curvepanel.curve.setCurve();
    this.nlabel.setText("n="+curvepanel.curve.n); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    nleft.repaint();
  } else if (nright.fill && e.target == nright) {
    nright.fill = false;
    curvepanel.curve.n += paramincrement;
    if (Math.abs(curvepanel.curve.n)<0.05) { curvepanel.curve.n = 0.0; }
    curvepanel.curve.setCurve();
    this.nlabel.setText("n="+curvepanel.curve.n); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    nright.repaint();
  } else if (pleft.fill && e.target == pleft) {
    pleft.fill = false;
    curvepanel.curve.p -= paramincrement;
    if (Math.abs(curvepanel.curve.p)<0.05) { curvepanel.curve.p = 0.0; }
    curvepanel.curve.setCurve();
    this.plabel.setText("p="+curvepanel.curve.p); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    pleft.repaint();
  } else if (pright.fill && e.target == pright) {
    pright.fill = false;
    curvepanel.curve.p += paramincrement;
    if (Math.abs(curvepanel.curve.p)<0.05) { curvepanel.curve.p = 0.0; }
    curvepanel.curve.setCurve();
    this.plabel.setText("p="+curvepanel.curve.p); 
    curvepanel.curve.translate(0, 0);
    curvepanel.translate(0, 0);
    pright.repaint();
  }
  if (redraw) {
    curvepanel.recalculate();
    curvepanel.repaint();
  }
  return true;
} /* end of mouse methods */
  
  // beginning of printdefinition method
  
public void printdefinition(int i) {
  
  textpanel.setColor(new Color(160,0,0));
  
  ((CardLayout)cards.getLayout()).show(cards, TEXTCARD);
  
  Vector temp = new Vector();
  switch (i) {
    
  case 0:
    temp.addElement("The equation of the curve is given below.");
    break;
  case 1:
    temp.addElement("The Evolute is the envelope of");
    temp.addElement("the normals to a given curve.");
    break;
  case 2:
    temp.addElement("If C is a curve, and C' is its envolute,");
    temp.addElement("then C is called an Involute of C'.");
    break;
  case 3:
    temp.addElement("Given a circle C with centre O and radius r then");
    temp.addElement("two points P & Q are inverse wrt C if OP.OQ=r.");
    temp.addElement("If P describes a curve C1 then Q describes a curve C2");
    temp.addElement("called the Inverse of C1 wrt the circle C");
    break;
  case 4:
    temp.addElement("The Pedal Curve of C wrt a fixed \"pedal point\" O is");
    temp.addElement("the locus of the point P of intersection of");
    temp.addElement("the perpendicular from O to a tangent to C.");
    break;
  case 5:
    temp.addElement("Given a curve C and a fixed point O then for a point");
    temp.addElement("P on C draw a line perpendicular to OP.");
    temp.addElement("The envelope of these lines as P describes C is");
    temp.addElement("the negative pedal of C.");
    break;
  case 6:
    temp.addElement("When light reflects off a curve then the envelope of");
    temp.addElement("the reflected rays is a caustic.");
    temp.addElement("These light rays are radial to the chosen point.");
    break;
  case 7:
    temp.addElement("When light reflects off a curve then the envelope of");
    temp.addElement("the reflected rays is a caustic.");
    temp.addElement("These light rays are parallel to the chosen line.");
    break;
  }
  textpanel.setText(temp);
  
  textpanel.setFontSize(12);
  
} /* end of printdefinition method */
  
  // beginning of printinstructions method
  
public void printinstructions (int i) {
  
  if (i == 0) {
    textpanel.setColor(Color.black);
  } else {
    textpanel.setColor(CurvePanel.darkGreen);
  }
  
  ((CardLayout)cards.getLayout()).show(cards, TEXTCARD);
  
  Vector temp = new Vector();
  switch (i) {
    
  case 0:
    temp.addElement("Choose an associated curve");
    temp.addElement( "from the list above left.");
    break;
  case 1:
    temp.addElement("The Evolute is the curve drawn in red.");
    break;
  case 2:
    temp.addElement("Click on a point.");
    temp.addElement("You can drag the mouse to move the point");
    break;
  case 3:
    temp.addElement("Click on the centre of a circle and");
    temp.addElement("drag to a point on the circumference.");
    temp.addElement("You can drag the centre dot or readjust the radius.");
    break;
  case 4:
    temp.addElement("Click on a point.");
    temp.addElement("You can drag the mouse to move the point.");
    break;
  case 5:
    temp.addElement("Click on a point.");
    temp.addElement("You can drag the mouse to move the point.");
    break;
  case 6:
    temp.addElement("Click on a point.");
    temp.addElement("You can drag the mouse to move the point.");
    break;
  case 7:
    temp.addElement("Click on the point of a line");
    temp.addElement("that goes through the origin.");
    temp.addElement("You can drag the mouse to alter the line.");
    break;
  }
  textpanel.setText(temp);
  
  textpanel.setFontSize(12);
  
} /* end of printinstructions method */
  
  // beginning of printcontrols method
  
public void printcontrols() {
  
  ((CardLayout)cards.getLayout()).show(cards, CONTROLCARD);
  
} /* end of printcontrols method */
  
} /* end of CurveControls class */
