Ein Widget (der Typ, nicht die Instanz) ist durch seine BluePrint Schnittstelle und seine Widget Schnittstelle eindeutig festgelegt.
Die Widget Schnittstelle definiert die Schnittstelle des Widgets, die nach seiner Erzeugung (zum Beispiel für Modifikationen, Abfragen und Funktionen) zur Verfügung steht.
Die BluePrint Schnittstelle vereint die folgenden Aspekte:
Für die Core Widgets sind diese Aspekte in unterschiedliche Schnittstellen aufgeteilt.[6]
Die Aufteilung der Schnittstellen soll anhand des Label
Widgets verdeutlicht werden. Ein Label Widget setzt sich aus
einem Icon und einem Text Label zusammen. Ein Label Widget hat
die BluePrint
Schnittstelle ILabelBluePrint
und
die Widget
Schnittstelle ILabel
.
Die Widget Schnittstelle legt den Vertrag des Widgets (nach seiner Erzeugung) fest. Ein Widget Interface muss mindestens von IWidget abgeleitet sein. Widgets welche zu einem Container hinzugefügt werden sollen, sind mindestens von IControl abgeleitet usw..
Die Schnittstelle ILabel
ist von
ITextLabel
und IIcon
abgeleitet, welche wiederum von
IControl,
IComponent und
IWidget abgeleitet
sind, und hat damit die folgenden Methoden:
1 //inherited from IIcon 2 3 void setIcon(IImageConstant icon); 4 5 IImageConstant getIcon(); 6 7 //inherited from ITextLabel 8 9 void setFontSize(int size); 10 11 void setFontName(String fontName); 12 13 void setMarkup(Markup markup); 14 15 void setText(String text); 16 17 String getText(); 18 19 //inherited from IWidget 20 21 Object getUiReference() 22 23 //...and a lot more 24 25 //inherited from IComponent 26 27 void setForegroundColor(final IColorConstant colorValue); 28 29 //...and a lot more 30 31 //inherited from IControl 32 33 void setToolTipText(String toolTip); 34 35 //...and a lot more
Anmerkung: Die von IControl, IComponent und IWidget geerbten Methoden wurden dabei nicht vollständig aufgezählt.
Das Widget Setup liefert der Widget Implementierung die
Konfiguration eines Widgets. Ein Setup besteht immer aus
Properties, welche mit get()
,
is()
oder has()
abgefragt werden können. Setup Schnittstellen können von
anderen abgeleitet sein. Zum Beispiel leitet
ILabelSetup
von
IIconSetup
und von
ITextLabelSetup
ab, und hat keine
zusätzlichen Methoden.
Ein ILabelSetup
hat dadurch die folgenden
Methoden:
IImageConstant getIcon(); String getText(); String getToolTipText(); @Mandatory Markup getMarkup(); AlignmentHorizontal getAlignment(); Integer getFontSize(); String getFontName(); Boolean isVisible(); IColorConstant getForegroundColor(); IColorConstant getBackgroundColor();
Die @Mandatory
gibt an, dass diese
Properties nicht null
sein dürfen. Wenn es
(sinnvoll) möglich ist, haben solche Properties einen
Defaultwert. Für das Markup und das Alignment ist ein
sinvoller Default möglich (Markup.DEFAULT
und AlignmentHorizontal.LEFT
). Stellt eine
Property zum Beispiel ein Interface dar, welches der Nutzer
des Widgets implementiert (sozusagen als SPI), ist es unter
umständen nicht möglich, dafür einen sinnvollen Default
anzubieten. Dann führt das Weglassen dieser Property zu einem
Fehler, wenn das Widget erzeugt wird.
Ein Widget Setup Builder liefert die Setter Methoden zu einen Widget Setup. Diese sind alle nach dem folgenden Muster aufgebaut:
BLUE_PRINT_TYPE set(PROPERTY_TYPE property);
Dabei ist PROPERTY_TYPE
der Java Typ der
Property, die gesetzt werden soll. Der BLUE_PRINT_TYPE ist der
Typ des BluePrint, um verkettete Aufrufe zu ermöglichen.
Die Schnittstelle ILabelSetupBuilder
ist
von IIconSetupBuilder
und
ITextLabelSetupBuilder
abgeleitet und hat
die folgenden einfachen Setter Methoden:
BLUE_PRINT_TYPE setIcon(IImageConstant icon); BLUE_PRINT_TYPE setText(String text); BLUE_PRINT_TYPE setToolTipText(String text); BLUE_PRINT_TYPE setMarkup(Markup markup); BLUE_PRINT_TYPE setAlignment(AlignmentHorizontal alignmentHorizontal); BLUE_PRINT_TYPE setFontSize(Integer size); BLUE_PRINT_TYPE setFontName(String fontName); BLUE_PRINT_TYPE setVisible(Boolean visible); BLUE_PRINT_TYPE setForegroundColor(final IColorConstant foregroundColor); BLUE_PRINT_TYPE setBackgroundColor(final IColorConstant backgroundColor);
Zusätzlich zu den Bean Property Setter Methoden kann ein Setup
Builder weitere Convenience Methoden haben. Die Schnittstelle
ILabelSetupBuilder
hat folgende Convenience
Methoden:
INSTANCE_TYPE alignLeft(); INSTANCE_TYPE alignCenter(); INSTANCE_TYPE alignRight(); INSTANCE_TYPE setStrong(); INSTANCE_TYPE setEmphasized();
Diese Methoden ermöglichen eine verkürzte Schreibweise. So kann man zum Beispiel anstatt:
final ILabelBluePrint labelBp = BPF.label().setAlignment(AlignmentHorizontal.RIGHT).setMarkup(Markup.STRONG);
auch
final ILabelBluePrint labelBp = BPF.label().alignRight().setStrong();
Sowohl die Getter Methoden eines Widget Setup als auch die einfachen Setter Methoden eines Widget Setup Builders werden mit Hilfe eines Java Proxy implementiert. Einen solchen BluePrintProxy erhält man von der BluePrint Proxy Factory. Insbesondere bei der Erstellung eigener Widget Bibliotheken reicht also die Definition der Setup und Setup Builder Schnittstelle aus. Die Convenience Methoden sind durch (eine oder mehrere) eigene Schnittstellen definiert. Eine Implementierung der Convenience Schnittstelle muss bei der BluePrint Proxy Factory registriert werden.
Die Widget Setup Builder von jowidgets sind von der
Schnittstelle ISetupBuilder
abgeleitet.
Diese hat die folgende Methode:
INSTANCE_TYPE setSetup(IComponentSetupCommon descriptor);
Dadurch kann ein anderes Setup, welches auch einen anderen Typ haben kann, auf dem Builder gesetzt werden. Dabei werden alle Properties mit gleichen Namen und gleichem Typ auf dem Builder gesetzt. Auf diese Weise lassen sich leicht Kopien von Setups erzeugen.
Jeder Widget Typ benötigt seinen eigenen Widget Descriptor
Typ, welcher mit Hilfe einer Schnittstelle definiert wird, die
von IWidgetDescriptor
abgeleitet ist.
Die Schnittstelle ILabelDescriptor
ist zum
Beispiel wie folgt definiert:
public interface ILabelDescriptor extends ILabelSetup, IWidgetDescriptor<ILabel> {}
Für die Schnittstelle ILabelDescriptor kann genau eine
Implementierung (zur selben Zeit) in der
Generic Widget
Factory registriert sein. Der Widget Descriptor ist
gleichzeitig auch ein Widget Setup (im konkreten Fall ein
ILabelSetup
). Ein Widget Descriptor liefert
somit alles, was von der
Generic Widget
Factory für die Erzeugung eines Widget benötigt wird.
Die BluePrint Schnittstelle fügt dem Widget Descriptor noch den Widget Setup Builder Aspekt hinzu.
Die Schnittstelle ILabelBluePrint
ist zum
Beispiel wie folgt definiert:
public interface ILabelBluePrint extends ILabelSetupBuilder<ILabelBluePrint>, ILabelDescriptor {}
Hinweis: Für jedes Widget
existiert genau eine eigene BluePrint Schnittstelle, während
unterschiedliche Widgets sich die gleiche Widget Schnittstelle
Teilen können (z.B. IFrame
für das Frame
Widget (IFrameBluePrint
) und das Dialog
Widget (IDialogBluePrint
). Die Hierarchien
der Setup und Widget Schnittstellen müssen nicht zwingend
gleich sein. So ist ein LoginDialogSetup
zum Beispiel vom ITitledWindowSetup
abgeleitet, obwohl ein ILoginDialog
nicht
von IWindow
abgeleitet ist.
Hinweis: Der Begriff BluePrint wird oft stellvertretend für den Begriff WidgetDescriptor verwendet. Dies liegt unter anderem daran, dass ein BluePrint einen Widget Typ genauso eindeutig spezifiziert wie ein WidgetDescriptor und in der Praxis beide Aspekte oft in einer Schnittstelle vereint sind. Ein BluePrint fügt zu einem separierten (in einer eigenen Schnittstelle befindlichen) WidgetDescriptor noch den Aspekt des Setup Builder hinzu, weshalb der Begriff WidgetDescriptor nicht synonym für BluePrint verwendet werden sollte, wenn der Builder Aspekt in diesem Kontext auch relevant ist.
Die ursprüngliche Idee, den Builder und Setup Aspekt zu
trennen, hat sich in der Praxis nicht bewährt. Es wird daher
empfohlen, bei der
Erstellung eigener
Widget Bibliotheken die Builder und Setup Methoden in
einer Schnittstelle unterzubringen. Für das Label würde man
dann zum Beispiel die ILabelSetupBuilder
Schnittstelle wie folgt definieren:
IImageConstant getIcon(); BLUE_PRINT_TYPE setIcon(IImageConstant icon); String getText(); BLUE_PRINT_TYPE setText(String text); String getToolTipText(); BLUE_PRINT_TYPE setToolTipText(String text); @Mandatory Markup getMarkup(); BLUE_PRINT_TYPE setMarkup(Markup markup); AlignmentHorizontal getAlignment(); BLUE_PRINT_TYPE setAlignment(AlignmentHorizontal alignmentHorizontal); Integer getFontSize(); BLUE_PRINT_TYPE setFontSize(Integer size); String getFontName(); BLUE_PRINT_TYPE setFontName(String fontName); Boolean isVisible(); BLUE_PRINT_TYPE setVisible(Boolean visible); IColorConstant getForegroundColor(); BLUE_PRINT_TYPE setForegroundColor(final IColorConstant foregroundColor); IColorConstant getBackgroundColor();
Dann wäre auch die Trennung von Descriptor und BluePrint
überflüssig und die Schnittstelle
ILabelBluePrint
würde also wie folgt
aussehen:
public interface ILabelBluePrint extends ILabelSetupBuilder<ILabelBluePrint>, IWidgetDescriptor<ILabel> {}
Die Trennung der BluePrint Schnittstelle und er SetupBuilder Schnittstelle wird jedoch nach wie vor empfohlen, um die Möglichkeit zu haben, von einem Setup Builder ableiten zu können. Von einem BluePrint sollte nicht abgeleitet werden, unter Anderem weil für das abgeleitete BluePrint der Descriptor Typ nicht mehr eindeutig sein könnte.
[6] Dies muss bei der Erstellung eigener Widget Bibliotheken nicht zwingend so gemacht werden. Das Zusammenfassung von Setup und Setup Builder in eine Schnittstelle hat sich durchaus als praktikabel erwiesen und wird zum Beispiel auch bei den Widgets der jo-client-platform so umgesetzt.