Thema dieser Dokumentation / Das FirstSpirit 5 Modul- / Komponenten-Modell / Beispiel: Implementierung einer Eingabekomponente / NotifyValueChange - Änderungen propagieren
NotifyValueChange - Änderungen propagieren
Sofern eine Eingabekomponente Werte speichern und bearbeiten kann, müssen Änderungen innerhalb der Komponente nach außen propagiert werden. Andernfalls werden die Änderungen nicht gespeichert. Bei einer Änderung der inneren Komponente muss das äußere FirstSpirit-Gadget-Framework aktiv über die Änderung informiert werden. Dies ist über die Methode notifyValueChange(final GadgetIdentifier identifier) möglich.
Innerhalb des Beispiels wird der Swing-Komponente zunächst ein DocumentListener hinzugefügt, der auf Änderungen des Textdokuments reagiert:
Listing: Beispiel Änderungen propagieren - Hinzufügen eines DocumentListener
public JComponent getComponent() {
if (_component == null) {
final int maxRows = getForm().getMaxRows().intValue();
_jTextArea = new JTextArea(maxRows, 20);
_jTextArea.getDocument().addDocumentListener(this);
...
}
}
Die zugehörigen Methoden rufen bei jeder Aktion, die zu einer Änderung des Wertes in der Eingabekomponente führt, die Methode notifyValueChange(final GadgetIdentifier identifier) auf:
Listing: Beispiel Änderungen propagieren – Aufruf von notifyValueChange()
/* DocumentListener ==============================================*/
public void insertUpdate(final DocumentEvent e) {
notifyValueChange(getGadgetId());
}
public void removeUpdate(final DocumentEvent e) {
notifyValueChange(getGadgetId());
}
public void changedUpdate(final DocumentEvent e) {
notifyValueChange(getGadgetId());
}
Welche Aktionen eine Änderung des Wertes hervorrufen, entscheidet dabei jede Komponente selbst. Im Beispiel der Texteingabekomponente führt beispielsweise das Tippen innerhalb des Texteingabefelds zu einer Änderung des Wertes.
Über den Aufruf von notifyValueChange(final GadgetIdentifier identifier) teilt die Komponente – hier das SwingGadget – dem äußeren Framework mit, dass sich ihr Inhalt geändert hat. Erkennt das Framework, das ein geänderter Wert gespeichert werden muss, erscheint das Symbol (Speichern) auf dem Tab des aktuell geöffneten Arbeitsbereichs im FirstSpirit SiteArchitect:
Nicht jede Änderung muss auch tatsächlich gespeichert werden. Bleibt der Wert innerhalb der Eingabekomponente unverändert (bezogen auf den zuletzt gespeicherten Wert), beispielsweise weil die ursprüngliche Änderung wieder zurückgesetzt wurde, so muss die Änderung nicht gespeichert werden. Das Symbol (Speichern) auf dem Tab des Arbeitsbereichs wird wieder ausgeblendet.
Um unnötiges Speichern und die damit verbundene Erzeugung einer neuen Revision eines FirstSpirit-Objekts zu vermeiden, wird bei jeder Änderung im SwingGadget zunächst überprüft, ob der geänderte Wert dem zuletzt gespeicherten Wert entspricht (Speichern nicht notwendig) oder eine Änderung vorliegt (Speichern notwendig).
Das FirstSpirit-Gadget-Framework führt dazu bei jeder Änderung (also nach jedem Aufruf von notifyValueChange(final GadgetIdentifier identifier)) einen „Equals“-Vergleich des zuletzt gespeicherten Wertes mit dem aktuell im SwingGadget enthaltenen Wert durch, indem der Wert des SwingGadgets über die Methode getValue() abgefragt wird. Die Methode getValue() liefert ein Objekt vom Typ T zurück, wobei T immer der Daten-Container-Typ des zugehörigen EditorValue<T> (hier String) ist.
Abhängig von der Art der Eingabekomponente und des zugehörigen Daten-Container-Typs kann der Aufruf von getValue() unvorteilhaft sein. Das gilt, wenn:
- eine Transformation des inneren Modells der Eingabekomponente in den Persistenztyp teuer ist oder wenn
- eine Transformation des inneren Modells in den Persistenztyp nicht möglich ist.
Für Eingabekomponenten, die komplexe Wertemengen speichern (Bsp. DOM-Editor) oder Eingabekomponenten, die erst zu bestimmten Zeitpunkten einen gültigen Wert enthalten (Bsp. manuelle Eingabe eines Datums), sollten eigene Methoden zur Änderungserkennung implementiert werden. Dazu stehen die funktionalen Aspekte ChangeManaging (siehe Den Aspekt ChangeManaging verwenden) und ValueLikening (siehe Den Aspekt ValueLikening verwenden) zur Verfügung: