import java.awt.*;
import java.awt.event.*;

public class Fractal extends Frame
    implements ActionListener, MouseListener, WindowListener
{
    private Button    zoomIn, zoomOut;
    private TextField nbIterations;

    private Drawing drawing;
    private double  x1 = -2.5, x2 = 1.5,
 	            y1 = -1.5, y2 = 1.5;
    private int     nb =  200;

    public Fractal()
    {
	Panel lowerPanel  = new Panel();
	Panel centerPanel = new Panel();

	setLayout(new BorderLayout());

	drawing = new Drawing();
	centerPanel.add(drawing);

	nbIterations = new TextField(Integer.toString(nb), 6);
	zoomIn  = new Button("Zoom in");
	zoomOut = new Button("Zoom out");

	lowerPanel.add(new Label("Number of iterations:"));
	lowerPanel.add(nbIterations);
	lowerPanel.add(zoomIn);
	lowerPanel.add(zoomOut);

	this.add("Center", centerPanel);
	this.add("South",  lowerPanel);

	nbIterations.setEditable(true);
	nbIterations.addActionListener(this);
	zoomIn.addActionListener(this);
	zoomOut.addActionListener(this);

	drawing.addMouseListener(this);
        this.addWindowListener(this);

	this.pack();
	drawing.init();

	this.setResizable(false);
	this.setVisible(true);

	drawing.compute(x1, y1, x2, y2, nb);
    }

    public static void main(String[] args)
    {
	new Fractal();
    }

    public void actionPerformed(ActionEvent e)
    {
	if (e.getSource() == nbIterations)
	    {
		try
		    {
			int n = Integer.parseInt(nbIterations.getText());
			if (n < 1)
			    n = 1;
			nbIterations.setText(Integer.toString(n));
			if (n != nb)
			    {
				nb = n;
				drawing.compute(x1, y1, x2, y2, nb);
			    }
		    }
		catch(NumberFormatException ex)
		    {
			nbIterations.setText(Integer.toString(nb));
		    }
		return;
	    }

	if (e.getSource() == zoomIn)
	    {
		double dx = (x2 - x1) / 4.0;
		double dy = (y2 - y1) / 4.0;

		x1 += dx;  y1 += dy;
		x2 -= dx;  y2 -= dy;

		drawing.compute(x1, y1, x2, y2, nb);

		return;
	    }

	if (e.getSource() == zoomOut)
	    {
		double dx = (x2 - x1) / 2.0;
		double dy = (y2 - y1) / 2.0;

		x1 -= dx;  y1 -= dy;
		x2 += dx;  y2 += dy;

		drawing.compute(x1, y1, x2, y2, nb);

		return;
	    }
    }

    public void mouseClicked(MouseEvent e)
    {
	double x = x1 +
	    (x2 - x1) * ((double) e.getX()
			 / (double) drawing.width());
	double y = y1 +
	    (y2 - y1) * ((double) e.getY()
			 / (double) drawing.height());

	double dx = (x1 + x2) / 2.0 - x;
	double dy = (y1 + y2) / 2.0 - y;

	x1 -= dx;  y1 -= dy;
	x2 -= dx;  y2 -= dy;

	drawing.compute(x1, y1, x2, y2, nb);
    }

    public void windowClosing(WindowEvent e)
    {
        drawing.interrupt();
        System.exit(0);
    }

    public void mouseEntered(MouseEvent e)  { }
    public void mouseExited(MouseEvent e)   { }
    public void mousePressed(MouseEvent e)  { }
    public void mouseReleased(MouseEvent e) { }

    public void windowActivated(WindowEvent e) { }
    public void windowClosed(WindowEvent e) { }
    public void windowDeactivated(WindowEvent e) { }
    public void windowDeiconified(WindowEvent e) { }
    public void windowIconified(WindowEvent e) { }
    public void windowOpened(WindowEvent e) { }
}
