|
Eigene Smart Elements

Definiton eigener Objektinspektor Strategien
Der Objektinspektor ist die Programmkomponente in jap, die dem Endanwender die Eingabe und Manipulation der Eigenschaftswerte ermöglicht. Für die unterschiedlichen Eigenschaftstypen stehen verschiedene Strategien bereit, die Daten anzuzeigen und zu verändern. Neben der alphanumerischen Eingabe gibt es Hilfskomponenten, die die Eingabe erleichtern. Für numerische Eigenschaften, die sich innerhalb eines festgelegten Wertebereiches bewegen, steht z.B. ein Schieberegler zur Verfügung, mit dem sich schnell ein Eigenschaftswert einstellen lassen kann. Für Farbwerte, die eigentlich auch nichts anderes als drei Ganzzahlwerte sind, steht ein Farbauswahldialog bereit. Eigenschaften vom Typ FILE_TYPE werden intern als String gespeichert, der Objektinspektor erlaubt jedoch die Definition des Strings über einen Dateidialog.
Der Objektinspektor "weiss" also ein wenig über die semantische Bedeutung der Eigenschaften, so dass er eine passende Eingabeschnittstelle bereitstellen kann. Es ist aber unmöglich direkt alle möglichen Verwendungsformen für Eigenschaften im voraus zu kennen. Daher ist die Anzahl der vordefinierten Eigenschaftstypen begrenzt. Es gibt jedoch den Eigenschaftstyp USER_TYPE, der es erlaubt neue Interpretationen und Eingabeschnittstellen für Eigenschaften nachträglich hinzuzufügen.
Der Eigenschaftstyp wird durch einen Integer-Wert in einem TAPPropertyInformation-Objekt für jede Eigenschaft gespeichert. Die Bedeutung des Integer-Wertes wird durch Konstanten in der Klasse TAPPropertyGroup festgelegt. Die Konstante
public final static int USER_TYPE = 42;
definiert den Datentyp USER_TYPE. Er kann für eine Eigenschaft innerhalb einer Eigenschaftsgruppe verwendet werden, wenn das die Eigenschaft beschreibende TAPPropertyInformation-Objekt erzeugt wird:
private final static TAPPropertyInformation propertyInfo_myProperty =
new TAPPropertyInformation( "myProperty",USER_TYPE,null,null,
AlternativesIterator.getEmptyIterator());
Hier wurde ein Objet der Klasse TAPPropertyInformation in der Variablen propertyInfo_myProperty abgelegt. Die beschriebene Eigenschaft erhält dabei den Namen "myProperty" und ist vom Typ USER_TYPE. Die Eigenschaftsbeschreibungen aller Eigenschaften einer Eigenschaftsgruppe werden nacheinander von einer Enumeration an den Objektinspektor übergeben. Näheres hierzu findet sich hier: TAPPropertyGroup.
Der Eigenschaftstyp USER_TYPE sagt dem Objektinspektor nun, dass zur Darstellung und Manipulation der Eigenschaft keine der vordefinierten Strategien eingesetzt werden soll. Statdessen soll auf eine neue Strategie zurückgegriffen werden, die per Plug-In dazugeladen wurde. Doch woher weiss der Objektinspektor nun, welches Plug-In er verwenden soll, um die Eigenschaft anzuzeigen? Um dies herauszufinden fragt der Objektinspektor bei der Eigenschaftgruppe nach, zu der die Eigenschaft gehört. Schliesslich hat diese Eigenschsaftgruppe diese Eigenschaft als USER_TYPE definiert, also wird sie wohl auch wissen, welche benutzerdefinierte Strategie eingesetzt werden soll. Die Anfrage des Objektinspektors bei der Eigenschaftsgruppe geschieht über die Methode getInspectorStrategyClassName(...). Diese Methode ist in TAPPropertyGroup.java definiert und muss in abgeleiteten Eigenschaftsgruppen überschrieben werden, wenn diese benutzerdefinierte Eigenschaften verwenden. Die Methode erhält den Namen der Eigenschaft, für die eine geeignete Strategie angefordert wird. Für unser Beispiel ist das die Eigenschaft myProperty. Die dazugehörige Strategie heisst OISMyPropertyStrategy:
public String getInspectorStrategyClassName(String propertyName) {
if (propertyName.equals("myProperty"))
return "OISMyPropertyStrategy";
return null;
}
Bitte beachten Sie: Strategien, die als Plug-In dazugeladen werden, müssen in einer Klasse definiert sein, deren Name mit "OIS" beginnt!
Wir wollen nun Schritt für Schritt unsere eigene Strategie für den Objektinspektor entwickeln.
Plug-Ins gehören in das Paket TAPPlugins:
package TAPplugins;
Unsere Strategien soll auf die Klassen in TAP zugreifen können. Außerdem wird die Strategie zur Repräsentation der Eigenschaftswerte natürlich irgendwie in Swing-Komponenten gescheheh, daher binden wir das Swing-Paket ein. Zur Reaktion auf die Benutzereingaben brauchen wir ferner Event-Klassen:
import TAP.*;
import javax.swing.*;
import java.awt.event.*;
public class OISMyPropertyStrategy extends TAP.PropertyInspectorStrategy {
Zur Anzeige unseres Eingabeinterfaces überläßt uns der Objektinspektor Platz für genau zwei Swing-Komponenten. Diese sollten dabei nicht zu groß sein, da sie sonst das Objektinspektor-Fenster sprengen. Als "kleine" Komponenten können Label, Button, Checkboxen und Popup-Menüs verstanden werden. Wenn wir einen komplexeren Eingabedialog gestalten möchten, dann können wir einen Button dazu benutzen, ein zusätzliches Fenster zu öffnen. Dies wollen wir in unserem Beispiel verfolgen und definieren daher ein JFrame für unsere Eingabestrategie. Da wir immer nur eine Eigenschaft zur Zeit behandeln können, deklarieren wir das Fenster als statisch. Somit kann immer wieder das gleiche Fenster benutzt werden:
private static JFrame eingabeFrame = new MeinDialogFrame();
Dabei ist die Klasse MeinDialogFrame eine Erweiterung von JFrame, in der wir unseren Benutzerdialog - wie auch immer der aussehen mag - untergebracht haben. In der neuen Frame-Klasse können z.B. Swing-Tabellen, -Listen oder -bäume verwendet werden.
Der Objektinspektor ruft die Methode init(...) auf, um die Strategie zu initialisieren. Diese Methode ist bereits in der Klasse PropertyInspectorStrategy implementiert und muss nicht überschrieben werden. So sieht die Defaultimplementation:
public void init (TAPElement element, TAPPropertyInformation
propertyInfo,JPanel panel) {
this.propertyInfo = propertyInfo;
this.element = element;
this.panel = panel;
createGadgets();
}
Folgende Werte werden dabei gesetzt:
- propertyInfo referenziert fortan das TAPPropertyInformation-Objekt, dass die Eigenschaft beschreibt, für die diese Strategie eingesetzt werden soll
- element referenziert das Element, zu dem die Eigenschaft gehört
- panel ist ein Swing-Container, dem wir zwei Eingabe-Komponenten hinzufügen können.
Am Ende der init(..)-Methode wird createGadgets() aufgerufen. Diese Methode erzeugt nun wirklich die Eingabeelemente und fügt sie dem Container panel hinzu. Bei der Implementierung einer neuen Strategie müssen wir diese Methode überschreiben:
protected void createGadgets() {
Als erstes defineren wir zwei beliebige Swing-Komponenten, die wir zur Datenmanipulation benutzen wollen. Da wir in unserem Beispiel eine komplexere Eingabe in einem Extrafenster unterbringen wollen, erzeugen wir einen Button, der das Fenster öffnet. Ausserdem erzeugen wir ein Label, der einfach nur einen Hinweis ausgibt:
JLabel lbStringInfo = new JLabel("Irgend eine Information ");
JButton btnOpenEditor = new JButton("Open Editor");
Der Button soll nach einem Klick das Eingabfenster öffnen. Dazu muss dem Button ein geeigneter ActionListener hinzugefügt werden, der das Fenster öffnet. Da wir immer wieder dasselbe Fenster-Objekt verwenden, um diese Inspektorstrategie anzuwenden, müssen dem eingabeFrame-Objekt den aktuellen Kontext übergeben. Der Kontext sind beliebige Parameter, z.B. der Name der behandelten Eigenschaft oder eine Referenz auf das Element, zu dem die Eigenschaft gehört.
btnOpenEditor.addActionListener( new ActionListener() {
public void actionPerformed(ActionEvent e) {
eingabeFrame.setContext(Kontext_K);
eingabeFrame.show();
}
}); // end addActionListner
Nachdem die Komponenten erzeugt sind, können wir sie dem Anzeige-Container des Objektinspektors hinzfügen:
panel.add(lbStringInfo);
panel.add(btnOpenEditor);
} // end createGadgets()
Der Objektinspektor enthält danach eine neue Zeile in der Eigenschaftsgruppe. Die Zeile enthält zunächst den Namen der Eigenschaft und anschliessend die beiden Komponenten, die wir hinzugefügt haben. Die wichtige Komponente ist hier der Button, da wir mit ihm das Eingabefenster öffnen. Das Eingabefenster kann nun vom Element (welches wir als Kontext übergeben haben) den aktuellen Eigenschaftswert auslesen und beliebig aufbereiten. Der Eigenschaftswert kann z.B. ein String sein, der sich auf besondere Weise interpretieren und in eine Listen-, Tabellen-, oder Baumdarstellung überführen läßt. Wenn der Benutzer im Eingabefenster seine Eingaben beendet hat, dann ist es die Aufgabe des Eingabfensters die komplexe Darstellung wieder in einem String umzuwandeln und den neuen Wert dem Objektinspektor mitzuteilen. Dies geschieht über die Methode ObjectInspector.setProperty(String propertyName,String propertyValue). Im Eingabefenster befindet sich also irgendwo folgender Codeabschnitt:
// in MeinDialogFrame.java an der Stelle, wo die Benutzereingabe
beendet und übernommen wird:
ObjectInspector.getObjectInspector().setProperty(myProperty,
stringRepresentation);
In myPropety befindet sich dabei der Name der Eigenschaft, die unsere Strategie behandet. stringRepresentation enthält dabei den neu erzeugten String. Der Objektinspektor sorgt dafür, dass die Eigenschaftsänderung umgesetzt wird und rückgängig gemacht werden kann.
Da Eigenschaften durchaus auf mehrere Wege verändert werden können, muss es einen Weg geben, die Inspektorstrategie über extern veranlasste Eigenschaftsänderungen zu informieren. Ein Beispiel ist die Änderung eines Eigenschaftswertes, wenn ein Undo vom Anwender ausgelöst wird. Ein anderes Beispiel ist eine Inspektorstrategie, um Farbwerte zu ändern. In diesem Spezialfall veranlasst die Inspektorstrategie einer Farbkomponente (z.B. rot) stets die Änderung gleich mehrerer Eigenschaftswerte (nämlich rot, grün und blau).
Der Objektinspektor teilt der Strategie die Änderung der Eigenschaft durch Aufruf der Methode setPropertyValue(String value) mit. Die Strategie kann nun ihre Komponenten dem neuen Wert entsprechend anpassen. In unserem Beispiel aktualisieren wir das Datum in unserem Eingabfenster:
public void setPropertyValue(String value) {
eingabeFrame.setData(value);
Eine Eigenschaftsstrategie hat das Recht, den gewünschten neuen Eigenschaftswert (value) zu ändern - z.B. wenn die Strategie bestimmte Wertebereiche für eine Eigenschaft definiert. Die Strategie muss nun wiederum dem Objektinspektor mitteilen, welcher Eigenschaftswert tatsächlich verwendet wird. In unserem einfachen Beispiel lassen wir jeden neuen Eigenschaftswert zu und reichen daher einfach den Wert weiter:
ObjectInspector.getObjectInspector().changePropertyValue(
element, propertyInfo.getPropName(), value);
} // end setPropertyValue
} // end class OISMyPropertyStrategy
Und damit haben wir eine neue Strategie zur Interpretation und Manipulation von Eigenschaften im Objektinspektor definiert. Nachdem Sie kompiliete Klasse ins Verzeichnis TAPplugins kopiert haben, steht die Strategie zur Verwendung bereit.
Wie Sie für eine Eigenschaft mit einem benutzerdefinierten Datentyp festlegen, dass genau diese Strategie verwendet wird, lesen Sie in der Klassenbeschreibung TAPPropertyGroup nach. Dabei kommt die Methode getInspectorStrategyClassName(..) zum Einsatz.
|