/**
 * clifford.java - jpq - 27/01/99
 * 21/03/99 - jdk1.2 - double-buffering
 * modifications et ajout de main() le 03/01/18 - modifications le 04, le 09 et le 22/09/22
 */

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import geo.*;
import java.util.*;

public class clifford extends JFrame implements ActionListener {
	static final long serialVersionUID = 220922L;
	static Repere R;
	static Pt P;
	static PointLibre Oi;
	static Cercle COr, Ci, Cijk;
	int n, n1, id;
	boolean chgtn;
	JTextField tf;
	JLabel ln1;
	JButton Ok, Suivant, Precedent;
	Vector<Color> Vcouleur;
	Vector<PointSurCercle> VOi;
	Random alea;
	double r = 1;
	Feuille dessin = new Feuille();

	public clifford (String titre) {
		super (titre);
		setLayout (new BorderLayout());
		JPanel jp = new JPanel();
		add (jp, BorderLayout.NORTH);
		n1 = 0;
		n = 3;
		jp.add (tf = new JTextField ("3", 10));
		jp.add (Ok = new JButton ("Ok"));
		Ok.addActionListener (this);
		jp.add (Precedent = new JButton ("<<"));
		Precedent.addActionListener (this);
		jp.add (Suivant = new JButton (">>"));
		Suivant.addActionListener (this);
		jp.add (ln1 = new JLabel (Integer.toString (n1)));
		alea = new Random();
		add (dessin, BorderLayout.CENTER);
	}

protected class Feuille extends Canvas implements MouseListener, MouseMotionListener {
	static final long serialVersionUID = 220909L;
	int gw, gh;
	static Image img;
	static Graphics g1;

	public Feuille() {
		setBackground (Color.WHITE);
		addMouseMotionListener (this);
		addMouseListener (this);
	}

	public void update (Graphics g) {
		paint (g);
	}

	public void recursion (int k, Pt SPi, int ind, Graphics g1) {
		PointSurCercle Pi = VOi.elementAt (ind);
		Pt P = new Pt (SPi.x + Pi.x, SPi.y + Pi.y);
		if (k % 2 == 1) {
			g1.setColor (Color.black);
			P.trace ("", R, g1);
		} else {
			g1.setColor (Vcouleur.elementAt (k / 2 - 1));
			new Cercle (P.x, P.y, r).trace ("", R, g1);
		}
		for (int i = ind + 1; (i < n) && (k < n1); i++)
			recursion (k + 1, P, i, g1);
	}

	public void paint (Graphics g) {
		if (img == null || gw != getSize().width || gh != getSize().height) {
			gw = getSize().width;
			gh = getSize().height;
			img = createImage (gw, gh);
			g1 = img.getGraphics();
			g1.setFont (new Font ("Arial", Font.PLAIN, 10));

			if (R == null) {
				R = new Repere (gw / 2, gh / 2, gw, gh, 80.0, 80.0);
				COr = new Cercle (new Pt (0.0, 0.0), r);
				VOi = new Vector<PointSurCercle>();
				Vcouleur = new Vector<Color>();
				chgtn = true;
			} else {
				R.MAJ (gw / 2, gh / 2, gw, gh, 80.0, 80.0);
			}
		}

// on recalcule les objets liés si changement de la valeur n
	if (chgtn) {
		chgtn = false;
		VOi.removeAllElements();
		Vcouleur.removeAllElements();
		for (int i = 0; i < n; i++) {
			VOi.addElement (new PointSurCercle (alea.nextDouble() * 2 * Math.PI, COr));
			if (i % 2 == 0)
				Vcouleur.addElement (new Color (alea.nextFloat(), alea.nextFloat(), alea.nextFloat()));
		}
	}

// on trace
		g1.setColor (getBackground());
		g1.fillRect (0, 0, R.XMAX, R.YMAX);

		g1.setColor (Color.BLACK);
		R.cadre (g1);

		g1.setColor (Color.RED);
		R.trace (g1);
		for (int i = 0; i < VOi.size(); i++) {
			PointSurCercle Pi = VOi.elementAt(i);
			g1.setColor (Color.RED);
			Pi.trace ("", R, g1);
			g1.setColor (Color.GREEN);
			(new Cercle (Pi, r)).trace ("", R, g1);
		}
		if ((n1 > 0) && (n > 1))
			for (int i = 0; i < VOi.size(); i++)
				for (int j = i + 1; j < VOi.size(); j++)
					recursion (1, VOi.elementAt (i), j, g1);
		g.drawImage (img, 0, 0, this);
	}

	public void mousePressed (MouseEvent e) {
		int X = e.getX();
		int Y =  e.getY();
		id = -1;
		for (int i = 0; i < VOi.size(); i++) {
			if ((VOi.elementAt(i)).deplace = (VOi.elementAt(i)).zone (X, Y, R)) {
				id = i;
				break;
			}
		}
	}

	public void mouseDragged (MouseEvent e) {
		if (id >= 0) {
			(VOi.elementAt(id)).bouge (e.getX(), e.getY(), R);
		}
		repaint();
	}

	public void mouseReleased (MouseEvent e) {
		if (id >= 0) {
			(VOi.elementAt(id)).deplace = false;
			id = -1;
		}
	}

	public void mouseMoved (MouseEvent e) {
		int X = e.getX();
		int Y = e.getY();
		int i = 0;
		for (; i < VOi.size(); i++) {
			if ((VOi.elementAt(i)).zone (X, Y, R)) {
				break;
			}
		}
		if (i < VOi.size()) {
			setCursor (new Cursor (Cursor.HAND_CURSOR));
		} else {
			setCursor (new Cursor (Cursor.DEFAULT_CURSOR));
		}			
	}

	public void mouseClicked (MouseEvent e) {}
	public void mouseEntered (MouseEvent e) {}
	public void mouseExited (MouseEvent e) {}

}	// fin protected class Feuille

	public void actionPerformed (ActionEvent e) {
		if (e.getSource() == Ok) {
			int nn = n;
			try {
				nn = Integer.parseInt (tf.getText().trim());
			}
			catch (NumberFormatException excp) {}
			nn = Math.max (1, nn);
			chgtn = true;	//(n != nn);
			n = nn;
			tf.setText (Integer.toString (n));
			n1 = 0;
			ln1.setText (Integer.toString (n1));
			dessin.repaint();
		} else if (e.getSource() == Suivant) {
			if(n1 < n - 1)
				n1++;
				dessin.repaint();
				ln1.setText (Integer.toString (n1));
		} else if (e.getSource() == Precedent) {
			if(n1 > 0)
				n1--;
				dessin.repaint();
				ln1.setText (Integer.toString (n1));
		}
	}

	public static void main (String [] args) {
		clifford c = new clifford("Les cercles de Clifford");
		c.setDefaultCloseOperation (JFrame.DISPOSE_ON_CLOSE);
		c.setSize (500, 500);
		c.setVisible (true);
	}

}
