/**
 *Sprache: JAVA<p> Autoren: Fabian Wleklinski (fabian@wleklinski.de), Martin Klossek (martin@klossek3000.de),
 * Martin Meedt (mmeedt@aol.com)<p> Datum:   18.05.1999 - 19.2.2001<p>
 */

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, dStartYField, dEndYField;
        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, dStartY, dEndY;
                                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 {
                                        dStartY = new Double(dStartYField.getText()).doubleValue();
                                } catch (NumberFormatException ex) { dStartYField.setText ("0"); return; }
                                try {
                                        dEndY = new Double(dEndYField.getText()).doubleValue();
                                } catch (NumberFormatException ex) { dEndYField.setText ("0"); return; }

                                // neue Instanz erzeugen und plotten
                                PlotFrame newPlotFrame = new PlotFrame ( dummyThis, tAusdruck.getText(), xmin, xmax, dStartY, dEndY );

                                // 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

                                /* Fabian Wleklinski: method addItem() is deprecated */

                                // funcList.addItem ( tAusdruck.getText() ); // In Liste einfügen
                                funcList.add ( 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.m_dStartX));
                                                xmaxField.setText(Double.toString(actPlotFrame.m_dEndX));
                                                dStartYField.setText(Double.toString(actPlotFrame.m_dStartY));
                                                dEndYField.setText(Double.toString(actPlotFrame.m_dEndY));

                                                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( AutorInfo.APPLETCOLOUR );

                // Überschrift, Untertitel und Leerzeile plazieren
                constr.gridwidth = GridBagConstraints.REMAINDER;  // constr.weightx = 4.0;
                addLabel (" ", Label.CENTER, gridBag, constr);
                Label titleLabel = new Label ("Funktionsplotter", Label.CENTER);
                titleLabel.setFont (
                    new Font("SansSerif", Font.BOLD, 16));
                addLabel (titleLabel, gridBag, constr);
                setFont (
                    new Font("SansSerif", Font.PLAIN, 12));
                addLabel ("von " + AutorInfo.AUTHORNAMES, 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);
                dStartYField = new TextField ("-5", 5);
                addTextField (dStartYField, gridBag, constr);
                addLabel ("yMax:", Label.CENTER, gridBag, constr);
                constr.gridwidth = GridBagConstraints.REMAINDER;
                dEndYField = new TextField ("5", 5);
                addTextField (dEndYField, 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("Funktionsplotter");
                AppletFrame.addWindowListener(ExitListener); // Event-Handling aktiv.
                AppletFrame.add(thisPlotter); // pflanze applet ein...
                AppletFrame.pack();
                AppletFrame.setSize(AppletFrame.getPreferredSize());
                AppletFrame.show(); // und anzeigen (visible=true)...
        }

}
