FormEditor

Der Zweck der Komponente ist es zuerst eine Sammlung der Formulare zu einer Datenbank zu generieren und zweitens eine Benutzerschnittstelle für die Anpassung der Formulare zu liefern. Das Produkt des Formular-Editor eine Beschreibung der Formulare als ein XML-Dokument. Dabei wird es im Gegenteil zu vorhanden ähnlichen Systemen nicht einzeln zu jedem Tabellen ein Formular generiert, vielmehr wird eine ganze Sammlung der Formularen in einem Schritt generiert. Dabei werden die Assoziationen im Datenbank in der Formularen direkt unterstützt. Der Benutzer des Formular-Editor (Applikation-Entwickler) muss das Schema der Daten nicht kennen. Seine Aufgabe ist es höchstens die automatisch erzeugte Formulare unter dem gestalterischen Gesichtspunkten anzupassen oder die Eingabefelder des Formulars noch weiter zu spezifizieren.

Ein Formular wird als eine Sammlung von verschiedenen Eingabefelder, ihrer Platzierung, und ihrer Entsprechung zu Objekten in der Datenbank verstanden. Folgende Typen der Eingabefelder wurden realisiert:

Frames. Rahmen für die Platzierung der Elemente
einfache Textfelder (einzeilig)
Eingabefelder für Ganzzahlen mit Steuerungspfeilen
Listenfelder
Radiobuttons
Checkbox Felder (Ja/Nein Schalter)
mehrzeilige Textfelder
Mehrspaltige Auswahllisten für die Darstellung der Fremdschlüssel (Referenzen)
Formular Links
Objekt für die Einbettung von Formularen

Zu speziellen Elementen der Formulare gehören die eingebettete Formulare und die Formular Links. Beide sind verschiedene Visualisierung der Formularverknüpfungen. Die Verknüpfungen entstehend entlang der Beziehung Pfaden (Assoziation oder auch Aggregation). Dabei kann man aus einem Formular ein Formular des Objekts erreichen der ein Fremdschlüssel auf das erste Formular hat. Dabei wird bei dem verknüpften Formular der Fremdschlüssel ausgeblendet (Der Wert wird von ersten Formular bestimmt) und die Dateien werden nach dem Fremdschlüssel gefiltert. Es werden durch die Filterung nur die Objekte gezeigt, die mit dem gezeigten Objekt in dem ersten Formular in Verbindung stehen. Bei eingebetteten Formularen ist der verknüpfte Formular ein Teil des Elternformulars. Bei Formular-Links wird eine Schaltfläche eingebaut, die erst zum öffnen des verknüpften Formulars dient. Die Fremdschlüssel werden nicht als normale Attribute behandelt sondern als spezielle graphische Elemente dargestellt. Dabei sind zwei Tatsachen zu berücksichtigen. Zuerst ist das Wertebereich des Fremdschlüssel durch Integritätsbedingungen auf die Menge von Primärschlüsselwerte in der korrespondierenden Tabelle begrenzt. Das kann durch eine Auswahlliste repräsentiert werden. Der Benutzer weiß dann, dass er nur eine bestimmte Anzahl von Möglichkeiten hat, die er ansehen und auswählen kann. Zweitens sind die Werte des Schlüssel oft für den Benutzer aussageleer oder ungeeignet für die Identifizierung des Objektes. Dafür erwartet der Benutzer weitere Attribute (z.B Name und Vorname außer des PersonalIDs). Die Aggregation kann als die eingebetteten Formulare realisiert werden. Die Assoziation wird als Formular-Links umgesetzt. Die Spezialisierung kann auch als eine Verknüpfung von Formularen realisiert werden. Dabei wird ein Formular für ein Elternobjekt (Ober-Typ) und je ein Formular für den Kindobjekt (Unter-Typ) verwendet.

GUI Editor für Formulare

Durch das Doppelklick auf ein Formular in Hauptfenster wird ein GUI Editor für Formulare geöffnet. Damit kann das Aussehen des Formulars und die Verknüpfungen der einzelnen Elemente zum Datenbank spezifiziert werden.

Abbildung 2. GUI-Form-Editor (screenshoot)

Die Eigenschaften der Elemente werden auf drei Typen

Widget

Die Eigenschaften, die zu eigentlichen GUI-Objekt gehören wie: Länge, Art.

Data

Verknüpfung mit Tabellen-Spalte. Defaultwert und NotNULL

Packer

Angaben zu Platzierung des Elements

Die Platzierung der Elemente wird nicht absolut (also mit Koordinaten) aber unter Verwendung von s.g Geometry-Manager angegeben. Es werden der Pack-Geomentry-Manager und Grid-Widget-Manager der Tk-Widgetset unterstützt. Die Elementen können in s.g. Frames (Rahmen) gestellt werden (auch geschachtelt).

Tipp

Die aktuellen Pack Optionen kann man in der Statusleiste nach dem Anzeigen des Widgets mit Mauszeiger auslesen.

Die meisten Standard-Widget werden angezeigt wie sie sind. Die anderen speziellen Widget wie (NestedForm, FormLink, SQLReference) werden bei GUI Editor durch die Vertreter angezeigt. Ihre Größe entspricht nicht der Wirklichkeit (Vorsicht beim NestedForm). Will man das tatsächlich Aussehen der Formulare haben, muss man den FormServer benutzten, die DB-Anbindung ist für solche Zwecke nicht nötig.

Drag and Drop im FormEditor

Die Fläche der FormEditor wird im drei Flächen geteilt.

Widget Sammlung
Arbeitsfläche mit dem gezeigten Formular
Ablage (untere Bereich)

Die Mögliche Drag & Drop Operationen werden in Abbildung 3 gezeigt. Die Drag & Drop wird gezeigt durch das veränderte Maus-Zeiger Icon. Das Objekt wird selbst nicht bewegt. Die Ablage ist hier etwas neues und ungewohntes. Meist verschwindet ein Objekt bei Ausschneiden in einen unsichtbaren Puffer. Hier wird es einfach in die Ablage bewegt. Das gleiche kann man mit Drag & Drop auf die Ablage erreichen. Die Ablage kann mehrere Objekte beinhalten. Deswegen gibt es auch keine Einfüge-Operation.

Tipp

Bei Einfügen der Widget zu Formular wird immer das Typ genommen der in Widgetsammlung ausgewählt wurde, also durch dunkles Hintergrund markiert ist.

Abbildung 3. Drag and Drop Operationen (schematisch)

Platzieren in einem Pack-Frame

Die Reihenfolge der Elemente in einem Frame ist entscheidend. Der Pack-Geomentry-Manager nimmt nacheinander die Elemente und stellt sie in den Rahmen der restliche Platz wird für nächste Elemente verwendet. Folgende Eigenschaften spezifizieren die Platzierung:

side - An welcher Seite der Rahmen soll der Objekt hinzugefügt werden
anchor - Anker zu welcher Seite
fill - Soll der Objekt in eine Richtung zu den verbleibenden Platz ausgefüllt werden
expand - Soll bei Änderung der Fenstergröße der Objekt angepasst werden

Wichtig in diesem Zusammenhang ist die Vorgehensweise wie beim Drag and Drop die Platzierung der Elemente vorgenommen wird. Zeigt man auf ein Frame allgemein wird das Element in das Frame an letzten Stelle mit Standard Optionen angefügt (-side top -anchor center -fill none -expand 0). Die genauere Platzierung wird durch das Anzeigen (Drop) auf ein Element, das bereits in der Frame ist ermöglicht. Die Reihenfolge wird relativ zu dem Angezeigten Element ermittelt, die -side Option wird von dem Element übernommen. Andere Optionen können nur im Eigenschaftenfenster verändert werden.

Abbildung 4. Platzieren in einem Pack-Frame (schematisch)

Die Abbildung 4 Zeigt an einem Beispiel das Prinzip wie der Pack-Geometry-Manager arbeitet und wie bei einen Drag & Drop Operation die Platzierung des Widget ermittelt wird . Die Widget haben folgende Platzierung-Optionen. Die Reihen Folge ist wichtig. Der Algorithmus platziert zuerst das erste Widget (markiert mit 1), der Bereich A wird besetzt und kann weiter nicht mehr verwendet werden. Die Optionen der weiteren Widget.

  1. -side left

  2. -side top

  3. -side bottom -anchor e

  4. -side right

Wie das Widget in seinem Bereich platziert wird hängt von -anchor Attribut. Standardmäßig wird es zentriert (-anchor center). Will man ein neues Widget in das Frame einfügen, muss man die Position relativ zu bestehenden 4 Widget angeben. Zeigt man in den Raum (Blau) zwischen den Widget, wird aus am Ende der Packliste (Position 5) mit Standardoptionen eingefügt (-side top -anchor center). Also das blaue Raum in der Mitte. Zeigt man auf ein Widget, wird der -side Attribut von dem Widget übernommen, die Pasten wird relativ zu dem gezeigten weidest ermittelt. Zeigt man auf die Fläche (a) des ersten Widget wird die Position auf 0 gewählt. Man kann auf diese Weise die Widget schnell aneinander reihen. Die speziellen Optionen können erst in einem Dialog spezifiziert werden.

Platzieren in einem Grid-Frame

Das Grid-Manager platziert die Widget in einem Gitter (Tabelle). Die Zellen-Größen werden entsprechen der Bedürfnissen der einzelnen Widget ermittelt. Ein Widget kann auch mehrere benachbarte Zellen besetzen (-columnspan -rowspan). Im Gegenteil zu anderen GUI-Editoren werden die Spalten und Zeilen dynamisch gebildet. Man muss also die Zeilen- und Spaltenzahl nicht angeben oder keine neuen Zeilen oder Spalten einfügen.

Abbildung 5. Platzieren in einem Grid-Frame (schematisch)

Die Abbildung 5 Zeigt ein beispielhaftes Grid-Frame. Die Zellen A2,B2,B3,C1,C3 sind bereits besetzt. Beim Drag&Drop Operation wird es zuerst ermittelt ob eine Zelle frei ist. Ist das der Fall wird sie einfach besetzt. Wird auf eine besetzte Zelle gezeigt (z.B. B2), wird angenommen, dass eine neue Spalte oder Zeile hinzugefügt werden soll um eine neue Zelle zu schaffen. Wird (siehe Zelle B2) der Bereich d (oben) angezeigt wird eine Zeile über der Zelle B3 hinzugefügt. Das neue Widget wird über das Widget im Zelle B2 platziert.

Die speziellen Optionen wie Spaltenbreite und Zeilenhöhe der Zelle können erst in einem Dialog spezifiziert werden.

Pack Geometry Manager

Es wurden zwei geometry Manager pack und grid für die Platzierung der Widget benutzt. Beide sind sehr mächtig und erlauben sehr gute Feststellung von Windows Platzierung auch beim wechselnden Windowsgroßen. Ähnliche oder gleiche Geometrymanager werden auch bei Java, Gtk und Qt benutzt. Grid ist am schnellsten zu verstehen und entspricht etwa der Tabelle.

Mehr dazu Lesen Sie in Tk-Dokumantation man pack, man grid Hier ein Ausschnitte aus pack Man-Dokumentation.

For each master the packer maintains an ordered list of slaves called the packing list. The -in, -after, and -before configuration options are used to specify the master for each slave and the slave's position in the packing list. If none of these options is given for a slave then the slave is added to the end of the packing list for its parent. The packer arranges the slaves for a master by scanning the packing list in order. At the time it processes each slave, a rectangular area within the master is still unallocated. This area is called the cavity; for the first slave it is the entire area of the master. For each slave the packer carries out the following steps:

  1. The packer allocates a rectangular parcel for the slave along the side of the cavity given by the slave's -side option. If the side is top or bottom then the width of the parcel is the width of the cavity and its height is the requested height of the slave plus the -ipady and -pady options. For the left or right side the height of the parcel is the height of the cavity and the width is the requested width of the slave plus the -ipadx and -padx options. The parcel may be enlarged further because of the -expand option (see ``EXPANSION'' below)

  2. The packer chooses the dimensions of the slave. The width will normally be the slave's requested width plus twice its -ipadx option and the height will normally be the slave's requested height plus twice its -ipady option. However, if the -fill option is x or both then the width of the slave is expanded to fill the width of the parcel, minus twice the -padx option. If the -fill option is y or both then the height of the slave is expanded to fill the width of the parcel, minus twice the -pady option.

  3. The packer positions the slave over its parcel. If the slave is smaller than the parcel then the -anchor option determines where in the parcel the slave will be placed. If -padx or -pady is non-zero, then the given amount of external padding will always be left between the slave and the edges of the parcel.

Once a given slave has been packed, the area of its parcel is subtracted from the cavity, leaving a smaller rectangular cavity for the next slave. If a slave doesn't use all of its parcel, the unused space in the parcel will not be used by subsequent slaves. If the cavity should become too small to meet the needs of a slave then the slave will be given whatever space is left in the cavity. If the cavity shrinks to zero size, then all remaining slaves on the packing list will be unmapped from the screen until the master window becomes large enough to hold them again.