Phase 4: Formularmodell und Objektsprache

This commit is contained in:
2026-09-04 17:30:32 +02:00
parent 5cf5a6582c
commit 54488b5b67
35 changed files with 7195 additions and 627 deletions

View File

@@ -0,0 +1,138 @@
# forms-objektmodell Specification
## Purpose
Das Forms-Objektmodell macht Formulare und Steuerelemente zu benannten
Objekten des laufenden Programms: Eigenschaften lesen und schreiben,
Formulare laden, zeigen, verbergen und entladen — modal wie nicht-modal —,
Steuerelement-Arrays führen und Ereignisse an die Prozeduren
`Name_Ereignis` zustellen. Es ist die Grundlage der Steuerelemente und der
vordefinierten Dialoge.
## Requirements
### Requirement: Formulare und Steuerelemente als benannte Objekte
Ein Formular SHALL unter seinem Namen ansprechbar sein, ein
Steuerelement unter seinem Namen innerhalb seines Formulars. Eigenschaften
SHALL über `objekt.eigenschaft` gelesen und geschrieben werden, mit dem
in der Forms-Referenz festgelegten Typ und Wertebereich. Es SHALL keine
Standardeigenschaft geben: `Text1 = "x"` MUST abgewiesen werden. Das
Schreiben eines Wertes außerhalb des Wertebereichs MUST Laufzeitfehler 5
auslösen; eine zur Laufzeit schreibgeschützte Eigenschaft MUST bei
Zuweisung einen Fehler auslösen.
#### Scenario: Eigenschaft lesen und schreiben
- **WHEN** `Text1.Text = "hallo"` ausgeführt und danach `Text1.Text` gelesen wird
- **THEN** liefert der Zugriff `hallo`
#### Scenario: Keine Standardeigenschaft
- **WHEN** ein Programm `Text1 = "x"` enthält
- **THEN** wird es abgewiesen und die Meldung nennt `Text1`
#### Scenario: Wert außerhalb des Bereichs
- **WHEN** `Check1.Value = 3` ausgeführt wird
- **THEN** tritt Laufzeitfehler 5 auf
### Requirement: Container-Zugriff über den Bang-Operator
`form!steuerelement.eigenschaft` SHALL ein Steuerelement eines benannten
Formulars ansprechen. Die Schreibweise MUST NOT mit dem Typsuffix `!`
für SINGLE verwechselt werden; eine Variable `Form1!` und ein Zugriff
`Form1!Text1` MUST unterscheidbar bleiben.
#### Scenario: Zugriff über den Container
- **WHEN** `Form1!Text1.Text = "a"` ausgeführt wird
- **THEN** trägt die Eigenschaft `Text` des Steuerelements `Text1` in `Form1` den Wert `a`
#### Scenario: Typsuffix bleibt Typsuffix
- **WHEN** ein Programm die Variable `Wert!` verwendet
- **THEN** bleibt sie eine SINGLE-Variable und wird nicht als Containerzugriff gelesen
### Requirement: Lade- und Entladezyklus
`LOAD form` SHALL das Formular anlegen und `Form_Load` ausführen, bevor
es sichtbar wird. `UNLOAD form` SHALL `Form_Unload (Cancel)` ausführen;
ein von der Prozedur gesetzter Wert `Cancel <> 0` MUST das Entladen
verhindern. `HIDE` SHALL nur die Sichtbarkeit zurücknehmen und das
Formular geladen lassen. Der Zugriff auf ein nicht geladenes Formular
SHALL es implizit laden.
#### Scenario: Load läuft vor der Anzeige
- **WHEN** ein Formular gezeigt wird, dessen `Form_Load` eine Eigenschaft setzt
- **THEN** ist der gesetzte Wert bereits in der ersten Anzeige sichtbar
#### Scenario: Entladen abbrechen
- **WHEN** `Form_Unload` den Parameter `Cancel` auf 1 setzt und `UNLOAD Form1` ausgeführt wird
- **THEN** bleibt das Formular geladen und sichtbar
#### Scenario: HIDE entlädt nicht
- **WHEN** `Form1.HIDE` ausgeführt und danach eine Eigenschaft von `Form1` gelesen wird
- **THEN** ist der zuvor gesetzte Wert erhalten und `Form_Load` läuft nicht erneut
### Requirement: Modales und nicht-modales Anzeigen
`form.SHOW [style%]` SHALL das Formular anzeigen; `style%` 0 (Vorgabe)
zeigt es nicht-modal, 1 modal. Bei modaler Anzeige MUST die Anweisung
nach `SHOW` erst ausgeführt werden, wenn das Formular entladen oder
verborgen wurde; die Ereignisschleife MUST währenddessen weiterlaufen.
Verstöße gegen die Stapelregeln des Vorbilds MUST die Fehler 400403
auslösen.
#### Scenario: Modal hält den Ablauf an
- **WHEN** ein Programm `Form1.SHOW 1 : PRINT "danach"` ausführt und ein Ereignis `Form1` entlädt
- **THEN** erscheint `danach` erst nach dem Entladen
#### Scenario: Ereignisse laufen während der Modalität
- **WHEN** ein modales Formular angezeigt wird und ein Ereignis eintrifft
- **THEN** läuft die zugehörige Ereignisprozedur
### Requirement: Steuerelement-Arrays
Steuerelemente mit gleichem Namen und `Index` SHALL als Array
ansprechbar sein. `LOAD ctl(index%)` SHALL ein weiteres Element zur
Laufzeit anlegen, `UNLOAD ctl(index%)` es entfernen. Der Versuch, ein zur
Entwurfszeit angelegtes Element zu entladen, MUST Fehler 362 auslösen.
Bei einem Array MUST `Index AS INTEGER` als erster Parameter der
Ereignisprozedur übergeben werden.
#### Scenario: Element zur Laufzeit anlegen
- **WHEN** `LOAD Command1(3)` ausgeführt wird
- **THEN** existiert `Command1(3)` mit den Eigenschaften des Elements 0 als Vorlage
#### Scenario: Entwurfszeit-Element ist nicht entladbar
- **WHEN** `UNLOAD Command1(0)` für ein zur Entwurfszeit angelegtes Element ausgeführt wird
- **THEN** tritt Fehler 362 auf
#### Scenario: Index als erster Parameter
- **WHEN** ein Klick auf `Command1(3)` zugestellt wird
- **THEN** wird `Command1_Click` mit `Index = 3` aufgerufen
### Requirement: Ereignisdispatch an Name_Ereignis
Ein Ereignis SHALL die Prozedur `Name_Ereignis` des betroffenen Objekts
aufrufen und ihr die Argumente der in der Forms-Referenz festgelegten
Signatur übergeben. Fehlt die Prozedur, MUST das Ereignis wirkungslos
verfallen, ohne Fehler. Die Zustellung SHALL an den Zustellpunkten der
Ereignissteuerung erfolgen; es MUST NOT neue Zustellpunkte geben.
#### Scenario: Ereignisprozedur wird gerufen
- **WHEN** ein Klick auf `Command1` zugestellt wird und `SUB Command1_Click` existiert
- **THEN** läuft die Prozedur genau einmal
#### Scenario: Fehlende Ereignisprozedur
- **WHEN** ein Klick auf ein Steuerelement ohne passende Prozedur zugestellt wird
- **THEN** läuft das Programm unverändert weiter und es entsteht kein Fehler
#### Scenario: Signatur mit Mausargumenten
- **WHEN** `Form_MouseDown` definiert ist und ein Mausereignis in Zeile 5, Spalte 7 zugestellt wird
- **THEN** erhält die Prozedur Taste, Umschaltzustand und die Position in Zellen
### Requirement: SCREEN-Objekt
`SCREEN` SHALL als Objekt ansprechbar sein mit `ActiveControl`,
`ActiveForm`, `Height`, `Width`, `MousePointer` und `ControlPanel` sowie
den Methoden `SHOW` und `HIDE`. `Height` und `Width` SHALL die
**aktuelle** Terminalgröße in Zeichen liefern und schreibgeschützt sein;
die feste Größe des Vorbilds MUST als Abweichung dokumentiert sein.
#### Scenario: Größe folgt dem Terminal
- **WHEN** die Darstellungsfläche 120×40 misst und `SCREEN.Width` gelesen wird
- **THEN** liefert es 120
#### Scenario: Aktives Formular
- **WHEN** zwei Formulare geladen sind und eines den Fokus hat
- **THEN** liefert `SCREEN.ActiveForm` dieses Formular