/**
 * yeaxpb1.java - jpq - 29/03/99 - jdk1.2 - double-buffering
 * main() ajouté le 20/12/17; modification le 05, 12 et 22/09/22
 */

import java.awt.event.*;
import java.awt.*;
import javax.swing.*;
import java.util.Random;
import geo.*;

public class yeaxpb1 extends JFrame implements ActionListener {
	static final long serialVersionUID = 220922L;
	static Repere R;
	static Image img;
	static Graphics g1;
	int gw, gh;
	Feuille dessin = new Feuille();

// on definit ici les objets mathématiques
	static PointLibre A, B;
	static Pt L;
	static Pt b;
	static Segment AL, BL;
	static Droite AB, ypy;
	int pas = 40;
	Random rnd;
	JTextField tan, tad, tbn, tbd;
	String sbravo = "Bravo !";
	String sabon = "Le coefficient directeur est exact";
	String sbbon = "L'ordonnée à l'origine est exacte";
	String squestion = "???";
	JButton npts, ok;
	JLabel message;

	public yeaxpb1() {
		super ("y = a x + b");
		Font f = new Font ("Arial", Font.PLAIN, 16);
		setLayout (new BorderLayout());
		JPanel jp = new JPanel();
		add (jp, BorderLayout.NORTH);
		
		jp.add (message = new JLabel ("y ="));
		message.setFont (f);
		jp.add (tan = new JTextField ("", 8));
		jp.add (message = new JLabel ("/"));
		message.setFont (f);
		jp.add (tad = new JTextField ("", 8));
		jp.add (message = new JLabel ("x +"));
		message.setFont (f);
		jp.add (tbn = new JTextField ("", 8));
		jp.add (message = new JLabel ("/"));
		message.setFont (f);
		jp.add (tbd = new JTextField ("", 8));
		npts = new JButton ("Nouveaux points");
		npts.addActionListener (this);
		jp.add (npts);
		ok = new JButton ("Ok");
		ok.addActionListener (this);
		jp.add (ok);
		rnd = new Random();
		message = new JLabel (sabon);
		message.setFont (f);
		jp.add (message);
		setBackground (Color.WHITE);
		add (dessin, BorderLayout.CENTER);

		setDefaultCloseOperation (JFrame.EXIT_ON_CLOSE);	// à ne pas mettre après super ("y = a x + b");
		setSize (900, 700);
		setVisible (true);
	}

protected class Feuille extends Canvas implements MouseListener, MouseMotionListener {
	static final long serialVersionUID = 220912L;

	public Feuille() {
		setBackground (Color.WHITE);
		addMouseMotionListener (this);
		addMouseListener (this);
	}

	public void update (Graphics g) {
		paint (g);
	}

	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();

// on initialise ici les objets mathématiques
			if (R == null) {
				R = new Repere (gw / 2, gh / 2, gw, gh, pas, pas);
				A = new PointLibre (1.0, 3.0);
				B = new PointLibre (-1.0, -1.0);
				AB = new Droite();
				L = new Pt();
				ypy = new Droite (1.0, 0.0, 0.0);
				AL = new Segment();
				BL = new Segment();
			} else {
				R.MAJ (gw / 2, gh / 2, gw, gh, pas, pas);
			}
			message.setVisible (false);
		}

// on recalcule les objets liés
		A.MAJ (0.5 * Math.round (2.0 * A.x), 0.5 * Math.round (2.0 * A.y));
		B.MAJ (0.5 * Math.round (2.0 * B.x), 0.5 * Math.round (2.0 * B.y));
		AB.MAJ (A, B);
		if (A.x > B.x)
			L.MAJ (A.x, B.y);
		else
			L.MAJ (B.x, A.y);
		AL.MAJ (A, L);
		BL.MAJ (B, L);
		b = Pt.intersection (AB, ypy);

		g1.setFont (new Font (Font.SANS_SERIF, Font.PLAIN, 10));

// on trace dans la couleur du fond
		g1.setColor (getBackground());
		g1.fillRect (0, 0, R.XMAX, R.YMAX);

// on trace
		g1.setColor (Color.YELLOW);
		R.trace_grille (0.5, 0.5, g1);

		g1.setColor (Color.BLACK);
		R.cadre (g1);

		g1.setColor (Color.RED);
		R.trace (g1);
		R.trace_repere_gradue (1.0, 1.0, g1);

		g1.setColor (Color.GREEN);
		AL.trace ("", R, g1);
		BL.trace ("", R, g1);
		L.traceNom ("L", R, g1);

		g1.setColor (Color.BLUE);
		AB.trace ("", R, g1);

		g1.setColor (Color.BLACK);
		b.trace ("", R, g1);

		g1.setColor (Color.RED);
		A.trace ("A", R, g1);
		B.trace ("B", R, g1);

		g.drawImage (img, 0, 0, this);
	}


	public void mousePressed (MouseEvent e) {
		int X = e.getX();
		int Y =  e.getY();
		if ((A.deplace = A.zone (X, Y, R)) || (B.deplace = B.zone (X, Y, R))) {}
	}
 
	public void mouseDragged (MouseEvent e) {
		int X = e.getX();
		int Y = e.getY();
		A.bouge (X, Y, R);
		B.bouge (X, Y, R);
		message.setVisible (false);
		repaint();
	}

	public void mouseReleased (MouseEvent e) {
		A.deplace = B.deplace = false;
	}

	public void mouseMoved (MouseEvent e) {
		int X = e.getX();
		int Y = e.getY();
		if (A.zone (X, Y, R) || B.zone (X, Y, R)) {
			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 de protected class Feuille

	private int[] reducfraction (int n, int d) {
		int[] r = new int [2];
		if (n == 0) {
			r [0] = 0;
			r [1] = 1;
			return r;
		}
		boolean signe = n * d < 0;
		n = Math.abs (n);
		d = Math.abs (d);
		int a = (n >= d) ? n : d;
		int b = (n >= d) ? d : n;
		while (b > 0)
			b = a % (a = b);
		n = n / a;
		d = d / a;
		r [0] = (signe)? - n : n;
		r [1] = d;
		return r;
	}

	public void actionPerformed (ActionEvent e) {
		if (e.getSource() == npts) {
			A.MAJ ((double)(rnd.nextInt() % 8), (double)(rnd.nextInt() % 6));
			double d;
			do
				d = (double)(rnd.nextInt() % 8);
			while (d == A.x);
			B.MAJ (d, (double)(rnd.nextInt() % 6));
			message.setVisible (false);
			tan.setText ("");
			tad.setText ("");
			tbn.setText ("");
			tbd.setText ("");
		} else if (e.getSource() == ok) {
			int an = 0;
			int ad = 1;
			int bn = 0;
			int bd = 1;
			try {
				an = Integer.parseInt (tan.getText().trim());
				ad = Integer.parseInt (tad.getText().trim());
				bn = Integer.parseInt (tbn.getText().trim());
				bd = Integer.parseInt (tbd.getText().trim());
			}
			catch (NumberFormatException excp) {}
			if (ad * bd != 0) {
				int[] r = new int [2];
				r = reducfraction (an, ad);
				an = r [0];
				ad = r [1];
				r = reducfraction (bn, bd);
				bn = r [0];
				bd = r [1];
				int den = (int)((B.x - A.x) * 4.0);
				boolean atrouve = (int)((B.y - A.y) * 4.0) * ad == den * an;
				boolean btrouve = (int)((A.y * B.x - A.x * B.y) * 4.0) * bd == den * bn;
				if (atrouve || btrouve) {
					message.setVisible (true);
					if (atrouve && btrouve)
						message.setText (sbravo);
					else if (atrouve)
						message.setText (sabon);
					else
						message.setText (sbbon);
				}
			} else {
				message.setVisible (true);
				message.setText (squestion);
			}
			tan.setText (Integer.toString (an));
			tad.setText (Integer.toString (ad));
			tbn.setText (Integer.toString (bn));
			tbd.setText (Integer.toString (bd));
		}
		dessin.repaint();
	}

	public static void main (String[] args) {
		new yeaxpb1();
	}

}
