/*
Author: Shruti Parihar
Date: 05-15-2003
Title: CAContApp.java
*/

import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import java.lang.*;
import javax.swing.*;
import javax.imageio.*;
import java.util.*;


public class CAContApp extends JApplet implements Runnable, ActionListener{

  CAContCan CA = null;
  JButton start = null;
  JButton stop = null;
  JButton toggle = null;
  JButton rand = null;
  JButton params = null;
  JButton randrule = null;

  JComboBox ruleBox;
  JLabel label = null;


  JPanel southPanel,buttonPanel,menuPanel = null;
  Thread runner = null;
  boolean stoprun = false;
  public float pwl = 0.89F, pwr = 1.0F, pinc = 0.045F, pmul = 1.0F;
  Random randgen = null;
  ParameterWindow paramwindow = null;

  public void init() {

    getContentPane().setLayout(new BorderLayout());
    CA = new CAContCan();
    start = new JButton("Start");
    stop  = new JButton("Stop");
    toggle = new JButton("Toggle");
    rand  = new JButton("Randomize");
    params = new JButton("Parameters");
    randrule = new JButton("Random Rule");
    randgen = new Random(); 

    paramwindow = new ParameterWindow(this, pwl, pwr, pinc, pmul);

    menuPanel = new JPanel();
    menuPanel.setLayout(new FlowLayout());

    ruleBox = new JComboBox();
    ruleBox.addItem("Empire State");
    ruleBox.addItem("Classic Web");
    ruleBox.addItem("Go Diagonal");
    ruleBox.addItem("Pink Pyramid");
    label = new JLabel("Select a Rule");

    menuPanel.add(label);
    menuPanel.add(ruleBox);
    menuPanel.add(randrule);

    southPanel = new JPanel();
    southPanel.setLayout(new BorderLayout());

    buttonPanel = new JPanel();
    buttonPanel.setLayout(new FlowLayout());

    getContentPane().add(CA, BorderLayout.CENTER);

    buttonPanel.add(start);
    buttonPanel.add(stop);
    buttonPanel.add(toggle);
    buttonPanel.add(rand);
    buttonPanel.add(params);


    start.addActionListener(this);
    stop.addActionListener(this);
    toggle.addActionListener(this);
    rand.addActionListener(this);
    params.addActionListener(this);
    randrule.addActionListener(this);
    ruleBox.addActionListener(new java.awt.event.ActionListener() {
    public void actionPerformed(ActionEvent e) {
        jRuleBox_actionPerformed(e);
      }
    });


    
    // add southPanel to this frame
    southPanel.add(menuPanel, BorderLayout.NORTH);
    southPanel.add(buttonPanel, BorderLayout.SOUTH);
    getContentPane().add(southPanel, BorderLayout.SOUTH);

  }

  public void run() {

    CA.set();
 
    while (!stoprun) {
         CA.calculateRow(pwl, pwr, pinc, pmul);
         CA.makenewrow();
     try { Thread.sleep(10); }
        catch (InterruptedException ex) { }
    }

   }

   public void start() {

    if (runner == null) {
      runner = new Thread(this);
      runner.start();
    }
   }

   public void stop() {
      if (runner != null) {
         runner.stop();
         runner = null;
         CA.disposeimg();
     }
   }

   public void actionPerformed(ActionEvent e) {

      String command = e.getActionCommand();
      if (command == "Start")
       {  
          this.stoprun = false;
          runner = null;
          CA.randomize = false;
          this.start();
       }
      else if (command == "Stop")
       {
          this.stoprun = true;
          this.stop();
        }
      else if (command == "Toggle")
       {
          if (CA.difference)
            CA.difference = false;
          else CA.difference = true;
        }
      else if (command == "Parameters")
       {
          paramwindow.setValues(pwl, pwr, pinc, pmul);
          paramwindow.setSize(300,300);
          paramwindow.show();
       }
      else if (command == "Randomize")
       {
          CA.randomize = true;
          this.stoprun = false;
          if (runner != null)
           runner.stop();
          runner = null;
          CA.disposeimg();
          this.start();
       }
      else if (command == "Random Rule")
      {
       pwr = randgen.nextFloat();
       if (pwr > 1.0F)
        pwr = pwr % 1.0F;
       pwl = randgen.nextFloat();
       if (pwl > 1.0F)
        pwl = pwl % 1.0F;
       pmul = randgen.nextFloat();
       if (pmul > 1.0F)
        pmul = pmul % 1.0F;
       pinc = randgen.nextFloat();
       if (pinc > 1.0F)
        pinc = pinc % 1.0F;
      }
    }

    void jRuleBox_actionPerformed(ActionEvent e) {

     String item = (String) ruleBox.getSelectedItem();
  
     if (item.equals("Empire State"))
     {
     	pwr = 0.9F;
	pwl = 0.89F;
	pinc = 0.495F;
        pmul = 1.0F;
        
     }else if (item.equals("Classic Web"))
      {
     	pwr = 1.0F;
	pwl = 1.0F;
	pinc = 0.3299F;
        pmul = 1.0F;
        
     }else if (item.equals("Go Diagonal"))
      {
     	pwr = 0.2F;
	pwl = 0.91F;
	pinc = 0.325F;
        pmul = 0.98F;
        
     }else if (item.equals("Pink Pyramid"))
      {
     	pwr = 1.0F;
	pwl = 1.0F;
	pinc = 0.325F;
        pmul = 0.8F;
        
      }
   }


}


import java.awt.*;
import java.lang.*;
import java.util.*;
import javax.swing.*;

class CAContCan extends Canvas {

  Color row = null;
  Image offimg = null;
  Graphics offgraphics = null;
  int w = 620, h = 500;
  int currentHeight = 0,rowcount = 1;
  float hue = 1.5F, s = 1.0F, b = 1.0F;
  Random rand = null;
  float[] oldrow = null;
  float[] newrow = null;
  float[] displayrow = null;
  float temp;
  public boolean randomize = false;
  public boolean difference = false;


     public void set() {
      rand = new Random();
      currentHeight = 0;
      rowcount = 1;
      row = new Color(100);
      offimg = createImage(w,h);
      offgraphics = offimg.getGraphics();
      oldrow = new float[w+2];
      newrow = new float[w+2];
      displayrow = new float[w+2];
     }


  public void paint(Graphics g) {

      if (offimg != null)
       g.drawImage(offimg, 0, 0,this);
  }

 synchronized void makenewrow() {
      
      
      Graphics g = null;
      g = getGraphics();
      update(g);
     
 }

  synchronized void clear() {
      
       Graphics g = getGraphics();
       g.fillRect(0,0,w,h);
       g.dispose();
     
   }


 public void update(Graphics g) {

      if (currentHeight >= h && g != null) {
         offgraphics.copyArea(0,0,w,h,0,-1);
         //for (int d=1; d<=h; d++)
          //offgraphics.copyArea(0,d,w,1,0,-1);
         currentHeight = h-1;
      }

      if (offgraphics != null) {

         for (int i=1; i<= w; i++) {

           if(difference)
            offgraphics.setColor(row.getHSBColor(displayrow[i], s, b));
           else
            offgraphics.setColor(row.getHSBColor(newrow[i], s, b));
            offgraphics.fillRect(i,currentHeight,1,1);
         }
         currentHeight++;
      }

      g.drawImage(offimg,0,0,this);
      g.dispose();
     
  }

  void disposeimg() {
 
     offgraphics.dispose();
     offimg = null;
  }


  public void calculateRow(float pwl, float pwr, float pinc, float pmul)
   {
       if (rowcount == 1)
       {
         if (randomize)
         {
            for (int i=0; i<= w + 1; i++)
           	 newrow[i] = rand.nextFloat();
	   } else
         {
            for (int i=0; i<= w + 1; i++)
           	 newrow[i] = 0.0F;
            newrow[w/2] = 0.99F;
         }

       }
       else 
       {
         newrow[0] = (pmul * ((pwl*oldrow[w + 1] + oldrow[0] + pwr*oldrow[1])/ (pwr + 1.0F + pwl))) + pinc;
         for (int i=1; i<= w ; i++)
            newrow[i] = (pmul * ((pwl*oldrow[i-1] + oldrow[i] + pwr*oldrow[i + 1])/ (pwr + 1.0F + pwl))) + pinc;
         
         newrow[w + 1] = (pmul * ((pwl*oldrow[w] + oldrow[w+1] + pwr*oldrow[0])/ (pwr + 1.0F + pwl))) + pinc;
       }
       
       rowcount++;

        
      for (int c = 0; c <= w + 1; c++)
       {
        if (newrow[c] > 1.0F)
          newrow[c] = newrow[c] % 1.0F;
     	  oldrow[c] = newrow[c];
       }

      for (int i=1; i<= w; i++)
       {
	   displayrow[i] = (float)((newrow[i-1] + newrow[i+1])/2.0F) - newrow[i] ;
           if (displayrow[i] <= 0.0F)
             displayrow[i] = 0.0F - displayrow[i];
           

       }
       displayrow[0] = (float)((newrow[w+1] + newrow[1])/2.0F) - newrow[0] ; 
           if (displayrow[0] <= 0.0F)
             displayrow[0] = 0.0F - displayrow[0];

       displayrow[w+1] = (float)((newrow[w] + newrow[0])/2.0F) - newrow[w+1] ;    
           if (displayrow[w+1] <= 0.0F)
             displayrow[w+1] = 0.0F - displayrow[w+1];

   }

}

import java.awt.*;
import java.awt.event.*;
import java.lang.*;
import javax.swing.*;

public class ParameterWindow extends JFrame implements ActionListener
{
  CAContApp parentApp = null;
  JTextField Wl = null;
  JTextField Wr = null;
  JTextField Inc = null;
  JTextField Mul = null;
  JButton set = null;
  JLabel header = null;
  JLabel lw = null;
  JLabel rw = null;
  JLabel inc = null;
  JLabel mul = null; 
  Insets insets = null;
  
  JPanel panel = null;


  public ParameterWindow(CAContApp parent, float pwl, float pwr, float pinc, float pmul)
  {
   this.parentApp = parent;
   
   panel = new JPanel();
   panel.setLayout(null);
   
   insets = getContentPane().getInsets();
   Wl = new JTextField(Float.toString(pwl),10);
   Wr = new JTextField(Float.toString(pwr),10);
   Inc = new JTextField(Float.toString(pinc),10);
   Mul = new JTextField(Float.toString(pmul),10);
   set = new JButton("Set");
   header = new JLabel("Enter the following Parameters");
   lw = new JLabel("Left Weight:");
   rw = new JLabel("Right Weight:");
   inc = new JLabel("Increment:");
   mul = new JLabel("Multiplier:");

   set.addActionListener(this);
 
   panel.add(header);
   header.setBounds(50 + insets.left, 5, 250, 15);

   lw.setBounds(20 + insets.left, 30 + insets.top, 80, 20); 
   panel.add(lw);
   panel.add(Wl);
   Wl.setBounds(150 + insets.left, 30 + insets.top, 100, 20);

   panel.add(rw);
   panel.add(Wr);
   rw.setBounds(20 + insets.left, 70 + insets.top, 80, 20);
   Wr.setBounds(150 + insets.left, 70 + insets.top, 100, 20);

   panel.add(inc);
   panel.add(Inc);
   inc.setBounds(20 + insets.left, 110 + insets.top, 80, 20);
   Inc.setBounds(150 + insets.left, 110 + insets.top, 100, 20);
  
   panel.add(mul);
   panel.add(Mul);
   mul.setBounds(20 + insets.left, 150 + insets.top, 80, 20);
   Mul.setBounds(150 + insets.left, 150 + insets.top, 100, 20);

   panel.add(set);
   set.setBounds(100 + insets.left, 190 + insets.top, 75, 30);

   getContentPane().add(panel);

      addWindowListener(new WindowAdapter() {
        public void windowClosing(WindowEvent e) { 
           dispose(); } }); 

  }

  public void setValues(float pwl, float pwr, float pinc, float pmul){
 
    Wl.setText(Float.toString(pwl));
    Wr.setText(Float.toString(pwr));
    Inc.setText(Float.toString(pinc));
    Mul.setText(Float.toString(pwl));
 }
  

  public void actionPerformed(ActionEvent e) {
   
   String command = e.getActionCommand();
   if (command == "Set")
    {
     try {
            parentApp.pwl = Float.parseFloat(Wl.getText());
            if (parentApp.pwl > 1.0F)
              parentApp.pwl = parentApp.pwl % 1.0F;
            parentApp.pwr = Float.parseFloat(Wr.getText());
            if (parentApp.pwr > 1.0F)
              parentApp.pwr = parentApp.pwr % 1.0F;
            parentApp.pinc = Float.parseFloat(Inc.getText());
            if (parentApp.pinc > 1.0F)
              parentApp.pinc = parentApp.pinc % 1.0F;
            parentApp.pmul = Float.parseFloat(Mul.getText());
            if (parentApp.pmul > 1.0F)
              parentApp.pmul = parentApp.pmul % 1.0F;

     } catch (NumberFormatException nfe)
     {
            parentApp.pwl = 1.0F;
            parentApp.pwr = 1.0F;
            parentApp.pinc = 1.0F;
		parentApp.pmul = 1.0F;
     }
    }
  }
}
