/*
  The 
  Mitch Fincher April 12, 1997 - Java practice applet

 */

import java.applet.Applet;
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.lang.*;

////////////////////////////////////////////////////////////////
public class Arbor extends Applet {
////////////////////////////////////////////////////////////////
  
  Font	titleFont ;
  int canvas_width=400;
  int canvas_height=500;
  int xcenter = canvas_width/2;
  public Graphics G,drawGC;
  float PI = 3.14159f;
  float DEGREES_TO_RADIANS = 2.0f*PI/360.0f;
  float smallest_branch=5.0f;

  Scrollbar angleOfBranch, newBranchRatio;
  Label angleOfBranchLabel, newBranchRatioLabel;

  Button drawButton;
  GUIController mycontroller;

  Panel titlePanel = new Panel();
  Panel drawPanel = new Panel();
  Panel controlPanel = new Panel();

////////////////////////////////////////////////////////////////
public void init() 
////////////////////////////////////////////////////////////////
  {
    mycontroller = new GUIController(this);

    setLayout(new BorderLayout(10,10));
    
    add("North",titlePanel);
    Label BigTitle = new Label("Make your own tree", Label.CENTER);
    titlePanel.add(BigTitle);
    BigTitle.setBackground(Color.gray);
    titlePanel.setBackground(Color.gray);

    add("Center",drawPanel);
    drawGC = drawPanel.getGraphics();
    
    add("South",controlPanel);
    angleOfBranch = new Scrollbar(Scrollbar.HORIZONTAL,10,10,10,55);
    angleOfBranch.addAdjustmentListener(mycontroller);
    angleOfBranch.setValue(35);

    newBranchRatio = new Scrollbar(Scrollbar.HORIZONTAL,10,10,50,80);
    newBranchRatio.addAdjustmentListener(mycontroller);
    newBranchRatio.setValue(62);

    drawButton = new Button("Draw");
    drawButton.addActionListener(mycontroller);

    controlPanel.setLayout(new GridLayout(3,1,5,5));
    angleOfBranchLabel = new Label("Angle of Branch (degrees): 35", Label.LEFT);
    angleOfBranchLabel.setBackground(Color.gray);
    controlPanel.add( angleOfBranchLabel );
    controlPanel.add(angleOfBranch);
    newBranchRatioLabel = new Label("Thickness  (50-70%): 62", Label.LEFT);
    newBranchRatioLabel.setBackground(Color.gray);
    controlPanel.add(newBranchRatioLabel);
    controlPanel.add(newBranchRatio);

    controlPanel.add(drawButton);
    controlPanel.setBackground(Color.gray);
  }

////////////////////////////////////////////////////////////////
public void start()
////////////////////////////////////////////////////////////////
  {
    drawArbor();
  }

////////////////////////////////////////////////////////////////
public void paint(Graphics g)
////////////////////////////////////////////////////////////////
{
  drawArbor();
}
  
////////////////////////////////////////////////////////////////
public void drawArbor() {
////////////////////////////////////////////////////////////////
  
  drawGC.setColor(Color.white);
  drawGC.fillRect(0,0,drawPanel.getSize().width,drawPanel.getSize().height);
  drawGC.setColor(Color.green);
  float root = 350.0f;
  DPoint first = new DPoint((float)xcenter,root);
  DPoint last = new DPoint((float)xcenter,root - 50.0f);
  float angle = angleOfBranch.getValue();
  float ratio =  ((float)newBranchRatio.getValue())/100.0f;

  draw_branch(first,last,angle,ratio);
}

  //{**********************************************************************}
public DPoint calc_point(DPoint first, DPoint last,float theta,float ratio)
  {
    float phi;

   float xdelta=last.x - first.x;
   float ydelta=last.y - first.y;
   float length = first.distanceTo(last);
   //   System.out.print("\n theta = " + theta + ", ratio = " + ratio);
   //if( theta == 0.0 )
   //  {
   //   ratio = ratio*1.3;
   //  }
   theta = theta*DEGREES_TO_RADIANS;
   //   System.out.print("\n -- theta = " + theta + ", ratio = " + ratio);

   //float r=length*ratio;
   if (xdelta != 0.0f)
      phi= (float) Math.atan(ydelta/xdelta);
   else
      phi=PI/2.0f;
   // now lets straigthen out phi for the right quadrant
   
   if ( (xdelta < 0.0) && (ydelta > 0.0) )
     phi = phi + PI;
   else if ( (xdelta < 0.0) && (ydelta < 0.0) )
     phi = phi + PI;
   else if ( (xdelta > 0.0) && (ydelta < 0.0) )
     phi = 2*PI - phi;

   // calculate the next points
   float xprime=xdelta*ratio+last.x;
   float yprime=ydelta*ratio+last.y;

   DPoint newpoint = new DPoint(0.0f,0.0f);
   newpoint.x = last.x + (xprime-last.x)*(float) Math.cos(theta)-(yprime-last.y)*(float) Math.sin(theta);
   newpoint.y = last.y + (yprime-last.y)*(float) Math.cos(theta)+(xprime-last.x)*(float) Math.sin(theta);

   return(newpoint);
}

////////////////////////////////////////////////////////////////
public void draw_branch(DPoint first, DPoint last, float theta ,float ratio) 
////////////////////////////////////////////////////////////////
  {
    float length = first.distanceTo(last);
    int num_branches=5;

    mdraw(first,last,Color.green);
    DPoint point1;
    if( length > smallest_branch)
     {
      float itheta = ((float)(num_branches -1))*theta/2.0f * -1.0f;
      //System.out.println("itheta= " + itheta + ", theta = " + theta);
       for(int i = 0; i<num_branches; i++)
	 {
	   //System.out.println("*** " + i + ", itheta= " + itheta);
	   if(itheta < 0.1 && itheta > -0.1)
	     point1 = calc_point(first,last,itheta,ratio*1.3f );
	   else
	     point1 = calc_point(first,last,itheta,ratio );

	   draw_branch(last, point1 ,theta,ratio);
	   itheta += theta;
	 }
     }
     else
       //draw the leaf
       mdraw(first,last,Color.red);
     }
     

  //{**********************************************************************}
////////////////////////////////////////////////////////////////
public void mdraw(DPoint first, DPoint last, Color mycolor) 
////////////////////////////////////////////////////////////////
{

    drawGC.setColor(mycolor);
    drawGC.drawLine((int)first.x,(int)first.y,(int)last.x,(int)last.y);
}
////////////////////////////////////////////////////////////////
public static void main(String argv[])
////////////////////////////////////////////////////////////////
  {
    Frame myFrame;

    myFrame = new Frame();
    myFrame.resize(600,600);
    myFrame.show();
    
    Arbor app = new Arbor();
    myFrame.add("Center",app);
    app.init();
    app.start();

  } // function main()

} /* end of Arbor class */

/* Class DPoint - Points with x and y in floats instead of ints --*/
class DPoint {
  float x,y;

  DPoint(float x1, float y1)
  {
    x = x1; y = y1;
  }

float distanceTo(DPoint other)
  {
   float xdelta= x - other.x;
   float ydelta= y - other.y;
   return((float) Math.sqrt(xdelta*xdelta + ydelta*ydelta));
  }

}

////////////////////////////////////////////////////////////////
class GUIController implements ActionListener, AdjustmentListener {
  Arbor myArbor;
  
  GUIController (Arbor myarbor) 
  {
    myArbor = myarbor;
  }
  
////////////////////////////////////////////////////////////////
public void actionPerformed(ActionEvent event)
////////////////////////////////////////////////////////////////
  {
    if(event.getSource() == myArbor.drawButton)
      {
	myArbor.drawArbor();
      }
  }

////////////////////////////////////////////////////////////////
public void adjustmentValueChanged(AdjustmentEvent event)
////////////////////////////////////////////////////////////////
  {
    if(event.getSource() == myArbor.angleOfBranch)
      {
	myArbor.angleOfBranchLabel.setText("Angle of Branch (degrees):" + myArbor.angleOfBranch.getValue());
      }
    else if(event.getSource() == myArbor.newBranchRatio)
	myArbor.newBranchRatioLabel.setText("Thickness  (50-70%): " + myArbor.newBranchRatio.getValue());
	
    //myArbor.drawArbor();
  }
}


  
