/** file: CalAp114.java */

import java.awt.*;
import java.awt.event.*;
import java.lang.Boolean;
import java.lang.Exception;

/** ========================================
      Calcolatrice (APPLET) per JDK v1.1.4
    ======================================== */

/** ===== IL DISPLAY DELLA CALCOLATRICE ===== */
class DispCalcPadre extends Panel {
  protected myFrame MiaFin = null;
  
  public DispCalcPadre(){
    createDisplay("");
  }

  protected void createDisplay (String TitoloFin) {
    MiaFin = new myFrame (TitoloFin);
    MiaFin.resize (634,474);
    MiaFin.add (this);  // AGGIUNGE SE STESSO ALLA FINESTRA!
  }

  protected void mostraFinestra () {
    if (MiaFin != null) {
      MiaFin.show();
      MiaFin.setCursor (new Cursor (Cursor.HAND_CURSOR));
    }
  }
}

class DispCalc114 extends DispCalcPadre {
  protected CalAp114 MyCalc;  // USA LA SUA CALCOLATRICE (uso M.V.C.)

  protected TextArea AreaMsg;      // area per i messaggi
  protected TextArea AreaValuta;   // area per str.da valutare
  protected TextArea AreaRisulta;  // area per il risultato
  protected TextArea AreaAmbient;  // area per il risultato

  protected myButton BottoneUgu = new myButton("= VAL", "", 'v');
  protected myButton BottoneCAN = new myButton("CANC",  "", 'c');

  protected static   int MAX_BOT      = 26;
  protected myButton ArrBottoni[] = new myButton [MAX_BOT];
          // NB: TUTTI I BOTTONI CHE AGGIUNGONO CARATTERI IN STR.
                                   // Testo del bottone:
  protected String   StrSuBot[]   = {"1", "2", "3", "+",
                                     "4", "5", "6", "-",
                                     "7", "8", "9", "x",
                                     "(", "0", ")", ":",
                                     ".", "sqr", "sqrt", "inv",
                                     "X", "Y", "A", "B",
                                     "= Ass", "Spazio"};
                                   // Da inserire nella stringa:
  protected String   StrPerStr[]  = {"1", "2", "3", "+",
                                     "4", "5", "6", "-",
                                     "7", "8", "9", "*",
                                     "(", "0", ")", "/",
                                     ".", "sqr", "sqrt", "inv",
                                     "X", "Y", "A", "B",
                                     "=", " "};
  protected Panel    PannelloBott;    // Pannello per i bottoni

  Checkbox CBTracAlb  = new Checkbox ("Disegna Albero",  true);
  Checkbox CancInput  = new Checkbox ("Cancella Input",  true);
  Checkbox DispAction = new Checkbox ("Mostra 'action'", false);
  Checkbox DispCostr  = new Checkbox ("Costruzione RI",  true);
  Checkbox DispValut  = new Checkbox ("Valutazione RI",  true);
  protected Panel    PannelloCB;     // Pannello per i check-box
  
  protected CheckboxGroup NotazCBG = new CheckboxGroup();
  protected Checkbox NotazPre   = new Checkbox ("PREFISSA", NotazCBG, false);
  protected Checkbox NotazInf   = new Checkbox ("INFISSA",   NotazCBG, true);
  protected Checkbox NotazPos   = new Checkbox ("POSTFISSA", NotazCBG, false);
  protected Panel    PannNotazCB;   // Pannello per il CBG "notazione"
              // NB: TUTTI I LISTENER per i BOTTONI:
  protected ArrBottList[] ArrBList = new ArrBottList [MAX_BOT];
  protected CanBottList   CanBList;
  protected UguBottList   UguBList;

  public DispCalc114 (CalAp114 DiCheCalc) {
    this (true, DiCheCalc, "");
  }
  public DispCalc114 (boolean ConFrame,
                      CalAp114 DiCheCalc) {
    this (ConFrame, DiCheCalc, "");
  }
  public DispCalc114 (boolean ConFrame,
                      CalAp114 DiCheCalc,
                      String TitoloFin) {
    super();  //invoca il costruttore di DispCalcPadre che
              // pero' quando chiama "createDisplay" chiamera'
              // quella di questa classe (LATE-BINDING)!
    if (ConFrame) super.createDisplay(TitoloFin);
    Registra (DiCheCalc);
    if (ConFrame) super.mostraFinestra();
  }
  
  protected void createDisplay(String N) { };  // NON FA NULLA!!!

  protected void Registra (CalAp114 DiCheCalc) {
    MyCalc = DiCheCalc;               // SALVA RIFERIMENTO A CALCOLATRICE

    setBackground (Color.blue);
    setForeground (Color.white);          // Aree di stampa
    setFont (new Font("TimesRoman", Font.PLAIN, 13));

    // Area stampa espress.da calcolare
    AreaValuta = new TextArea ("",1,35, TextArea.SCROLLBARS_NONE);
    AreaValuta.setBackground (Color.white);
    AreaValuta.setForeground (Color.black);
    AreaValuta.setFont (new Font("Courier", Font.BOLD, 20));
    AreaValuta.setEditable(false);
    add (AreaValuta);

    // Area stampa risultato
    AreaRisulta = new TextArea ("",1,6, TextArea.SCROLLBARS_NONE);
    AreaRisulta.setBackground (Color.yellow);
    AreaRisulta.setForeground (Color.black);
    AreaRisulta.setFont (new Font("Helvetica", Font.BOLD, 30));
    AreaRisulta.setEditable(false);
    add (AreaRisulta);
    
    PannNotazCB = new Panel();  // pannello per Gruppo CheckBox
    add (PannNotazCB);
    PannNotazCB.setLayout (new GridLayout(4,1, 10,10));
    PannNotazCB.setBackground (Color.cyan);
    PannNotazCB.setForeground (Color.red);
    PannNotazCB.setFont (new Font("TimesRoman", Font.PLAIN, 18));
    PannNotazCB.add (new Label("Notazione:"));
    PannNotazCB.add (NotazPre);
    PannNotazCB.add (NotazInf);
    PannNotazCB.add (NotazPos);
    
    PannelloBott = new Panel();      // pannello per i bottoni
    add (PannelloBott);
    PannelloBott.setLayout (new GridLayout(7,4, 3,3));
  
    for (int i=0; i<MAX_BOT; i++) {
      ArrBottoni[i] = new myButton (StrSuBot[i], StrPerStr[i], 'f');
      PannelloBott.add (ArrBottoni[i]);     // TUTTI I BOTTONI
    }
    
    PannelloBott.add (BottoneCAN);
    PannelloBott.add (BottoneUgu);
            
    PannelloCB = new Panel ();
    add (PannelloCB);
    PannelloCB.setLayout (new GridLayout(5,1,2,2));
    PannelloCB.setForeground (Color.orange);
    PannelloCB.setFont (new Font("TimesRoman", Font.PLAIN, 14));

    PannelloCB.add (CBTracAlb);
    PannelloCB.add (CancInput);
    PannelloCB.add (DispAction);
    PannelloCB.add (DispCostr);
    PannelloCB.add (DispValut);
    
    AreaMsg = new TextArea ("Area dei Messaggi\n", 8,65,
                            TextArea.SCROLLBARS_VERTICAL_ONLY);
    add (AreaMsg);
    AreaMsg.setBounds (10,100, 300,100);
    AreaMsg.setBackground (Color.black);
    AreaMsg.setForeground (Color.white);
    AreaMsg.setFont (new Font("Courier", Font.PLAIN, 12));
    
    
    AreaAmbient = new TextArea ("", 6,10,
                                TextArea.SCROLLBARS_NONE);
    add (AreaAmbient);
    AreaAmbient.setBackground (Color.orange);
    AreaAmbient.setForeground ((Color.blue).brighter());
    AreaAmbient.setFont (new Font("TimesRoman", Font.BOLD, 15));
    AreaAmbient.setEditable(false);

    // DEFINIZIONE DEI LISTENER DEI BOTTONI!
    for (int i=0; i<MAX_BOT; i++) {
      ArrBList[i] = new ArrBottList (MyCalc, ArrBottoni[i].Oper());
      ArrBottoni[i].addActionListener (ArrBList[i]);
    }
    CanBList = new CanBottList (MyCalc, BottoneCAN.Oper());
    BottoneCAN.addActionListener (CanBList);
    UguBList = new UguBottList (MyCalc, BottoneUgu.Oper());
    BottoneUgu.addActionListener (UguBList);
    
    StampaAmbiente();
  }

  protected void StampaAmbiente() {
    AreaAmbient.setText ("Ambiente:\n");
    java.util.Hashtable AmbG = MyCalc.RendiAmbiente();
    AreaAmbient.append  ("X = "+AmbG.get("X")+"\n");
    AreaAmbient.append  ("Y = "+AmbG.get("Y")+"\n");
    AreaAmbient.append  ("A = "+AmbG.get("A")+"\n");
    AreaAmbient.append  ("B = "+AmbG.get("B"));
  }// StampaAmbiente

  public void AggiornaDisplay () {
    AreaValuta.setForeground(Color.black);
    AreaValuta.setText (MyCalc.RendiStrDaValutare());
    AreaRisulta.setText (""+MyCalc.RendiRisultato());    // Stampa risultato
    StampaAmbiente();
  }

  public int RendiNotazScelta() {
    if (NotazInf.getState()) return 0;
    else
      if (NotazPre.getState()) return 1;
      else
        return 2;
  }

  public void CancellaInput () {
    AreaValuta.setForeground(Color.blue);
    AreaValuta.setText (MyCalc.RendiStrDaValutare());
  }

  public TextArea RendiAreaMsg() {
    return AreaMsg;
  }

  public void StampaMsg (String Messaggio) {
    AreaMsg.append (Messaggio);
  }
  
  public void CancellaAreaMsg () {
    AreaMsg.setText ("");
  }
}//DispCalc114

class DispCalcListener {                         // I LISTENER DEI BOTTONI
  CalAp114 IntCalc;
  String  AddString;
  public DispCalcListener (CalAp114 CC, String StrPerStrExp) {
    IntCalc=CC;
    AddString=StrPerStrExp;
  }
  public void actionPerformed(ActionEvent evt) {
    DispCalc114 DD = IntCalc.RendiDisp();
    if (DD.DispAction.getState())
      DD.StampaMsg ("ACTION - BOTTONE "+evt+"\n");
  }
}
class ArrBottList extends DispCalcListener implements ActionListener {
  public ArrBottList (CalAp114 CC, String S) { super (CC, S); }
  public void actionPerformed (ActionEvent evt) {
    super.actionPerformed(evt);  // classe da cui eredito
    IntCalc.AggiungiStr(AddString); }
}
class CanBottList extends DispCalcListener implements ActionListener {
  public CanBottList (CalAp114 CC, String S) { super (CC, S); }
  public void actionPerformed (ActionEvent evt) {
    super.actionPerformed(evt);  // classe da cui eredito
    IntCalc.AzzeraStr(true); }
}
class UguBottList extends DispCalcListener implements ActionListener {
  public UguBottList (CalAp114 CC, String S) { super (CC, S); }
  public void actionPerformed (ActionEvent evt) {
    super.actionPerformed(evt);  // classe da cui eredito
    IntCalc.VALUTAZIONE ();
  }
}

/** ===== LA CALCOLATRICE VERA E PROPRIA ===== */
public class CalAp114 extends java.applet.Applet {   // PER LA VERS. JDK 1.1.4
  protected DispCalc114 MyDisp;      // USA IL SUO DISPLAY

  protected String StrDaValutare=new String(""); // Exp in stringa
  protected Exp    ExpDaValutare;                // Exp ad albero
  protected double Risultato;                    // Exp valutata

  protected myDispPerAlbero DispAlb;
  protected VisitorRiscriviExp   PreVis,
                                 InVis,
                                 PostVis;      // Visitor per RISTAMPARE
  protected VisitorValutaExp     ValVis;   // Visitor per VALUTARE l'espr.in albero

  protected java.util.Hashtable AmbGlobale = new java.util.Hashtable();
                                       // AMBIENTE GLOBALE

  protected myFrame FinDisp;

  public CalAp114 () {
    this (false, "");
  }
  public CalAp114 (boolean ConFrame) {
    this (ConFrame, "CALCOLATRICE");
  }
  public CalAp114 (boolean ConFrame, String NomeFin) {
    StrDaValutare = "";
    Risultato=0;
    CreaDisplay (ConFrame, NomeFin);
  }
 
  protected void CreaDisplay (boolean ConFrame, String Nome) {
    MyDisp = new DispCalc114 (ConFrame, this, Nome);
  }                           // Crea display dandogli se stesso
 
  public void AggiungiStr (String AddStr) {
    StrDaValutare = StrDaValutare.concat (AddStr); // accodo operaz. passata
    MyDisp.AggiornaDisplay();
  }

  public void AzzeraStr (boolean Subito) {
    if (Subito) StrDaValutare = "";
    MyDisp.CancellaInput ();
    StrDaValutare = "";
  }

  public String RendiStrDaValutare() { return StrDaValutare; }
  
  public DispCalc114 RendiDisp ()    { return MyDisp; }

  public double RendiRisultato()     { return Risultato; }

  public java.util.Hashtable RendiAmbiente() {return AmbGlobale;}

  public void init()   { super.init(); }
  public void start()  { super.start(); }

  protected Exp CompilaStrInExp (String StrDaValutare) {
    Exp ExpAtt = null;  // inizializzo a exp.nulla
    TextArea MyTA;
    if (MyDisp.DispCostr.getState()) MyTA = MyDisp.RendiAreaMsg();
                                  else MyTA = new TextArea();  // Non la mostro
    MyTA.append ("--------CONVERSIONE DA STRINGA A R.I.--------\n");
    try{
      // Creo il tokenizer
      ExpTokenizer ETokz  = new ExpTokenizer (StrDaValutare, MyTA);
      // e lo do in pasto al Parser (che creo ora)
      StrParser    Parser = new StrParser (ETokz, MyTA);
      // Compilo la stringa a seconda della notazione scelta
      switch (MyDisp.RendiNotazScelta()) {
        case 0: ExpAtt = Parser.RendiExpDaNotazInfissa();  break;
        case 1: ExpAtt = Parser.RendiExpDaNotazPrefissa(); break;
        case 2: ExpAtt = Parser.RendiExpDaNotazPostfissa();
      }
      MyTA.append (" Exp: "+ ExpAtt +"\n");
    } catch (Exception e)
            { MyDisp.StampaMsg ("!!! ERRORE !!!   "+ e + "\n"); }
    return ExpAtt;
  }//CompilaStrInExp

  protected void VisualizzaFinestraConAlbero (Exp Esp) {
    FinDisp = new myFrame ("Display per Espressioni");
    FinDisp.resize (500,400);
    MyDisp.StampaMsg ("--------DISEGNANDO ALBERO----------\n");
    
    TextArea AreaStr = new TextArea("", 4,15);
    AreaStr.setFont (new Font("Courier", Font.BOLD, 12));
    DispAlb = new myDispPerAlbero(Esp, MyDisp.RendiAreaMsg());
    setLayout (new BorderLayout());
    FinDisp.add ("North",  AreaStr);     // Aggiungo componenti
    FinDisp.add ("Center", DispAlb);
    PreVis = new VisitorRiscriviExp(0, MyDisp.RendiAreaMsg());
    InVis  = new VisitorRiscriviExp(1, MyDisp.RendiAreaMsg());
    PostVis= new VisitorRiscriviExp(2, MyDisp.RendiAreaMsg());
    try {
      Esp.accept (PreVis);  // ACCETTA VISITOR per RISTAMPA
      Esp.accept (InVis);
      Esp.accept (PostVis);
    } catch (Exception e)
          { MyDisp.StampaMsg ("!!! ERRORE !!!   "+ e +"\n"); }
    AreaStr.appendText ("Notazione  Prefissa: "+ PreVis.Val()+"\n");
    AreaStr.appendText ("Notazione   Infissa: "+ InVis.Val()+"\n");
    AreaStr.appendText ("Notazione Postfissa: "+ PostVis.Val()+"\n");
    AreaStr.appendText ("Risultato = "+ ValVis.Val());
    FinDisp.show ();
    FinDisp.resize (DispAlb.RendiMaxX(), DispAlb.RendiMaxY());
  }//VisualizzaFinestraConAlbero

  protected double ValutaExp (Exp ExpInExp) {
    TextArea MyTA;
    double Ris = 0;
    if (MyDisp.DispCostr.getState()) MyTA = MyDisp.RendiAreaMsg();
                                else MyTA = new TextArea();  // Non la mostro
    MyTA.append ("--------VALUTAZIONE DELLA R.I.--------\n");
    try{
      ValVis = new VisitorValutaExp (AmbGlobale, MyTA); //nell'amb.dato
      ExpInExp.accept (ValVis);     // ACCETTA IL VISITOR DI VALUTAZIONE
      Ris = ValVis.Val();
    } catch (Exception e)
            { MyDisp.StampaMsg ("!!! ERRORE !!!   "+ e +"\n"); }

    if (MyDisp.CBTracAlb.getState())
      VisualizzaFinestraConAlbero (ExpInExp);
    return Ris;
  }//ValutaExp

  protected void VALUTAZIONE () {
    MyDisp.CancellaAreaMsg();  // Cancella area messaggi
    // INTERPRETA EXP: STR -> RI
    ExpDaValutare = CompilaStrInExp (StrDaValutare);
    // VALUTA ESPRESSIONE: R.I -> STR
    if (!(ExpDaValutare == null)) {
      Risultato = ValutaExp (ExpDaValutare);
      MyDisp.AggiornaDisplay();
      if (MyDisp.CancInput.getState())   // Cancella input
        AzzeraStr (false);
    }//If
    MyDisp.StampaMsg ("*** VAL Terminata ***\n");
  }//VALUTAZIONE

}//CalAp114

//*FINE FILE*