Dazu wollen wir exemplarisch die Realisierung der GUI-Elemente betrachten. Auf der Modell-Seite sieht dies wie folgt aus: Jedes GUI-Element muss dem Interface IGuiElement genügen. Dabei wird die Implementierung dieses Interfaces durch die abstrakte Klasse GuiElement erleichtert. Diese Basisklasse erfüllt bereits einen Teil des Interfaces mit Standardimplementierungen, die im Normalfall völlig ausreichen.
Das Interface IGuiElement (siehe Abb. 4.4) vereinigt dabei mehrere andere Interfaces und erweitert deren Anforderungen um einige speziell für GUI-Elemente notwendige Methoden. Zu den Interfaces, die Teil des Interfaces IGuiElement sind, gehört zum Beispiel Sizeable, da es sich um ein Modell-Element handelt, dass eine Position und Größe besitzt. Desweiteren umfasst es das Interface HasProperties, da ein GUI-Element Eigenschaften (Properties) besitzt, die über die Methoden des Interfaces ausgelesen und gesetzt werden können.
Jedes GUI-Element muss also eine Liste von Properties bereithalten, aus denen sich das jeweilige GUI-Element zusammensetzt. Wird zur Implementierung des Interfaces die Basisklasse GuiElement spezialisiert, so kann die für diesen Zweck dort bereitgestellte Methode contributeProperties durch Überschreiben dazu benutzt werden, um in einer Initialisierungsphase die Liste der Properties zu erstellen. Dabei kann schrittweise vorgegangen werden, indem weitere abstrakte Klassen zwischen der Basisklasse GuiElement und der eigentlichen Klasse des GUI-Elements geschaltet werden (vgl. Abb. 4.5). Diese repräsentieren dann Kategorien von GUI-Elementen, die sich durch gemeinsame Eigenschaften auszeichnen. Außerdem werden bereits in der Basisklasse selbst einige Eigenschaften definiert, die allen GUI-Elementen gemein sind, wie zum Beispiel die Position und Größe des GUI-Elements.
Eigenschaften können wie GUI-Elemente beliebig geartet sein. Wieder kapselt ein Interface die von einer Property erwarteten Funktionalitäten (siehe Abb. 4.6). Ein Property besteht aus einem Identifikator, einer Kategorie, einem Namen und einem Wert. Zusätzlich besitzt es noch eine Referenz auf das GUI-Element, welches das Property besitzt. Außerdem lässt sich noch ein sogennanter PropertyValidator angeben, der Wertzweisungen des Property überwacht und gegebenenfalls ablehnen kann.
Wie bei den GUI-Elementen gibt es auch für die Properties eine Basisklasse Property, die das Interface IProperty implementiert und die von den konkreten Properties spezialisiert wird (siehe Abb. 4.7). Darunter befinden sich zum Beispiel ColorProperty, DoubleProperty, BooleanProperty oder FileProperty, wobei FileProperty wiederum als Basisklasse für ImageFileProperty und SoundFileProperty dient. Für jedes Property und für verschiedene Zwecke werden verschiedenste PropertyValidators angeboten. Diese zeichnen sich durch die Implementierung des Interfaces IPropertyValidator aus und lassen sich wie auch die Properties selbst leicht erweitern, da nirgendwo sonst konkrete Annahmen über Properties oder ihre Validatoren gemacht werden, die über die im Interface zugesicherten Operationen hinausgehen.
Dasselbe gilt selbstverständlich für die GUI-Elemente selbst. Soll ein neues GUI-Element hinzugefügt werden, so reicht lediglich die Implementierung des Interfaces IGuiElement aus, was natürlich nochmal wesentlich erleichtert wird, wenn man die entsprechende Basisklasse spezialisiert. Anschließend sind nur noch die gewünschten Properties zu definieren, welche sich gegebenenfalls mit entsprechenden Validatoren versehen lassen. Abschließend ist lediglich noch das neue GUI-Element in der GuiElementRegistry zu registrieren, damit es dem System auch bekannt ist und entsprechend beim Starten von GuiBuilder geladen wird.
Für GUI-Elemente, die in der GuiElementRegistry registriert wurden, erstellt GuiBuilder automatisch entsprechende Einträge in der Werkzeugleiste, so dass sich die neuen GUI-Elemente auch erzeugen lassen. Alle Funktionen von GuiBuilder werden mit dem neuen GUI-Element reibungslos zusammenarbeiten, da diese ausschließlich über das Interface IGuiElement mit diesem kommunizieren. Als besonderes Beispiel sei an dieser Stelle der Eigenschaften-Dialog erwähnt, welcher sich vollkommen dynamisch entsprechend den von dem GUI-Element propagierten Eigenschaften aufbaut. Für jedes Property werden geeignete Dialogkomponenten ausgewählt, die im Dialog nach ihren Kategorien in entsprechend benannte Registerkarten aufgeteilt werden. Ein Property findet sich dann im Dialog mit seinem Namen und einer dem Typ entsprechenden Eingabemöglichkeit wieder.
Als Steuerungskomponente (Controller / Parts) für GUI-Elemente dient die Klasse GuiElementEditPart. Die gemeinsame Basisklasse aller Steuerungskomponenten ist EditPartBase. Allerdings gibt es keine separaten Steuerungskomponenten für jedes einzelne GUI-Element, sondern GuiElementEditPart ist in der Lage, beliebige GUI-Elemente zu verwalten. Schließlich wurde bei der Erweiterung von GUI-Elementen auch nicht verlangt, dass neue Steuerungselemente erzeugt werden müssten, was schlicht und einfach daran liegt, dass dies nicht nötig ist. GuiElementEditPart und andere Komponenten von GuiBuilder greifen ausschließlich auf die im Interface IGuiElement bereitgestellten Methoden zurück und können somit beliebige GUI-Elemente verwalten und steuern.
Als graphische Repräsentationen für GUI-Elemente dienen GuiElementFigures. Die graphischen Repräsentationen (Figures) sind dabei analog zu den GUI-Elementen strukturiert. Es gibt ein Interface IGuiElementFigure, welches jede Figure, die als graphische Repräsentation eines GUI-Elements herhalten soll, implementieren muss. Dazu gibt es wieder eine entsprechende Basisklasse GuiElementFigure und die davon spezialisierten Klassen für die jeweiligen GUI-Elemente.
Änderungen von Properties am Modell, also an den GUI-Elementen, triggern die Steuerungskomponente und veranlassen diese, die geänderten Properties an die entsprechende GuiElementFigure weiterzuleiten. Diese kann daraufhin ihr Aussehen entsprechend anpassen. Für die Übergabe der geänderten Properties ist die Methode notifyPropertiesChanged im Interface IGuiElementFigure vorgesehen (siehe Abb. 4.8).
Diese kann wie schon die Methode contributeProperties in der Hierarchie der GUI-Elemente (vgl. Abb. 4.9) schrittweise überschrieben werden, so dass für jede GuiElement-Klasse, sei sie abstrakt oder nicht, eine analoge GuiElementFigure-Klasse erstellt werden kann, die die in der entsprechenden GuiElement-Klasse bereitgestellten Properties von der Steuerungskomponente in Empfang nehmen und auch die Änderungen an der graphischen Repräsentation durchführen kann.
Layouts werden durch die Klasse Layout realisiert. Diese bedient sich dabei der Klasse LayoutData, welche als Datenspeicher für die Liste der Änderungen des Layouts benutzt wird (vgl. Abb. 4.10). Als besondere Änderung gilt dabei die Erzeugung eines GUI-Elements, welche durch das Interface IGuiElementConstructor gekapselt wird. Für die Wertänderungen an Eigenschaften geerbter GUI-Elemente werden einfach Properties verwendet. Die in LayoutData gehaltenen Properties werden dabei als absolute Wertänderungen der durch den Identifier des Property eindeutig identifizierten Eigenschaft des GUI-Elements interpretiert, welches als Besitzer des Property eingetragen ist.
D. Hannwacker - A. Gebel - M. Dürksen 