/**
 * sp.java
 *
 * La symétrie perturbée, d'après l'ouvert n°49 de décembre 1987
 *
 * Jean-Paul Quelen 14/04/20
 */

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class sp extends JPanel implements MouseListener {
	static final long serialVersionUID = 200414L;
// dir =	0	1	2	3	4	5	6	7
//			N	NE	E	SE	S	SO	O	NO
	int xmax, ymax, Niter, X0, Y0, dir, Xp, Yp;
	double l, x, y;
	char or;
	TextField tfn, tfl, tor, lcalc;

	public sp() {
		Font f = new Font (Font.SANS_SERIF, Font.PLAIN, 10);
		Label lbl;

		add (lbl = new Label ("Orientation initiale (N, S, O, E)"));
		nlab (lbl, f);
		or = 'E';
		add (tor = new TextField ("E", 1));

		add (lbl = new Label ("Itérations : "));
		nlab (lbl, f);
		Niter = 2;
		add (tfn = new TextField ("2", 10));

		add (lbl = new Label ("Longueur d'un pas (en pixels)"));
		nlab (lbl, f);
		l = 8.0;
		add (tfl = new TextField ("8.0", 10));

		add (lcalc = new TextField (20));
		lcalc.setFont (f);
		lcalc.setBackground (Color.black);
		lcalc.setForeground (Color.white);
		addMouseListener (this);
	}

	private void nlab (Label lbl, Font f) {
		lbl.setFont (f);
		lbl.setBackground (Color.black);
		lbl.setForeground (Color.white);
	}

	public void init() {
		x = Xp = X0;
		y = Yp = Y0;
		dir = "NESO".indexOf (or) * 2;
	}

	public void avance (Graphics g, double l) {
		switch (dir) {
			case 1, 2, 3 :
				x += l;
				break;
			case 5, 6, 7 :
				x -= l;
		}
		switch (dir) {
			case 3, 4, 5 :
				y += l;
				break;
			case 7, 0, 1 :
				y -= l;
		}
		int X = (int) x;
		int Y = (int) y;
		if (X != Xp || Y != Yp) {
			g.drawLine (Xp, Yp, X, Y);
			Xp = X;
			Yp = Y;
		}
	}

	public void gauche (Graphics g) {
		avance (g, l);
		dir = (dir + 7) % 8;			// ne pas faire (dir - 1) % 8
		avance (g, l / 2.0);
		dir = (dir + 7) % 8;
		avance (g, l);
	}

	public void droite (Graphics g) {
		avance (g, l);
		dir = (dir + 1) % 8;
		avance (g, l / 2.0);
		dir = (dir + 1) % 8;
		avance (g, l);
	}

	public void sn (int n, Graphics g) {
		if (n > 0) {
			sn (n - 1, g);
			gauche (g);
			snm1 (n - 1, g);
		}
	}

	public void snm1 (int n, Graphics g) {
		if (n > 0) {
			sn (n - 1, g);
			droite (g);
			snm1 (n - 1, g);
		}
	}

	public void update (Graphics g) {
		paint (g);
	}

	public void paint (Graphics g) {
		lcalc.setText ("Calcul en cours");
		if (xmax != getWidth() || ymax != getHeight()) {
			xmax = getWidth();
			ymax = getHeight();
			X0 = xmax / 2;
			Y0 = ymax / 2;
		}
		init ();
		g.setColor (Color.black);
		g.fillRect (0, 0, xmax, ymax);
		g.setColor (Color.white);
		avance (g, l);
		sn (Niter, g);
		avance (g, l);
		lcalc.setText ("");
	}

	public void mousePressed (MouseEvent e) {
		char or1 = tor.getText().toUpperCase().charAt(0);
		if ("NSOE".indexOf (or1) != -1) {
			or = or1;
		}
		tor.setText (Character.toString (or));

		int niter1 = Niter;
		try {
			niter1 = Integer.parseInt (tfn.getText());
			if (niter1 > 0)
				Niter = niter1;
		}
		catch (NumberFormatException nfe) {}
		tfn.setText (Integer.toString (Niter));

		double l1 = l;
		try {
			l1 = Double.parseDouble (tfl.getText());
			if (l1 > 0.0)
				l = l1;
		}
		catch (NumberFormatException nfe) {}
		tfl.setText (Double.toString (l));
		if (e.getY() > 20) {
			X0 = e.getX();
			Y0 = e.getY();
			init();
		}
		repaint ();
	}

	public void mouseReleased (MouseEvent e) {}
	public void mouseClicked (MouseEvent e) {}
	public void mouseEntered (MouseEvent e) {}
	public void mouseExited (MouseEvent e) {}

////////////////////////////////////////////////////////////////////////////////

	public static void main (String [] args) {
		int w = 800;
		int h = 800;

		sp s = new sp();

		JFrame f = new JFrame ("La symétrie perturbée");
		f.setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);
		f.add (s);
		f.setSize (w, h);
		f.setVisible (true);
	}

}

