import java.awt.*;
import java.applet.Applet;

public class calcolatrice extends Applet {

Label display;      // Il display
Button bottoni [];  // L'array dei bottoni
/* Costanti per gli indici dei tasti */
static final int VIRGOLA = 10;
static final int PIU = 11;
static final int MENO = 12;
static final int PER = 13;
static final int DIVISO = 14;
static final int UGUALE = 15;
static final int C = 16;
static final int CE = 17;

double dispVal;   // Il numero sul display
double acc;       // Il totale da elaborare
/* Gestione input */
boolean decs;     // E' stata premuta la virgola? 
double curDec;    // Moltiplicatore del decimale corrente
int oldOper = 0;  // Operazione da eseuire (quella indicata tra gli operandi)

  /* Inizializzazione: crea l'interfaccia */
  public void init () {
  int i;
  GridBagLayout gridbag = new GridBagLayout ();    // layout manager
  GridBagConstraints c = new GridBagConstraints(); // 'constraints' per creare la tabella

    /* Inizializzazione */
    dispVal = 0.0;
    acc = 0.0;
    decs = false;

    setLayout (gridbag);             // Layout tabella flessibile

    display = new Label ("0.0");     // Crea il  display
    display.setBackground (Color.white);// Sfondo display

    bottoni = new Button [18];       // Array dei bottoni
    /* Crea i dieci bottoni numerici */
    for (i = 0; i < 10; i++)
      bottoni [i] = new Button (String.valueOf (i));
    /* Bottoni con i simboli */
    bottoni [VIRGOLA] = new Button (",");
    bottoni [PIU] = new Button ("+");
    bottoni [MENO] = new Button ("-");
    bottoni [PER] = new Button ("*");
    bottoni [DIVISO] = new Button ("/");
    bottoni [UGUALE] = new Button ("=");
    bottoni [C] = new Button ("C");
    bottoni [CE] = new Button ("CE");

    /* Inizializza i 'constraints' delle celle */
    c.fill = GridBagConstraints.BOTH;          // Espande in entrambe le direzioni
    c.weightx = 1.0;                           // Allarga l'elemento per riempire l'area
    c.weighty = 1.0;                           // Alza l'elemento per riempire l'area
    c.gridheight = 1;                          // Occupa una sola riga

    /* Prima riga - il solo display */
    c.gridwidth = GridBagConstraints.REMAINDER;// E' l'ultimo della sua riga
    gridbag.setConstraints(display, c);        // Applica i 'constraints'
    add(display);                              // Ed inserisce

    /* Seconda riga: ' 1  2  3  CE C ' */
    c.gridwidth = 1;                           // Elementi che occupano una sola cella (non ultimi)
    gridbag.setConstraints(bottoni [1], c);    // Applica i 'constraints'
    add(bottoni [1]);                          // Ed inserisce
    gridbag.setConstraints(bottoni [2], c);    // Applica i 'constraints'
    add(bottoni [2]);                          // Ed inserisce
    gridbag.setConstraints(bottoni [3], c);    // Applica i 'constraints'
    add(bottoni [3]);                          // Ed inserisce
    gridbag.setConstraints(bottoni [CE], c);   // Applica i 'constraints'
    add(bottoni [CE]);                         // Ed inserisce
    c.gridwidth = GridBagConstraints.REMAINDER;// Ultimo elemento
    gridbag.setConstraints(bottoni [C], c);    // Applica i 'constraints'
    add(bottoni [C]);                          // Ed inserisce

    /* Terza riga: ' 4  5  6    =    ' */
    c.gridwidth = 1;                           // Elementi che occupano una sola cella (non ultimi)
    gridbag.setConstraints(bottoni [4], c);    // Applica i 'constraints'
    add(bottoni [4]);                          // Ed inserisce
    gridbag.setConstraints(bottoni [5], c);    // Applica i 'constraints'
    add(bottoni [5]);                          // Ed inserisce
    gridbag.setConstraints(bottoni [6], c);    // Applica i 'constraints'
    add(bottoni [6]);                          // Ed inserisce
    c.gridwidth = GridBagConstraints.REMAINDER;// Ultimo elemento (largo due celle)
    gridbag.setConstraints(bottoni [UGUALE], c);// Applica i 'constraints'
    add(bottoni [UGUALE]);                     // Ed inserisce

    /* Quarta riga: ' 7  8  9  +  - ' */
    c.gridwidth = 1;                           // Elementi che occupano una sola cella (non ultimi)
    gridbag.setConstraints(bottoni [7], c);    // Applica i 'constraints'
    add(bottoni [7]);                          // Ed inserisce
    gridbag.setConstraints(bottoni [8], c);    // Applica i 'constraints'
    add(bottoni [8]);                          // Ed inserisce
    gridbag.setConstraints(bottoni [9], c);    // Applica i 'constraints'
    add(bottoni [9]);                          // Ed inserisce
    gridbag.setConstraints(bottoni [PIU], c);  // Applica i 'constraints'
    add(bottoni [PIU]);                        // Ed inserisce
    c.gridwidth = GridBagConstraints.REMAINDER;// Ultimo elemento
    gridbag.setConstraints(bottoni [MENO], c); // Applica i 'constraints'
    add(bottoni [MENO]);                       // Ed inserisce

    /* Quinta ed ultima riga: ' ,    0    *  / ' */
    c.gridwidth = 1;                              // Elementi che occupano una sola cella (non ultimi)
    gridbag.setConstraints(bottoni [VIRGOLA], c); // Applica i 'constraints'
    add(bottoni [VIRGOLA]);                       // Ed inserisce
    c.gridwidth = 2;                              // Elemento che occupano due celle
    gridbag.setConstraints(bottoni [0], c);       // Applica i 'constraints'
    add(bottoni [0]);                             // Ed inserisce
    c.gridwidth = 1;                              // Elementi che occupano una sola cella (non ultimi)
    gridbag.setConstraints(bottoni [PER], c);     // Applica i 'constraints'
    add(bottoni [PER]);                           // Ed inserisce
    c.gridwidth = GridBagConstraints.REMAINDER;   //end row
    gridbag.setConstraints(bottoni [DIVISO], c);  // Applica i 'constraints'
    add(bottoni [DIVISO]);                        // Ed inserisce
  }

  /* Metodo che gestisce la costruzione del numero */
  private void addCifra (int cifra) {
    if (cifra == VIRGOLA) {         // Se il tasto era ','
      if (!decs) {                  // Se e' gia stata premuta
        decs=true;                  // Memorizza che siamo nei decimali
        curDec = 1.0;               // Ed imposta il moltiplicatore
      }
    } else {                        // Altrimente erano cifre
      if (decs) {                   // Se siamo nella parte decimale
        curDec /= 10.0;             // Prima di tutto spostiamo il decimale a destra
        dispVal += curDec * cifra;  // Quindi aggiungiamo la cifra, moltiplicata per il peso
      } else {                      // Se invece siamo nella parte intera
        dispVal *= 10.0;            // Spostiamo a sinistra le cifre gia' inserite
        dispVal += cifra;           // Ed aggiungiamo la nuova cifra
      }
    }

    display.setText (String.valueOf (dispVal)); // Visualizza il nuovo numero
  }

  /* Merodo che esegue le operazioni */
  private void oper (int op) {
    switch (oldOper) {         // Visto che la notazione e' infissa, l'oerazione da eseguire
                               // e' quella indicata 'la volta scorsa'
      case PIU :               // Somma
        acc += dispVal;
        break;
      case MENO :              // Sottrazione
        acc -= dispVal;
        break;
      case PER :               // Moltiplicazione
        acc *= dispVal;
        break;
      case DIVISO :            // Divisione
        if (dispVal != 0.0) {  // (solo se il divisore e' diverso da 0)
          acc /= dispVal;
        }
        break;
      case UGUALE :            // Tasto uguale (al ciclo dopo)
        if (dispVal != 0.0) {  // Se si e' introdotta alcuna cifra (empirico)
          acc = dispVal;       // Prendiamo il numero introdotto come primo operando
        }
        break;
      default :                // (siamo alla prima chiamata)
        acc = dispVal;         // Prendiamo il numero introdotto come primo operando
    }
    dispVal = 0.0;             // Con ogni operazione si azzera il display
    decs = false;              // E di conseguenza il flag della virgola
    display.setText (String.valueOf (acc)); // Visualizza l'accumulatore
    oldOper = op;              // Memorizza l'operatore premuto ora, per poi
  }

  /* metodo che cancella (tasti C e CE) */
  private void canc (boolean isAll) {
    dispVal = 0.0;  // Azzera il display
    decs = false;   // Ed il flag della virgola
    if (isAll) {    // Se e' C (cancella tutto)
      acc = 0.0;    // Azzera anche l'accumulatore
      oldOper = 0;  // E l'operazione in corso
    }
    display.setText (String.valueOf (dispVal)); // Visualizza lo 0
  }

  /* Gestisce tutti i tasti */
  public boolean action(Event event, Object arg) {
  int i;
    for (i = 0; i <= VIRGOLA; i++)       // Loop sui tasti numerici e ','
      if (event.target == bottoni [i]) { // Se l'evento corrisponde a...
        addCifra (i);                    // Eseguo l'azione
        return true;
      }
    for (i = PIU; i <= UGUALE; i++)      // Loop sui tasti operatore
      if (event.target == bottoni [i]) { // Se l'evento corrisponde a...
        oper (i);                        // Eseguo l'azione
        return true;
      }
    /* Tasti 'C' e 'CE' */
    if (event.target == bottoni [C] || event.target == bottoni [CE]) {
      canc (event.target == bottoni [C]); // Esegue (parametro: "e' 'C'?")
      return true;
    }
    return true;
  }

}