/**
 * Fractal viewer for JDK 1.1
 * Copyright © 1998,1999 @author Marko Mäkelä (msmakela@cc.hut.fi).
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Button;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Label;
import java.awt.Panel;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import Fractal;
import DoubleField;
import IntegerField;

/** The applet class */

public final class Viewer extends Applet implements ActionListener {
  /** The fractal image */
  private Fractal fractal;
  /** The Mandelbrot button */
  private Button mandel;
  /** The Julia button */
  private Button julia;
  /** The BiasedMandel button */
  private Button biasedmandel;
  /** The Defaults button */
  private Button defaults;

  /** The parameter fields */
  private DoubleField ltField, utField, lxField, uxField, itField, ixField;
  private DoubleField yField, iyField;
  /** Number of iterations */
  private IntegerField iterField;

  /** The Generate Mandelbrot button string */
  private static String MANDEL = "Mandelbrot";
  /** The Generate Julia button string */
  private static String JULIA = "Julia";
  /** The Generate BiasedMandel button string */
  private static String BIASEDMANDEL = "Biased Mandelbrot";
  /** The Defaults button string */
  private static String DEFAULTS = "Defaults";

  private static String LT = "Min t:", UT = "Max t:";
  private static String LX = "Min x:", UX = "Max x:";
  private static String Y = "y:";
  private static String IT = "Init t:", IX = "Init x:", IY = "Init y:";
  private static String ITER = "Iterations:";

  /** Default values */
  public static double d_lt = -2.0, d_ut = 2.0, d_lx = -1.4, d_ux = 1.4;
  public static double d_y = 0;
  public static double d_it = .3, d_ix = -.5, d_iy = 0.0;
  public static int d_iter = 64;

  /** Create the user interface */
  public void init () {
    /** The button panel */
    Panel panel = new Panel ();
    GridBagLayout g = new GridBagLayout ();
    GridBagConstraints c = new GridBagConstraints ();
    panel.setLayout (g);
    Label label;

    c.gridwidth = 1;
    g.setConstraints (label = new Label (LT, Label.RIGHT), c);
    panel.add (label);
    g.setConstraints (ltField = new DoubleField (d_lt, -2., 2.), c);
    panel.add (ltField);

    g.setConstraints (label = new Label (LX, Label.RIGHT), c);
    panel.add (label);
    g.setConstraints (lxField = new DoubleField (d_lx, -2., 2.), c);
    panel.add (lxField);

    g.setConstraints (label = new Label (Y, Label.RIGHT), c);
    panel.add (label);
    g.setConstraints (yField = new DoubleField (d_y, -2., 2.), c);
    panel.add (yField);

    c.gridwidth = GridBagConstraints.REMAINDER;
    g.setConstraints (mandel = new Button (MANDEL), c);
    panel.add (mandel);
    mandel.addActionListener (this);

    c.gridwidth = 1;
    g.setConstraints (label = new Label (UT, Label.RIGHT), c);
    panel.add (label);
    g.setConstraints (utField = new DoubleField (d_ut, -2., 2.), c);
    panel.add (utField);

    g.setConstraints (label = new Label (UX, Label.RIGHT), c);
    panel.add (label);
    g.setConstraints (uxField = new DoubleField (d_ux, -2., 2.), c);
    panel.add (uxField);

    g.setConstraints (label = new Label (ITER, Label.RIGHT), c);
    panel.add (label);
    g.setConstraints (iterField = new IntegerField (d_iter,
						    1, Integer.MAX_VALUE), c);
    panel.add (iterField);

    c.gridwidth = GridBagConstraints.RELATIVE;
    g.setConstraints (julia = new Button (JULIA), c);
    panel.add (julia);
    julia.addActionListener (this);

    c.gridwidth = GridBagConstraints.REMAINDER;
    g.setConstraints (defaults = new Button (DEFAULTS), c);
    panel.add (defaults);
    defaults.addActionListener (this);

    c.gridwidth = 1;
    g.setConstraints (label = new Label (IT, Label.RIGHT), c);
    panel.add (label);
    g.setConstraints (itField = new DoubleField (d_it, -2., 2.), c);
    panel.add (itField);

    g.setConstraints (label = new Label (IX, Label.RIGHT), c);
    panel.add (label);
    g.setConstraints (ixField = new DoubleField (d_ix, -2., 2.), c);
    panel.add (ixField);

    g.setConstraints (label = new Label (IY, Label.RIGHT), c);
    panel.add (label);
    g.setConstraints (iyField = new DoubleField (d_iy, -2., 2.), c);
    panel.add (iyField);

    c.gridwidth = GridBagConstraints.REMAINDER;
    g.setConstraints (biasedmandel = new Button (BIASEDMANDEL), c);
    panel.add (biasedmandel);
    biasedmandel.addActionListener (this);

    setLayout (new BorderLayout ());
    add ("Center", fractal = new Fractal (this));
    add ("South", panel);
    validate ();
    doFractal (Fractal.MANDEL);
  }

  /** The action listener
   * @param e		ActionEvent to be handled
   */
  public void actionPerformed (ActionEvent e) {
    if (e.getActionCommand () == DEFAULTS) {
      doDefaults ();
    }
    else if (e.getActionCommand () == MANDEL) {
      doFractal (Fractal.MANDEL);
    }
    else if (e.getActionCommand () == JULIA) {
      doFractal (Fractal.JULIA);
    }
    else if (e.getActionCommand () == BIASEDMANDEL) {
      doFractal (Fractal.BIASEDMANDEL);
    }
  }

  /** Restore default values */
  public void doDefaults () {
    ltField.setValue (d_lt); utField.setValue (d_ut);
    lxField.setValue (d_lx); uxField.setValue (d_ux);
    yField.setValue (d_y); iterField.setValue (d_iter);
    itField.setValue (d_it); ixField.setValue (d_ix);
    iyField.setValue (d_iy);
  }

  /** Generate the fractal
   * @param type	Type of the fractal (@see Fractal.type)
   */
  public void doFractal (int type) {
    fractal.setParameters (ltField.getValue (), utField.getValue (),
			   lxField.getValue (), uxField.getValue (),
			   yField.getValue (),
			   itField.getValue (), ixField.getValue (),
			   iyField.getValue (), iterField.getValue (),
			   type);
  }

  /** Display the argument string in the "status window".
   * Hack: check the coordinates from the Fractal class.
   * @param msg		String to be displayed
   */
  public void showStatus (String msg) {
    super.showStatus (msg);
    if (fractal != null && fractal.coordinatesChanged ()) {
      ltField.setValue (fractal.getLT ()); utField.setValue (fractal.getUT ());
      lxField.setValue (fractal.getLX ()); uxField.setValue (fractal.getUX ());
    }
  }
}

