/**
   Klasse Plotter<BR> <BR>
   Sprache:  JAVA<BR>
   Autor:    Fabian Wleklinski, Martin Klossek, Martin Meedt<BR>
   Datum:    18.05.1999<BR>
   Funktion: Hauptklasse unseres Plotters

   <BR>&nbsp;<BR>

   Klasse ist Steuerzentrale des einfachen Plottingprogramms
*/

import java.applet.*;
import java.awt.*;
import java.awt.event.*;

/** Klasse Plotter, erzeugt UI und steuert PlotFrames */
public class Plotter extends Applet {

 // Variablendeklaration
  PlotFrame LastPlotFrame, FirstPlotFrame; // Erstes Plotfenster in der Liste
  TextField tAusdruck; // Die TextFields mit unseren Daten
  TextField xminField, xmaxField, yminField, ymaxField;
  List funcList; // Die Liste aller Funktionen
  Plotter dummyThis; // unangenehme Konstrukte...

 /** Der Action-Listener lauscht dem Plot-Button */
 class ButtonListener implements ActionListener {

  public void actionPerformed( ActionEvent e ) {

     if (e.getActionCommand().equals("Plot!")) { // Erzeugt neuen Plot
     
       // Prüfen, ob eingegebener Ausdruck schon in Liste vorhanden ist
        int i = 0;
        for ( i = 0; i < funcList.getItemCount (); i++) {
           if (funcList.getItem(i).equals(tAusdruck.getText())) { 
              return; 
           }
        }

       // Range-Grenzen auslesen
        double xmin, xmax, ymin, ymax; 
        try {
           xmin = new Double(xminField.getText()).doubleValue(); // Werte aus Getches rausholen
        } catch (NumberFormatException ex) { xminField.setText ("0"); return; }
        try {
          xmax = new Double(xmaxField.getText()).doubleValue();
        } catch (NumberFormatException ex) { xmaxField.setText ("0"); return; }
        try {
          ymin = new Double(yminField.getText()).doubleValue();
        } catch (NumberFormatException ex) { yminField.setText ("0"); return; }
        try {
          ymax = new Double(ymaxField.getText()).doubleValue();
        } catch (NumberFormatException ex) { ymaxField.setText ("0"); return; }

       // neue Instanz erzeugen und plotten
        PlotFrame newPlotFrame = new PlotFrame ( dummyThis, tAusdruck.getText(), xmin, xmax, ymin, ymax );

       // Wenn aus irgendwelchen Gründen keine Instanz erstellt wurde, dann auch nicht in Liste einfügen
        if (newPlotFrame == null) { return; }
        else { if (!newPlotFrame.AusdruckString.equals(tAusdruck.getText())) {
           MessageBox ErrorBox = new MessageBox( "Falsche Eingabe", newPlotFrame.AusdruckString );
           return; 
        } }

       // Neue Funktion in Liste einfügen
        if (FirstPlotFrame == null) { 
           FirstPlotFrame = newPlotFrame; 
           LastPlotFrame = FirstPlotFrame;
           newPlotFrame.next = null;
        } else {
           LastPlotFrame.next = newPlotFrame;
           LastPlotFrame = newPlotFrame;
           newPlotFrame.next = null;
        }

       // Ausdrucksstring in Komponente einfügen
        funcList.addItem ( tAusdruck.getText() ); // In Liste einfügen
     } else if (e.getActionCommand().equals("Info")) { // INFO-BUTTON

        InfoBox pInfoBox = new InfoBox();

     } else { // Alle anderen Events sollten dem Doppelklick in die Listbox entstammen

       // PlotFrame aus verketteter Liste rausholen
        PlotFrame actPlotFrame = FirstPlotFrame; // Frame-Liste durchgehen und Ausdruck suchen
        PlotFrame preActPlotFrame = null; // Vorgängerframe

        do {
           if (e.getActionCommand().equals(actPlotFrame.AusdruckString)) { 
  
              tAusdruck.setText(actPlotFrame.AusdruckString); // Werte in getches schreiben
              xminField.setText(Double.toString(actPlotFrame.xmin));
              xmaxField.setText(Double.toString(actPlotFrame.xmax));
              yminField.setText(Double.toString(actPlotFrame.ymin));
              ymaxField.setText(Double.toString(actPlotFrame.ymax));
 
              actPlotFrame.setVisible(false); // Frame unsichtbar machen...
              funcList.remove (actPlotFrame.AusdruckString);  // Aus Liste rausholen
              if (actPlotFrame==FirstPlotFrame) {
                 FirstPlotFrame = actPlotFrame.next;
              } else {
                 preActPlotFrame.next = actPlotFrame.next; // ... und aus Liste killen
              }
              break; // und raus hier... wir sind ja fertig!          
           }
           preActPlotFrame = actPlotFrame;
           actPlotFrame = actPlotFrame.next;

        } while (actPlotFrame!=null);

     }
  }
 }

 /** Löscht übergebenen PlotFrame aus Fensterliste (wird von Klasse PlotFrame aufgerufen)
   * @param PlotFrame Zeiger auf Kinder-PlotFrame 
   */ 
 public void KickMe (PlotFrame ChildPlotFrame) { 
   // Funktion aus ListBox entfernen
    funcList.remove (ChildPlotFrame.AusdruckString); 
 
   // PlotFrame aus verketteter Liste rausholen
    PlotFrame actPlotFrame = FirstPlotFrame; // Frame-Liste durchgehen und Ausdruck suchen 
    PlotFrame preActPlotFrame = null; // Vorgängerframe 
    do { 
       if (actPlotFrame==ChildPlotFrame) {  
          if (actPlotFrame==FirstPlotFrame) { 
             FirstPlotFrame = actPlotFrame.next; 
          } else { 
             preActPlotFrame.next = actPlotFrame.next; // ... und aus Liste killen 
          } 
          break; // und raus hier... wir sind ja fertig!           
       } 
       preActPlotFrame = actPlotFrame; 
       actPlotFrame = actPlotFrame.next;
    } while (actPlotFrame!=null); 
 } 
 
 /** Fügt ein neues Label mit den angegebenen Parametern ins Interface ein
   * @param String Die Caption des Labels
   * @param int Der Modus (Label.LEFT, Label.CENTER, Label.RIGHT) des Labels
   * @param GridBagLayout Der zu verwendende LayoutManager
   * @param GridBagConstraints Die zu verwendenden Constraints
   */
 void addLabel ( String caption, int mode, GridBagLayout layout, GridBagConstraints constr ) {
    Label dummyLabel = new Label(caption, mode);
    layout.setConstraints (dummyLabel, constr);
    add (dummyLabel);
 }

 /** Fügt ein bestehendes Label ins Interface ein
   * @param Label Das einzufügende Label
   * @param GridBagLayout Der zu verwendende LayoutManager
   * @param GridBagConstraints Die zu verwendenden Constraints
   */
 void addLabel ( Label dummyLabel, GridBagLayout layout, GridBagConstraints constr ) {
    layout.setConstraints (dummyLabel, constr);
    add (dummyLabel);
 }

 /** Fügt ein bestehendes Textfeld ins Interface ein
   * @param TextField Das einzufügende Textfeld
   * @param GridBagLayout Der zu verwendende LayoutManager
   * @param GridBagConstraints Die zu verwendenden Constraints
   */
 void addTextField ( TextField dummyTextField, GridBagLayout layout, GridBagConstraints constr ) {
    layout.setConstraints (dummyTextField, constr);
    add (dummyTextField);
 }

 /** Die Initialisierungsmethode -> plaziert UI-Elemente */
 public void init() {

   // Fensterkette initialisieren (KEINE FENSTER)
    FirstPlotFrame = null; 
    LastPlotFrame = null;
    dummyThis = this;

   // ActionListener instanzieren
    ButtonListener globalListener = new ButtonListener();
 
   // Steuerelemente mit GridBagLayout plazieren
    GridBagLayout gridBag = new GridBagLayout();
    GridBagConstraints constr = new GridBagConstraints();
    constr.fill = GridBagConstraints.BOTH;
    setLayout (gridBag);
    // setBackground (Color.white);

   // Überschrift, Untertitel und Leerzeile plazieren
    constr.gridwidth=GridBagConstraints.REMAINDER;  // constr.weightx = 4.0;
    addLabel (" ", Label.CENTER, gridBag, constr);
    Label titleLabel = new Label ("Der JavaPlotter", Label.CENTER);
    titleLabel.setFont (new Font("SansSerif", Font.BOLD, 16));
    addLabel (titleLabel, gridBag, constr);
    setFont (new Font("SansSerif", Font.PLAIN, 12)); 
    addLabel ("von Fabian Wleklinski, Martin Klossek und Martin Meedt", Label.CENTER, gridBag, constr);
    addLabel (" ", Label.CENTER, gridBag, constr);

   // Ausdrucks-Textfeld plazieren
    constr.gridwidth=1; 
    addLabel ("Ausdruck:", Label.CENTER, gridBag, constr);
    constr.gridwidth=GridBagConstraints.REMAINDER;
    tAusdruck = new TextField ("",40); 
    addTextField (tAusdruck, gridBag, constr);   
    addLabel (" ", Label.CENTER, gridBag, constr);

   // Range-Textfelder plazieren
    constr.gridwidth=1;  constr.weightx=1.0;
    addLabel ("xMin:", Label.CENTER, gridBag, constr);
    xminField = new TextField ("-5", 5);
    addTextField (xminField, gridBag, constr);
    addLabel ("xMax:", Label.CENTER, gridBag, constr);
    constr.gridwidth=GridBagConstraints.REMAINDER;
    xmaxField = new TextField ("5", 5);
    addTextField (xmaxField, gridBag, constr);

    constr.gridwidth=1;
    addLabel ("yMin:", Label.CENTER, gridBag, constr);
    yminField = new TextField ("-5", 5); 
    addTextField (yminField, gridBag, constr);
    addLabel ("yMax:", Label.CENTER, gridBag, constr);
    constr.gridwidth=GridBagConstraints.REMAINDER;
    ymaxField = new TextField ("5", 5);
    addTextField (ymaxField, gridBag, constr);
    addLabel (" ", Label.CENTER, gridBag, constr);

   // Plot-Button plazieren:
    constr.gridwidth=1;
    addLabel (" ", Label.CENTER, gridBag, constr);
    Button plotButton = new Button ("Plot!"); 
    plotButton.addActionListener (globalListener); 
    constr.gridwidth=1;
    gridBag.setConstraints (plotButton, constr);
    add (plotButton);    
    addLabel (" ", Label.CENTER, gridBag, constr);
    constr.gridwidth=GridBagConstraints.REMAINDER;;
    Button infoButton = new Button ("Info"); 
    infoButton.addActionListener (globalListener);
    gridBag.setConstraints (infoButton, constr);
    add (infoButton); 
    addLabel (" ", Label.CENTER, gridBag, constr);

   // Liste plazieren
    constr.gridwidth=1; 
    addLabel ("Funktionen:", Label.CENTER, gridBag, constr);
    constr.gridwidth=GridBagConstraints.REMAINDER;
    funcList = new List (6);
    funcList.addActionListener (globalListener);
    gridBag.setConstraints(funcList,constr);
    add (funcList);
 }  

 /** Die Main-Methode des JavaPlotters 
   * @param String[] Die (nicht ausgewerteten) Kommandozeilenparameter
   */
 public static void main (String Args[]) {
   // Neue Instanz von uns selbst erzeugen
    Plotter thisPlotter = new Plotter(); 
 
   // Action-Listener für Exit-Event definieren
    WindowListener ExitListener = new WindowAdapter()
    {
      // Event-Methode die beim Schließen aufgerufen wird
       public void windowClosing (WindowEvent ThisEvent) {
          System.exit (0); // Errorlevel 0 zurück
       }
    };

   // Initialisieren des Applets
    thisPlotter.init();
    thisPlotter.start();

   // Frame anlegen und die applet-Klasse einpflanzen    
    Frame AppletFrame = new Frame("Der JavaPlotter");
    AppletFrame.addWindowListener(ExitListener); // Event-Handling aktiv.
    AppletFrame.add(thisPlotter); // pflanze applet ein...
    AppletFrame.pack();
    AppletFrame.setSize(AppletFrame.getPreferredSize());
    AppletFrame.show(); // und anzeigen (visible=true)...
 }

}
