/*
********************************************************************************
** file: Mand.java
** does: Does an exercise of float math and graphics
** author: Bob Jamison, rjamison@gothamcity.jsc.nasa.gov
**
********************************************************************************
*/
import java.awt.*;
import java.applet.Applet;

/*
********************************************************************************
** MAIN CLASS
********************************************************************************
*/
public class Mand extends Applet
{
MandWin mand;

public Mand()
  {
  mand = new MandWin();
  setLayout(new AbsoluteLayout());
  add("North",mand);
  show();
  } 


public static void main(String args[])
  {
  Frame f = new Frame("Mandelbrot Test");
  Mand MandApp = new Mand();
  MandApp.resize(410,450);

  f.resize(420,420);
  f.add("North",MandApp);
  f.show();
  }



}

/*
********************************************************************************
** MANDELBROT PANEL
********************************************************************************
*/
class MandWin extends Panel
{
Label xposlbl,yposlbl;
double range;
double xc,yc;
int xres,yres;

/*
*****
This does the actual Mandelbrot Set calculation at the given x,y coordinate
and return the number of iterations processed.  Done as a separate function
in order to allow it to be used in other ways!
*****
*/
int PointMand(double x,double y,int maxiter)
{
int i;
double a,b;
double a2, b2,twoab,val;
  a = b = 0.0;
  for (i=0;i<maxiter;i++)
    {
    a2  = a*a;
    b2  = b*b;
    val = a2 + b2;
    if (val>=4.0)
      break;
    twoab = 2.0*a*b;
    a = a2 - b2  + x;
    b = twoab + y;
    }
  return i;
}

/*
****
This draws the screen
*****
*/
public void update(Graphics g)
{
double x0,y0,x,y;
double delta;
float xpos,ypos,rng;
int i,row,col,tcol,xoff,yoff,iter,lastiter;
Color clr[];
String pos_lbl;
  xpos = (float)xc;
  ypos = (float)yc;
  rng  = (float)range;
  pos_lbl = "X:"+xpos+"  Y:"+ypos+"   Range:"+rng;
  resize(420,420);
  g.clearRect(0,0,420,420);
  pos_lbl = "X:"+xpos+"  Y:"+ypos;
  g.drawString(pos_lbl,155,350);
  pos_lbl = "Range:"+rng;
  g.drawString(pos_lbl,155,365);
  if (xres<=64)
    xoff = 118;
  else
    xoff = 1;
  if (yres<=64)
    yoff = 158;
  else
    yoff = 0;
  x0 = xc - range/2.0;
  y0 = yc + range/2.0;
  delta = range / (double)yres;
  y=y0;
  iter = 0;
  lastiter = -1;
  clr = new Color[8];
  clr[0] = Color.black;  /*Use "standard" colors*/
  clr[1] = Color.red;
  clr[2] = Color.blue;
  clr[3] = Color.green;
  clr[4] = Color.yellow;
  clr[5] = Color.magenta;
  clr[6] = Color.cyan;
  clr[7] = Color.orange;

  g.setColor(Color.red);
  g.drawRect(xoff-1,yoff-1,xres+2,yres+2);
  g.setColor(clr[0]);
  g.fillRect(xoff,yoff,xres,yres);
  
  for (row=0;row<yres;row++)
    {
    x=x0; tcol=0;
    for (col=0;col<xres;col++)
      {
      iter = PointMand(x,y,63);
      if (iter != lastiter)  /*Color cache*/
        {
        lastiter=iter;
        g.drawLine(tcol+xoff,row+yoff,col+xoff,row+yoff);
        g.setColor(clr[iter&7]);
        tcol=col; /*Color transition cache*/
        }
      x += delta;
      }
    g.setColor(clr[iter&7]);
    g.drawLine(tcol+xoff,row+yoff,col+xoff,row+yoff); /*Finish the line!*/
    y -= delta;
    }

}

/*
****
Do button callbacks
*****
*/
public boolean action(Event evt,Object obj)
  {
  double range2;
  range2 = range / 2.0;
  if (evt.target instanceof Button)
    {
    String label = (String)obj;
    if (label.equals("NW"))
      {
      xc -= range2;
      yc += range2;
      repaint();
      }
    else if (label.equals("N"))
      {
      yc += range2;
      repaint();
      }
    else if (label.equals("NE"))
      {
      xc += range2;
      yc += range2;
      repaint();
      }
    else if (label.equals("W"))
      {
      xc -= range2;
      repaint();
      }
    else if (label.equals("E"))
      {
      xc += range2;
      repaint();
      }
    else if (label.equals("SW"))
      {
      xc -= range2;
      yc -= range2;
      repaint();
      }
    else if (label.equals("S"))
      {
      yc -= range2;
      repaint();
      }
    else if (label.equals("SE"))
      {
      xc += range2;
      yc -= range2;
      repaint();
      }
    else if (label.equals("In"))
      {
      range = range2;
      repaint();
      }
    else if (label.equals("Out"))
      {
      range = range * 2.0;
      repaint();
      }
    else if (label.equals("Big"))
      {
      xres=400; yres=300;
      repaint();
      }
    else if (label.equals("Small"))
      {
      xres=64; yres=64;
      repaint();
      }
      }
  else if (evt.id == Event.WINDOW_DESTROY)
    {
    hide();
    }
  return true;
  }

/*
****
Creates the interface
*****
*/
MandWin()
  {
  Button tmp;

  Panel buttons = new Panel();
  buttons.setLayout(new GridLayout(4,3));

  buttons.add(tmp = new Button("NW"));
  buttons.add(tmp = new Button("N"));
  buttons.add(tmp = new Button("NE"));

  buttons.add(tmp = new Button("W"));
  buttons.add(tmp = new Button("In"));
  buttons.add(tmp = new Button("E"));

  buttons.add(tmp = new Button("SW"));
  buttons.add(tmp = new Button("S"));
  buttons.add(tmp = new Button("SE"));

  buttons.add(tmp = new Button("Small"));
  buttons.add(tmp = new Button("Out"));
  buttons.add(tmp = new Button("Big"));

  resize(420,420);
  /*
  setLayout(new AbsoluteLayout());
  */
  setLayout(null);
  add(buttons);

  buttons.resize(150,110);
  buttons.move(0,310);

  range=0.25;
  xc=0.0;
  yc=0.85;
  xres=64; yres=64;
  }

}

/*
********************************************************************************
** LAYOUT MANAGER
** Note: This class is not mine.  I lost the e-mail where he sent this to me, so I
** can't attribute this,
** but one of the fine engineers at Sun Inc loaned me this nice layout class.
** I'm forever grateful!
********************************************************************************
*/
class AbsoluteLayout implements LayoutManager {

  public AbsoluteLayout()
    {
    }

  public void addLayoutComponent(String name, Component comp)
    {
    }

  public void removeLayoutComponent(Component comp)
    {
    }

  public Dimension preferredLayoutSize(Container parent)
   {
        Insets insets = parent.insets();
        int ncomponents = parent.countComponents();
        int w = 0;
         int h = 0;

        for (int i = 0; i < ncomponents; i++)
         {
            Component comp = parent.getComponent(i);
            Dimension d = comp.preferredSize();
            Point p = comp.location();
            if ((p.x + d.width) > w)
                w = p.x + d.width;
            if ((p.y + d.height) > h)
                h = p.y + d.height;
          }
        return new Dimension(insets.left + insets.right + w,
                             insets.top + insets.bottom + h);
    }

  public Dimension minimumLayoutSize(Container parent)
   {
        Insets insets = parent.insets();
        int ncomponents = parent.countComponents();
        int w = 0;
        int h = 0;

        for (int i = 0; i < ncomponents; i++)
          {
          Component comp = parent.getComponent(i);
          Dimension d = comp.preferredSize();
           Point p = comp.location();
          if ((p.x + d.width) > w)
              w = p.x + d.width;
          if ((p.y + d.height) > h)
              h = p.y + d.height;
          }
        return new Dimension(insets.left + insets.right + w,
                             insets.top + insets.bottom + h);
    }

  public void layoutContainer(Container parent)
   {
    int nmembers = parent.countComponents();

    for (int i = 0; i < nmembers; i++)
     {
     Component m = parent.getComponent(i);
     Dimension d = m.preferredSize();
     m.resize(d.width, d.height);
     }
   }
}
/* END OF FILE ********************************************************************/




