import java.awt.event.*;

import java.awt.*;

import java.applet.*;

import java.awt.image.*;

public  class myMandel extends Applet implements

Runnable,ActionListener,MouseListener{

  private static final Color backgroundColor = Color.white;

  private static final String[] LABELS = {"Minimum x", "Minimum y","Maximum x", "Maximum y"};

  private static final int LOWER_X = 0;

  private static final int LOWER_Y = 1;

  private static final int UPPER_X = 2;

  private static final int UPPER_Y = 3;

  private static final int GENERATE_MANDEL = 0;

  private static final int GENERATE_JULIA = 1;

 

  int                  ww=600,hh=350;

  myMandelCanvas       mc;

  private Thread       animation;

  private Graphics     graphics;

  private Panel        controls;

  private int          state;

  private Font         font = new Font("Times", Font.PLAIN, 10);

 

  private TextField[]  mandelFields;

  private float[]      mandelLimits = {-1.3f, -1.2f, 1.0f, 1.2f};

 

  private TextField[]  juliaFields;

  private float[]      juliaLimits = {-1.5f, -1.0f, 1.5f, 1.0f};

  private boolean      juliaSelected;

  private float        juliaX, juliaY;

   

  Button zoomin_M, zoomout_M,reset_M,zoomin_J, zoomout_J,reset_J;

 

  // ready applet

  public void init() {

    setBackground(backgroundColor);

    setFont(font);

   

    // create mandelbrot control panel

    Panel mandelControls = new Panel();

    mandelControls.setLayout(new GridLayout(2, 2, 5, 5));

 

 

mandelFields = new TextField[mandelLimits.length];

    for (int i = 0; i < mandelLimits.length; i++) {

      mandelFields[i] = new TextField(Float.toString(mandelLimits[i]));

      mandelFields[i].setEditable(true);

      Label l = new Label(LABELS[i]);

      l.setAlignment(Label.RIGHT);

      mandelControls.add(l);

      mandelControls.add(mandelFields[i]);

    }

   

    // create julia control panel

    Panel juliaControls = new Panel();

    juliaControls.setLayout(new GridLayout(2, 2, 5, 5));

    juliaFields = new TextField[juliaLimits.length];

    for (int i = 0; i < juliaLimits.length; i++) {

      juliaFields[i] = new TextField(Float.toString(juliaLimits[i]));

      juliaFields[i].setEditable(true);

      Label l = new Label(LABELS[i]);

      l.setAlignment(Label.RIGHT);

      juliaControls.add(l);

      juliaControls.add(juliaFields[i]);

    }

   

    // put both panel at bottom of applet

    controls = new Panel();

    controls.setLayout(new GridLayout(1, 2, 1, 1));

    controls.add(mandelControls);

    controls.add(juliaControls);

    setLayout(new BorderLayout());

    add("South", controls);

   

    graphics = getGraphics();

    state = GENERATE_MANDEL;

 

    mc = new myMandelCanvas(juliaX, juliaY,ww,hh,mandelLimits,juliaLimits);

    add("Center", mc);

    mc.addMouseListener(this);

 

    Panel buttonControl=new Panel();

    buttonControl.setLayout(new GridLayout(6,1));

    zoomin_M=new Button("Z_M");

    zoomout_M=new Button("z_M");

    reset_M=new Button("reset_M");

    zoomin_J=new Button("Z_J");

    zoomout_J=new Button("z_J");

    reset_J=new Button("reset_J");

 

    buttonControl.add(zoomin_M);

    buttonControl.add(zoomout_M);

    buttonControl.add(reset_M);

    buttonControl.add(zoomin_J);

    buttonControl.add(zoomout_J);

    buttonControl.add(reset_J);

    add("East",buttonControl);

    zoomin_M.addActionListener(this);

    zoomout_M.addActionListener(this);

    reset_M.addActionListener(this);

    zoomin_J.addActionListener(this);

    zoomout_J.addActionListener(this);

    reset_J.addActionListener(this);

  }

 

  public void start(){

    if (animation == null) {

      animation = new Thread(this);

      animation.start();

    }

  }

 

  // stop animation and get rid of graphics

  public void destroy() {

    if (animation != null && animation.isAlive())

      animation.stop();

    if (graphics != null)

      graphics.dispose();

  }

       

  // new julia sets or changing limits on either set

 

  public void mousePressed(MouseEvent e) {  }

 

  public void mouseReleased(MouseEvent e) {}

 

  public void mouseEntered(MouseEvent e) {}

 

  public void mouseExited(MouseEvent e) { }

 

  public void mouseClicked(MouseEvent e) {

    int x=e.getX();

    int y=e.getY();

    if (mc.mandelRect.contains(x, y)) {

      // new limits for mandelbrot set

      if (captureLimits(mandelFields, mandelLimits)) {

        for(int i=0;i<mandelLimits.length;i++){

 

    mandelLimits[i]=Float.valueOf(mandelFields[i].getText()).floatValue();

        }

        stop();

        state = GENERATE_MANDEL;

        start();

      }

      // new julia set

      else if (mc.mandelPicture != null) {

        stop();

        juliaSelected = true;

        float relative_x = (float) (x - mc.mandelRect.x) / (float)mc.mandelRect.width;

        float relative_y = (float) (y - mc.mandelRect.y) / (float)mc.mandelRect.height;

        juliaX = mandelLimits[LOWER_X] + (mandelLimits[UPPER_X] -mandelLimits[LOWER_X]) * relative_x;

        juliaY = mandelLimits[LOWER_Y] +(mandelLimits[UPPER_Y] -mandelLimits[LOWER_Y]) * relative_y;

        state = GENERATE_JULIA;

        start();

      }

    }// Mandelbrot if end

   

    else if (mc.juliaRect.contains(x, y)) {

      // new limits for julia set

      if (mc.mandelPicture != null && juliaSelected && captureLimits(juliaFields, juliaLimits)) {

        stop();

        state = GENERATE_JULIA;

        start();

      }

    }

  }

 

  // stop animation thread

  public void stop() {

    if (animation != null && animation.isAlive())

      animation.stop();

    animation = null;

  }

 

  // either generate mandelbrot or julia set

  public void run() {

    switch (state) {

    case GENERATE_MANDEL:

      mc.createMandel(mandelLimits);

 

  break;

    case GENERATE_JULIA:

      mc.createJulia(juliaX, juliaY,juliaLimits);

      break;

    default:

      // do nothing

      break;     

    }

  }

 

// capture limiting values

  private boolean captureLimits(TextField[] fields, float[] limits){

    boolean changed = false;   

    for (int i = limits.length - 1; i >= 0; i--) {

      try {

        float o = limits[i];

        limits[i] =Float.valueOf(fields[i].getText()).floatValue();

        changed = changed | (o != limits[i]);

      }

      catch (NumberFormatException e) {

        fields[i].setText(Float.toString(mandelLimits[i]));

      }

    }

    return changed;

  }

 

  public void actionPerformed(ActionEvent e){

    Object target = e.getSource();

    if (target.equals(zoomin_M)){

      for(int n=0; n<mandelLimits.length;n++){

        mandelLimits[n]=mandelLimits[n]/2;

      }

      mc.createMandel(mandelLimits);

    }

    if (target.equals(zoomout_M)){

      for(int n=0; n<mandelLimits.length;n++){

        mandelLimits[n]=2*mandelLimits[n];

      }

      mc.createMandel(mandelLimits);

    }

    if (target.equals(reset_M)){

for(int n=0; n<mandelLimits.length;n++){

    mandelLimits[n]=Float.valueOf(mandelFields[n].getText()).floatValue();;

      }

      mc.createMandel(mandelLimits);

    }

 

if (target.equals(zoomin_J)){

      for(int n=0; n<juliaLimits.length;n++){

        juliaLimits[n]=juliaLimits[n]/2;

      }

      mc.createJulia(juliaX, juliaY,juliaLimits);

    }

    if (target.equals(zoomout_J)){

      for(int n=0; n<juliaLimits.length;n++){

        juliaLimits[n]=2*juliaLimits[n];

      }

      mc.createJulia(juliaX, juliaY,juliaLimits);

    }

    if (target.equals(reset_J)){

for(int n=0; n<mandelLimits.length;n++){

 

   juliaLimits[n]=Float.valueOf(juliaFields[n].getText()).floatValue();;

      }

      mc.createJulia(juliaX, juliaY,juliaLimits);

    }

  }

}