/* *
 *
 * arbre.java - jpq - 14/11/11 - 13/02/15
 *
 * Trace l'arbre dans le cadre d'une loi binomiale
 *
 */

import java.awt.event.* ;
import java.awt.* ;
import java.applet.* ;
import java.math.* ;

public class arbre extends java.applet.Applet implements ActionListener, AdjustmentListener {
    static final long serialVersionUID = 130215L;

    Image img;
    Graphics g;
    int wimg, himg;

    TextField tn;
    Button ok;
    Scrollbar sc;
    int n, ndep, pas;
    boolean deplace;
    int [] posd, posf;
    int index;
    
    public void init () {
        setFont (new Font ("sans-serif", Font.BOLD, 12));
        setLayout (new BorderLayout ());
  	    Panel p = new Panel ();
        p.setLayout (new GridLayout (1, 3));
  	    add (p, BorderLayout.NORTH);
		if (n <= 0) n = 3;
        p.add (tn = new TextField (4));
        tn.setText (Integer.toString (n));
        posd = new int [28]; // 2^(n+2)-4
        posf = new int [28];

        p.add (ok = new Button ("Ok"));
        ok.addActionListener (this);
        ndep = 400;
        p.add (sc = new Scrollbar (Scrollbar.HORIZONTAL, 0, 10, 0, ndep + 10));
        sc.addAdjustmentListener (this);
//        deplace = false;
    }

    public String getAppletInfo () {
        return "arbre.java par J.-P. Quelen";
    }

    public void actionPerformed (ActionEvent e) {
        if (e.getSource () == ok) {
            int an = n ;
            try {
                n = Integer.parseInt (tn.getText ());
            }
            catch (NumberFormatException nfe) { }
            if (n <= 0)
                n = an;
            tn.setText (Integer.toString (n));
            int dim = (1 << n + 2) - 4; // 2^(n+2)-4        + prioritaire sur <<
            if (dim > posd.length) {
                posd = new int [dim];
                posf = new int [dim];
            }
            deplace = false;
            pas = 0;
            sc.setValue (0);
            repaint ();
        }
    }

    public void adjustmentValueChanged (AdjustmentEvent e) {
        if (e.getSource () == sc) {
            pas = sc.getValue ();
            deplace = true;
            repaint ();
        }
    }

////////////////////////////////////////////////////////////////////////////////

    private void efface () {
        g.setColor (Color.WHITE);
        g.fillRect (0, 0, wimg, himg);
    }

    public void update (Graphics g1) {
        paint (g1);
    }

    private void trace (int niveau, int issue, int x, int y, int dy, Graphics g) {
        if (niveau < n) {
            g.setColor (Color.RED);
            g.drawLine (x, y, x + wimg / n - 20, y + dy);
            posd [index] = y;
            posf [index ++] = himg * (n + 1 + niveau - 2 * issue) / ((n+1) * 2);
            posd [index] = y + dy;
            posf [index ++] = himg * (n + 2 + niveau - 2 * issue) / ((n+1) * 2);
            g.drawString (Integer.toString (issue), x + wimg / n - 10, y + dy);
            g.drawString ("1-p", x + wimg / (2 * n) - 10, y + dy / 2 - 10);
            trace (niveau + 1, issue, x + wimg / n, y + dy, dy / 2, g);
            g.setColor (Color.BLUE);
            g.drawLine (x, y, x + wimg / n - 20, y - dy);
            posd [index] = y;
            posf [index ++] = himg * (n + 1 + niveau - 2 * issue) / ((n+1) * 2);
            posd [index] = y - dy;
            posf [index ++] = himg * (n + niveau - 2 * issue) / ((n+1) * 2);
            g.drawString (Integer.toString (issue + 1), x + wimg / n - 10, y - dy);
            g.drawString ("p", x + wimg / (2 * n) - 10, y - dy / 2 - 10);
            trace (niveau + 1, issue + 1, x + wimg / n, y - dy, dy / 2, g);
        }
    }

    private void tracedep (int niveau, int issue, int x, int pas, Graphics g) {
        if (niveau < n) {
            int y0 = posd [index] + (posf [index]- posd [index ++]) * pas / ndep;
            int y1 = posd [index] + (posf [index]- posd [index ++]) * pas / ndep;
            g.setColor (Color.RED);
            g.drawLine (x, y0, x + wimg / n - 20, y1);
            g.drawString (Integer.toString (issue), x + wimg / n - 10, y1);
            g.drawString ("1-p", x + wimg / (2 * n) - 10, (y0 + y1) / 2 - 10);
            tracedep (niveau + 1, issue, x + wimg / n, pas, g);
            y0 = posd [index] + (posf [index]- posd [index ++]) * pas / ndep;
            y1 = posd [index] + (posf [index]- posd [index ++]) * pas / ndep;
            g.setColor (Color.BLUE);
            g.drawLine (x, y0, x + wimg / n - 20, y1);
            g.drawString (Integer.toString (issue + 1), x + wimg / n - 10, y1);
            g.drawString ("p", x + wimg / (2 * n) - 10, (y0 + y1) / 2 - 10);
            tracedep (niveau + 1, issue + 1, x + wimg / n, pas, g);
        }
    }

    public void paint (Graphics g1) {
        int w = getWidth ();
        int h = getHeight ();
        if ((img == null) || (w != wimg) || (h != himg)) {
            wimg = w;
            himg = h;
            img = createImage (w, h);
            g = img.getGraphics ();
        }
        efface ();
        g.setColor (Color.BLACK);
        index = 0;
        if (deplace)
            tracedep (0, 0, 0, pas, g);
        else            
            trace (0, 0, 0, himg / 2, himg / 4, g);

        g1.drawImage (img, 0, 0, this);
    }

////////////////////////////////////////////////////////////////////////////////

/* permet le fonctionnement en mode commande 13/02/15
 * usage : arbre.jar width height n
 */

	public static void main (String [] args) {
		int w = 800;
		int h = 800;
		int stn = 3;
		if (args != null)
			if (args.length >= 2) {
				try {
					w = Integer.parseInt (args [0]) ;
				}
				catch (NumberFormatException nfe) {}
				try {
					h = Integer.parseInt (args [1]) ;
				}
				catch (NumberFormatException nfe) {}
			}
			if (args.length >= 3) {
				try {
					stn = Integer.parseInt (args [2]) ;
				}
				catch (NumberFormatException nfe) {}
			}
		if (w <= 0) w = 800;
		if (h <= 0) h = 800;
		if (stn <= 0) stn = 3;

// Création et lancement de l'applet
		arbre a = new arbre ();
		a.n = stn;
		a.init ();
		a.start ();

// Création de la fenêtre contenant l'applet
		Frame f = new Frame ("Loi binomiale") ;
		f.addWindowListener (new fermer ()) ;
		f.add (a) ;
		f.setSize (w, h) ;
		f.setVisible (true) ;
	}

// Permet la fermeture de la fenêtre contenant l'applet
	protected static final class fermer extends WindowAdapter {
		public void windowClosing (WindowEvent e) {
			System.exit (0) ;
		}
	}

}