import java.awt.*;
import java.awt.event.*;

public class Widget extends Frame implements WindowListener
{
    int unit = 4; //The basic unit for the smallest triangle

    int Order = 8; //The starting order

  public void windowClosing(WindowEvent e) { System.exit(0); }
  public void windowClosed(WindowEvent e) {}
  public void windowIconified(WindowEvent e) {}
  public void windowOpened(WindowEvent e) {}
  public void windowDeiconified(WindowEvent e) {}
  public void windowActivated(WindowEvent e) {}
  public void windowDeactivated(WindowEvent e) {}

  public Widget()
    {
      Toolkit tk = Toolkit.getDefaultToolkit();
      Dimension d = tk.getScreenSize();
      int screenHeight = d.height;
      int screenWidth = d.width;

      addWindowListener(this);
      setSize(screenHeight, screenHeight);
      setLocation(screenWidth/4, screenHeight/4);
      addMouseListener(new MouseAdapter() 
		       {
			 public void mouseClicked(MouseEvent evt)
			   { Order = (Order+1) % 10; repaint(); }
		       });
    }//method Widget

  public void paint(Graphics g)
    {
      g.translate(getInsets().left, getInsets().top);
      int height = getSize().height - getInsets().top - getInsets().bottom;
      int width = getSize().width - getInsets().left - getInsets().right;

      setTitle("Sierpinski Widget of order "+Order);	  
	  g.setColor(Color.black);
	  sier(g,Order,width/2,0);
	}//method paint

    private double power(int base, int exp){
        double t = 1; //This will be used to keep m even
        int m = exp;
        double n = (double) base; //We need a double because n may get large
        //right now, t*(n^m) = base^exp (because t=1, n=base, and m=exp)
        //t*(n^m) will not change anywhere in the algorithm.
        
        if (m == 0) return 1;
        
        while (m != 1) { //When m is one, we're done (t*n = base^exp)
            if (m % 2 == 0) {//Is n even?
                n = n*n; //=n^2
                m = m/2;
                //does not change t*(n^m) because:
                //t*(n^m) = t*(n^2)^(m/2)
            }
            else {//If n is not even, make it even.
                m = m - 1; //so m is divisible by two in the next iteration
                t = t * n;
                //does not change t*(n^m) because:
                //t*(n^m) = (t*n)*n^(m-1)
            }
        }
        return t*n; //base^exp = t*(n^m) = t*n (because m = 1)
    }//method power

    private void triangle(Graphics g, int x, int y){
        //Define variables to be used for other two corners of the triangle
        int x2 = 0;
        int x3 = 0;
        int y2 = 0; //the y value for both other corners is the same
        
        //X's are easy, because the triangle is oriented vertically, so the
        //top is, in terms of x, halfway between the other two corners
        x2 = x + this.unit/2;
        x3 = x - this.unit/2;
        
        //Both Y's are the same, and they can be found using the Pythagorean
        //formula. However, they must be cast to an int for drawLine()
        y2 = y + (int) java.lang.Math.sqrt(power(this.unit,2) - power(this.unit/2,2));
        
        //Now, draw the lines:
        g.drawLine(x, y, x2, y2);
        g.drawLine(x, y, x3, y2);
        g.drawLine(x2, y2, x3, y2);
    }// method triangle
    
    public void sier(Graphics g, int order, int x, int y){
        if (order==0) return; //Don't do anything if there are no triangles!
        if (order==1) {//order=1: paint the triangle at the specified point:
            this.triangle(g, x, y);
        }
        else {
            //find L, the length of triangle whose corners will form the
            //vertices of the next three triangles:
            int L = (int) power(2, order-2) * this.unit;
            //use L to determine the location of the corners of the triangle
            //with sides of length L and vertex (x,y), using geometry and the
            //Pythagorean formula
            int xDiff = L/2;
            int yDiff = (int) java.lang.Math.sqrt(power(L,2) - power(L/2,2));
            //Draw widgets for each of the three points, with order one
            //less than the current order:
            this.sier(g, order-1, x, y);
            this.sier(g, order-1, x - L/2, y + yDiff);
            this.sier(g, order-1, x + L/2, y + yDiff);
        }
    } //method sier

    /* Please do not touch the main method. */
     public static void main (String[] args)
    {
      Widget w = new Widget();
      w.show();
    } //method main
}//class Widget


