/*
 * Samira & Aymeric
 * RTM1
 * 28/10/2004
 * Java - M1 - TP1 - Calculatrice
 * fichier : Calculatrice.java
 */


import java.awt.*;
import java.util.*;
import java.awt.event.*;
import java.lang.*;
import java.lang.String;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.Container;
import java.awt.Component;
import java.awt.Insets;

public class Calculatrice extends Frame
{ 
	/*
	 * déclarations des éléments de la calculatrice
	 */
    Button bt_efface, bt_division, bt_produit, bt_7, bt_8, bt_9, bt_moins;
    Button bt_4, bt_5, bt_6, bt_plus;
    Button bt_1, bt_2, bt_3, bt_egal;
    Button bt_0, bt_signe, bt_point;
    GridBagLayout gridbag;   
    GridBagContainLayout gbcl;
    Label label;
    GeneralListener gl;
    
    /*
     * on définit une font SansSerif, en gras et de taille 18
     */
    Font boldFont = new Font("SansSerif", Font.BOLD, 18);
    
    public static String EFFACE = "efface";
    public static String ZERO = "zero";
    public static String UN = "un";
    public static String DEUX = "deux";
    public static String TROIS = "trois";
    public static String QUATRE = "quatre";
    public static String CINQ = "cinq";
    public static String SIX = "six";
    public static String SEPT = "sept";
    public static String HUIT = "huit";
    public static String NEUF = "neuf";
    public static String PLUS = "plus";
    public static String MOINS = "moins";
    public static String DIVISER = "diviser";
    public static String MULTIPLIER = "multiplier";
    public static String POINT = "point";
    public static String EGAL = "egal";
    public static String SIGNE = "signe";

	/*
	 * Fonction main() de notre programme qui appelle la Calculatrice
	 */
    public static void main(String argv[])
    {
		new Calculatrice().show();
    }

	/*
	 * Fonction makeButtons() appelée pour la création des boutons
	 */
    void makeButtons() {
		
		/*
		 * le paramètre passé à "new Button()" définit le texte visible sur le bouton
		 */
		bt_efface = new Button("Efface");
		bt_division = new Button("/");
		bt_produit = new Button("*");
		bt_7 = new Button("7");
		bt_8 = new Button("8");
		bt_9 = new Button("9");
		bt_moins = new Button("-");
		bt_4 = new Button("4");
		bt_5 = new Button("5");
		bt_6 = new Button("6");
		bt_plus = new Button("+");
		bt_1 = new Button("1");
		bt_2 = new Button("2");
		bt_3 = new Button("3");
		bt_egal = new Button("=");
		bt_0 = new Button("0");
		bt_point = new Button(".");
		bt_signe = new Button("+/-");
		
		/*
		 * setForeground() permet de définir la couleur du texte du bouton
		 */
		bt_efface.setForeground(Color.red);
		bt_egal.setForeground(Color.blue);
   }

	/*
	 * Constructeur de la classe Calculatrice
	 */
	public Calculatrice()
    {
    	/*
    	 * on utilise le GridBagContainLayout() donné dans le sujet pour l'interface graphique
    	 * et le positionnement des éléments
    	 */
		gbcl = new GridBagContainLayout();
		setLayout(gbcl);
		
		
		/******** ZONE DE TEXTE ***********/
		
		/*
		 * On utilise un label pour pouvoir aligner le texte sur la droite
		 */
		label = new Label("0",Label.RIGHT);
		
		/*
		 * la fonction constraint() permet de placer les éléments sur le layout
		 */
		gbcl.constrain(this,label,0,0,4,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		
		/*********************************/

		
		/************ BOUTONS ************/
		
		makeButtons();
		
		/*
		 * Placement de tous les boutons
		 */
		gbcl.constrain(this,bt_efface,0,1,2,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		gbcl.constrain(this,bt_division,2,1,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		gbcl.constrain(this,bt_produit,3,1,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		
		gbcl.constrain(this,bt_7,0,2,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		gbcl.constrain(this,bt_8,1,2,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		gbcl.constrain(this,bt_9,2,2,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		gbcl.constrain(this,bt_moins,3,2,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		
		gbcl.constrain(this,bt_4,0,3,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		gbcl.constrain(this,bt_5,1,3,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		gbcl.constrain(this,bt_6,2,3,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		gbcl.constrain(this,bt_plus,3,3,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		
		gbcl.constrain(this,bt_1,0,4,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		gbcl.constrain(this,bt_2,1,4,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		gbcl.constrain(this,bt_3,2,4,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		gbcl.constrain(this,bt_egal,3,4,1,2,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);

		gbcl.constrain(this,bt_0,0,5,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		gbcl.constrain(this,bt_point,1,5,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		gbcl.constrain(this,bt_signe,2,5,1,1,GridBagConstraints.BOTH,GridBagConstraints.CENTER,1.0,1.0,0,0,0,0);
		
		/*********************************/
		
		
		/*
		 * GeneralListener() et addMouseListener() sont utilisés pour la gestion des événements
		 */
		gl = new GeneralListener(label, this);
		
		bt_0.addMouseListener(gl);
		bt_1.addMouseListener(gl);
		bt_2.addMouseListener(gl);
		bt_3.addMouseListener(gl);
		bt_4.addMouseListener(gl);
		bt_5.addMouseListener(gl);
		bt_6.addMouseListener(gl);
		bt_7.addMouseListener(gl);
		bt_8.addMouseListener(gl);
		bt_9.addMouseListener(gl);
		bt_efface.addMouseListener(gl);

		bt_plus.addMouseListener(gl);
		bt_moins.addMouseListener(gl);
		bt_division.addMouseListener(gl);
		bt_produit.addMouseListener(gl);
		bt_point.addMouseListener(gl);
		bt_egal.addMouseListener(gl);
		bt_signe.addMouseListener(gl);
		
		/*
		 * setFont() applique la font définie plus haut à toute la calculatrice
		 */
		setFont(boldFont);

		/*
		 * setSize() permet de définir la largeur et hauteur de la calculatrice
		 */
		setSize(280, 300);
		
		/*
		 * setLocationRelaticeTo() permet de placer la calculatrice au centre de l'écran
		 */
		setLocationRelativeTo(this.getParent());
		
		/*
		 * setTitle() définit le titre de la fenêtre
		 */
		setTitle("Calculatrice");
		
		/*
		 * Evenement permettant de fermer la fenêtre lors du clic sur la croix
		 */
		this.addWindowListener(new java.awt.event.WindowAdapter() {
        	public void windowClosing(java.awt.event.WindowEvent evt) {
                dispose();
        } } );

    }

	/*
	 * classe utilisée dans la gestion des événements de la souris
	 */
	class GeneralListener extends MouseAdapter
	{
		Label txt;
		Frame win;
		boolean clear=false; // clear est utilisé pour savoir si l'affichage doit être remis à 0
		boolean point=false; // point est à true lorsqu'on utilise le point
		boolean multiop=true; // seul le dernier opérateur est retenu pour le calcul
		String op; // contient l'opérateur utilisé
		double a,b,c;
		Calcul moncalcul=new Calcul(); // moncalcul utilise la classe Calcul() qui permet de faire les calculs (!)
		
		/*
		 * Constructeur de la classe
		 */
		public GeneralListener(Label text, Frame window)
		{
			this.txt = text;
			this.win = window;
			this.c=0;
		}
		
		/*
		 * événement enclenché par le clic de souris
		 */
		public void mouseClicked(MouseEvent e)
		{
			String cmd="0"; // par défaut la commande est 0
	
			/*
			 * Selon le bouton cliqué (testé par getComponent(), on définit la touche tapée
			 */
			if (e.getComponent() == bt_0) cmd="0";
			else if (e.getComponent() == bt_1) cmd="1";
			else if (e.getComponent() == bt_2) cmd="2";
			else if (e.getComponent() == bt_3) cmd="3";
			else if (e.getComponent() == bt_4) cmd="4";
			else if (e.getComponent() == bt_5) cmd="5";
			else if (e.getComponent() == bt_6) cmd="6";
			else if (e.getComponent() == bt_7) cmd="7";
			else if (e.getComponent() == bt_8) cmd="8";
			else if (e.getComponent() == bt_9) cmd="9";
			else if (e.getComponent() == bt_plus) cmd="+";
			else if (e.getComponent() == bt_produit) cmd="*";
			else if (e.getComponent() == bt_division) cmd="/";
			else if (e.getComponent() == bt_moins) cmd="-";
			else if (e.getComponent() == bt_efface) cmd="Efface";
			else if (e.getComponent() == bt_egal) cmd="=";
			else if (e.getComponent() == bt_point) cmd=".";
			else if (e.getComponent() == bt_signe) cmd="signe";
			
			/*
			 * Affichage utilisé pour le débugage
			 */
			System.out.println(cmd);
			
			/*
			 * Si on appuie sur le bouton Efface on réinitialise les paramètres
			 * de plus la zone de texte affiche 0
			 */
			if (cmd == "Efface")
			{
				txt.setText("0");
				a=0;
				b=0;
				op="";
				point=false;
				bt_point.setEnabled(true);
				multiop=false;
				clear=false;
			}
	
			/*
			 * Ici on teste que le bouton cliqué est un chiffre
			 */
	   	    if (Character.isDigit(cmd.charAt(0)))
		    {
		    	/*
		    	 * si clear est à true, cela signifie qu'on doit mettre 0 dans la zone de texte
		    	 * Cela est utilisé, par exemple, lorsqu'on avait un Error affiché précédemment
		    	 */
				if (clear == true)
				{
					txt.setText("0");
					clear=false;
				}
				
				/*
				 * Cette condition s'applique pour afficher 2 au lieu de 02
				 */
		    	if ((txt.getText().charAt(0) == '0') && (point == false)) txt.setText(cmd);
		    	
		    	/*
		    	 * Dans les autres cas on peut simplement ajouter les chiffres à la suite
		    	 */
		    	else txt.setText(txt.getText() + cmd);

		    	multiop=false;
		    	if (point == false) bt_point.setEnabled(true);
		    }

			/*
			 * Si on clique sur l'un des opérateurs
			 */
			else if ((cmd == "+") || (cmd == "-") || (cmd == "*") || (cmd == "/") || (cmd == "="))
			{
				boolean ok=true;
				
				/*
				 * Si on a l'affichage "Error", on remplace le texte existant par 0
				 */
				if (txt.getText() == "Error") txt.setText("0");

				/*
				 * op va être égal au dernier opérateur choisi
				 * La condition ci-dessous est true lorsqu'on tape plusieurs opérations
				 * Exemple : 2 + 3 + ...
				 * multiop sert dans la gestion de plusieurs opérateurs entrés à la suite.
				 * Seul le dernier opérateur entré est pris en compte. Par exemple :
				 * 2 + - 1 = 1
				 */
				if (((op == "+") || (op == "-") || (op == "*") || (op == "/")) && (multiop == false))
				{
					b=Double.parseDouble(txt.getText()); // on récupère le nombre courant
					/*
					 * On utilise la classe Calcul() pour faire le calcul.
					 * Cette classe va aussi s'occuper de l'affichage.
					 * ok va être true si tout s'est bien passé, false dans l'autre cas
					 */
					ok=moncalcul.operation(a,b,op,txt);
				}
				
				/*
				 * On interdit l'utilisation du point/virgule tant qu'on a pas choisit un chiffre
				 */
				bt_point.setEnabled(false);
				
				/*
				 * multiop passe à true pour signifier qu'on vient de choisir une opération
				 */			
				multiop=true;

				/*
				 * Si l'affichage est correct, on place le contenu du label dans 'a'
				 * pour être utilisé plus tard
				 */
				if (ok)
				{
					a=Double.parseDouble(txt.getText());
					/*
					 * ici on divise par 1 pour virer les 0 surplus comme dans l'exemple :
					 * 2.000000000 devient 2.0
					 */
					ok=moncalcul.operation(a,1,"/",txt);
				}

				/*
				 * Si le bouton choisit est =, on met l'opérateur à vide
				 */
				if (cmd != "=")	op=cmd;
				else op="";
								
				point=false;
				
				clear=true;
			}
			
			/*
			 * Si on choisit le bouton poin
			 */
			else if (cmd == ".")
			{
				txt.setText(txt.getText() + ".");
				/*
				 * Après avoir utilisé le point, on désactive la touche pour éviter
				 * d'avoir plusieurs virgules à la suite
				 */
				bt_point.setEnabled(false);
				point=true;
			}
			
			/*
			 * Si le bouton signe est cliqué, on multiplie l'affichage courant par -1
			 */
			else if (cmd == "signe")
			{
				txt.setText(Double.toString(Double.parseDouble(txt.getText()) * -1));
			}
		}
	}	
}


