View.java

(vorläufig)

package algorithmen.umleditor;

import java.awt.*;
import javax.swing.*;
import java.io.*;
import java.util.*;

/**
 * Basisklasse aller Views von UML-Objekten.
 * Enthält das Modell und die Position
 *     (= linke obere Ecke des umgebenden Rechtecks)
 * Die Größe ergibt sich aus dem Modell.
 */
abstract public class View implements Serializable {
  protected Point pos;
  protected UmlElement model;
  protected Dimension size;    // aus den Strings berechnet und gecached
  
  /** Abstand zwischen Strings oder Strings und Linien in Pixel */
  protected int sepSize = 5;
  
  /** div. Font, werden lazy initialisiert,
   * da dazu Graphics-Objekt nötig */
  protected Font standardFont;
  protected Font cursiveFont;
  protected Font boldFont;
  protected Font curBoldFont;
  
  /**
   * Erzeugt einen View für das model an der Position p.
   */
  public View(UmlElement model, Point p) {
    this.model = model;
    pos = p;
    size = new Dimension();
    
    // Liste der Observer bereitmachen
    observers = new Vector();
  }
  
  /**
   * Zeichnet das Objekt.
   */
  abstract public void draw(Graphics g);
  
  /**
   * Erzeugt einen Editor für das Objekt.
   * Er ist modal bzgl. des angegebenen Frames bzw. Dialogs.
   */
  abstract public Editor createEditor(UmlElement m, Frame p);
  abstract public Editor createEditor(UmlElement m, Dialog p);
  
  /**
   * Erzeugt ein Standard-UmlElement.
   * Dies ist Teil des FactoryMethod Patterns und wird verwendet, damit
   *   der ListEditor neue Elemente verschiedenen Typs erzeugen kann.
   */
  abstract public UmlElement createStandardObject();
  
  /**
   * Holt die aktuelle Position eines Objekts.
   */
  public Point getPosition() {
    return pos;
  }
  
  /**
   * Setzt die aktuelle Position eines Objekts.
   */
  public void setPosition(Point p) {
    pos = p;
    notifyObservers();
  }
  
  /**
   * Holt das aktuelle Modell des Views.
   */
  public UmlElement getModel() {
    return model;
  }
  
  /**
   * Setzt das aktuelle Modell des Views.
   */
  public void setModel(UmlElement m) {
    model = m;
    notifyObservers();
  }
  
  /**
   * Holt die Größe des Objekts.
   * Gesetzt wird die Größe vom View selbst durch Bestimmung der Teile,
   *    nicht von außen vorgegeben.
   */
  public Dimension getSize() {
    return size;
  }
  
  
  /**
   * Prüft, ob der Punkt p im umschließenden Rechteck des Objekts liegt.
   */
  public boolean contains(Point p) {
    Rectangle r = new Rectangle(pos, size);
    return r.contains(p);
  }
  
  /**
   * Verschiebt das Objekt um (dx, dy).
   */
  public void translate(int dx, int dy) {
    pos.translate(dx, dy);
    notifyObservers();
  }
  
  // Hilfsmethoden
  
  /**
   * Gibt die Höhe von Strings bezogen auf den verwendeten Font zurück.
   */
  protected int getStringHeight(Graphics g) {
    return g.getFontMetrics().getHeight();
  }
  
  /**
   * Gibt die Breite eines Strings bezogen auf den verwendeten Font zurück.
   */
  protected int getStringWidth(String s, Graphics g) {
    return g.getFontMetrics().stringWidth(s);
  }
  
  /**
   * Fonts "lazy" initialisieren
   */
  protected void initFonts(Graphics g) {
    if (standardFont == null) {
      standardFont = g.getFont();
      cursiveFont = standardFont.deriveFont(Font.ITALIC);
      boldFont = standardFont.deriveFont(Font.BOLD);
      curBoldFont = standardFont.deriveFont(Font.ITALIC | Font.BOLD);
    }
  }
  
  
  // Infrastruktur für das Observer-Pattern
  
  /** Liste der Observer */
  protected Vector observers;
  
  /**
   * Registriert einen Observer.
   */
  public synchronized void addObserver(Observer o) {
    observers.addElement(o);
  }
  
  /**
   * Löscht einen Observer aus der Liste.
   */
  public synchronized void deleteObserver(Observer o) {
    observers.removeElement(o);
  }
  
  /**
   * Informiert alle Observer.
   */
  public void notifyObservers() {
    Vector l;
    
    // Klone die Liste der Listener, damit sich Benachrichtigung und evtl.
    // Änderungen an den Listenern (add/delete) nicht stören.
    synchronized (this) {
      l = (Vector) observers.clone();
    }
    
    for (int i = 0; i < l.size(); i++) {
      ((Observer) l.elementAt(i)).update();
    }
  }
}