//Titel:            Observer Pattern mit Testbeispiel für MDI-Fenster
//Version:          2.0, 06.11.2010
//Copyright:        HS-Harz, FB AI
//Autor:            Dipl.-Inf.(TU) Dipl.-Ing.(FH) Michael Wilhelm
//Beschreibung:     Beispiel eines Observer mit Enter-Taste fuer den Datentransfer



// Beispiel für das Observer Design Pattern
// Mit der Eingabetaste wird der Inhalt aktualisiert

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;


// InternalFrame
import javax.swing.event.*;

// 1. Import 
import java.util.Observable;
import java.util.Observer;


public class Observer1 extends JFrame {
  int anz=0;

    // Menü Variablen
  private JMenuBar menuBar1;
  private JMenu MainFile;
  private JMenuItem MnNew;
  private JMenuItem MnClose;


   // 4. Schritt  die Modell Variable im JFrame deklarieren
  private Modell modell;   // Modell 

   // Konstruktor
  public Observer1() {
    this.setSize(new Dimension(200, 100));
    setLocation(200,70);
    setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
    setGUI();
  }

  public void setGUI() {
    this.getContentPane().setLayout( new BorderLayout() );
    setMenus();
    // 5. Schritt  die Modell Variable erzeugen
    modell = new Modell();
    modell.setName("Paul");
  }



    // setzt die Menüs
  private void setMenus() {
    menuBar1 = new JMenuBar();

      // DATEI
    MainFile = new JMenu("Datei");
    MnNew = new JMenuItem("Neu");
    MnClose = new JMenuItem("Schließen");
    MnNew.addActionListener(new ActionListener()  {
      public void actionPerformed(ActionEvent e) {
        MnNew_click();
      }
    });
    MnNew.setAccelerator( KeyStroke.getKeyStroke(KeyEvent.VK_N, ActionEvent.CTRL_MASK));
    MainFile.add(MnNew);

    MainFile.addSeparator();

    // --------------------------
    MnClose.addActionListener(new ActionListener()  {
      public void actionPerformed(ActionEvent e) {
        MnClose_click();
      }
    });
    MainFile.add(MnClose);
    menuBar1.add(MainFile);
    // ----------------
    this.setJMenuBar(menuBar1);

    for (int i = 0; i < menuBar1.getComponentCount(); i++) {
      JMenu main = (JMenu) menuBar1.getComponent(i);
      main.setFont(new Font("Arial", Font.BOLD, 18));
      for (int j = 0; j < main.getItemCount(); j++) {
        Component c = main.getItem(j);
        if (c instanceof JMenuItem) {
          JMenuItem mn = (JMenuItem) c;
          mn.setFont(new Font("Arial", Font.BOLD, 18));
        }
      }
    }

  } // setMenus


  // Menü Aktions Methoden

  void MnNew_click() {
    // 7. Schritt  Viewer in der Methode "New_click" erzeugen    
   JObserverFrame frame = 
  new JObserverFrame(Integer.toString(anz), anz%3, modell);
    frame.setLocation(  (anz%2)*390+10, 180+110*(anz/2)  );
    frame.setSize(300,80);
    anz++;
  }

  void MnClose_click() {
    System.exit(0);
  }



  static public void main(String[] args) {
    Observer1 frame = new Observer1();
    frame.setVisible(true);
  }

  

}  // Observer1


//   |
//  +--java.util.Observable

// 2. Schritt ableiten von Observable, damit Modell und Observable
class Modell  extends java.util.Observable {
  String name= "Zappa";

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

    // Diese Methode wird von einem Viewern aufgerufen
    //
    // 3. Schritt: Im Controller eine Methode für die Viewer zum Updaten schreiben
  public void DataChangedFromViewer(int nr, String s) {
    System.out.println("s im Modell: "+s);
    this.setName(s);  // geänderte Daten speichern
    super.setChanged();
      // Sende Nachricht an ALLE Viewer
    super.notifyObservers( nr );
  }

} // Modell


// 6. Schritt  im JFrame  Implements einbauen
class JObserverFrame extends JFrame implements Observer {
  private String sFileName;

  private JLabel label1 = new JLabel("Student");
  private JTextField edit = new JTextField("XXXXX");

  // 7. Schritt  Modell deklarieren
  private Modell modell;
  private String caption;
  int nr;


  // 8. Schritt  Konstruktor
  public JObserverFrame( String caption, int nr,
       Observable DatenModell) {
    this.caption = caption;   
    setTitle(caption);
    this.nr=nr;

    // 9. Schritt  globale Variable setzen
    modell = (Modell) DatenModell;  //
    // 10. Schritt  im JFrame  registrierung
    modell.addObserver(this);  
    setGUI();
    setVisible(true);  // neu ab JDK 5.0
  }

  public void setGUI() {
    label1.setFont( new Font("Arial", Font.BOLD,28));

    // 11. Schritt  aus dem Modell die Daten holen
    edit.setText(  modell.getName()     );
    edit.setFont( new Font("Arial", Font.BOLD,28));

    this.setResizable(true);
    this.getContentPane().setLayout( new GridLayout(1,2) );


    this.getContentPane().add(label1);
    this.getContentPane().add(edit);

    edit.addActionListener(new java.awt.event.ActionListener() {
        //  Aufgerufen wenn Return-Taste
      public void actionPerformed(ActionEvent e) {
        edit_Change(e);
      }
    });


  }  // setGUI
  

  // 12. Schritt  Schnittstellen implentieren: Methode Update
  // aufgerufen vom Controller
  public void update(Observable o, Object arg) {
    System.out.println("Update");
    Integer I = (Integer) arg;
    if ( ( I.intValue()!=nr) || ( I.intValue()==-1) ){
      System.out.println("ich bin nicht Quelle: "+caption);
      // 13. Schritt  neue Daten holen
      edit.setText( modell.getName() );
      edit.updateUI();
    }
  }

  // 14. Schritt  Methode edit_change (Enter) implementieren, Aufruf des Modell/notify
  void edit_Change(ActionEvent e) {
    System.out.println("geändert");
    modell.DataChangedFromViewer( nr,edit.getText());
  }



}  // JObserverFrame


