Phase 4: Steuerelemente implementieren
This commit is contained in:
140
openspec/specs/forms-steuerelemente/spec.md
Normal file
140
openspec/specs/forms-steuerelemente/spec.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# forms-steuerelemente Specification
|
||||
|
||||
## Purpose
|
||||
|
||||
Die Steuerelemente machen ein Formular bedienbar: sie stellen sich im
|
||||
Textbildschirm dar, nehmen Tastatur und Maus entgegen, führen Fokus und
|
||||
Tabreihenfolge, tragen die Menüleiste und stellen die vordefinierten
|
||||
Dialoge bereit.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Darstellung im Zellenpuffer
|
||||
Steuerelemente SHALL sich im vorhandenen Textbildschirm darstellen; es
|
||||
MUST NOT eine zweite Zeichenschicht neben ihm entstehen. Jede Klasse
|
||||
SHALL die in der Forms-Referenz festgelegte Optik für die Zustände
|
||||
normal, fokussiert und deaktiviert zeigen. Der CommandButton SHALL seine
|
||||
Darstellung nach der Höhe wählen: eine Zeile als `<Text>`, zwei Zeilen
|
||||
mit einzeiligem Rahmen, ab drei Zeilen als Kasten. Überlappen
|
||||
Steuerelemente, SHALL die festgelegte Z-Reihenfolge entscheiden, welches
|
||||
sichtbar ist.
|
||||
|
||||
#### Scenario: Schaltfläche nach Höhe
|
||||
- **WHEN** ein CommandButton mit `Height = 1` und `Caption = "OK"` gezeichnet wird
|
||||
- **THEN** erscheint im Zellenpuffer `<OK>`
|
||||
|
||||
#### Scenario: Deaktivierter Zustand
|
||||
- **WHEN** ein Steuerelement `Enabled = 0` trägt
|
||||
- **THEN** unterscheidet sich seine Darstellung sichtbar vom aktiven Zustand und es nimmt keinen Fokus an
|
||||
|
||||
### Requirement: Fokus, Tabreihenfolge und Access-Keys
|
||||
Der Fokus SHALL mit Tab in aufsteigender `TabIndex`-Folge und mit
|
||||
Umschalt-Tab rückwärts wechseln; Elemente mit `TabStop = 0` oder
|
||||
`Enabled = 0` MUST übersprungen werden. Ein `&` im Text SHALL den
|
||||
folgenden Buchstaben zum Access-Key machen, der mit Alt das Element
|
||||
auslöst oder ihm den Fokus gibt. Enter SHALL die `Default`-Schaltfläche
|
||||
auslösen, Esc die `Cancel`-Schaltfläche. Fokuswechsel MUST `LostFocus`
|
||||
am alten und `GotFocus` am neuen Element auslösen, in dieser Reihenfolge.
|
||||
|
||||
#### Scenario: Tab überspringt
|
||||
- **WHEN** das mittlere von drei Elementen `TabStop = 0` trägt und Tab gedrückt wird
|
||||
- **THEN** erhält das dritte Element den Fokus
|
||||
|
||||
#### Scenario: Access-Key
|
||||
- **WHEN** eine Schaltfläche `Caption = "&OK"` trägt und Alt+O gedrückt wird
|
||||
- **THEN** wird ihr `Click`-Ereignis ausgelöst
|
||||
|
||||
#### Scenario: Reihenfolge der Fokusereignisse
|
||||
- **WHEN** der Fokus von `Text1` auf `Text2` wechselt
|
||||
- **THEN** läuft erst `Text1_LostFocus`, danach `Text2_GotFocus`
|
||||
|
||||
### Requirement: Maussteuerung mit Trefferprüfung
|
||||
Ein Mausereignis SHALL dem obersten Steuerelement an seiner Position
|
||||
zugestellt werden; liegt dort keines, dem Formular. Klick, Doppelklick
|
||||
sowie `MouseDown`, `MouseMove` und `MouseUp` SHALL mit Taste,
|
||||
Umschaltzustand und Position in Zellen zugestellt werden. Bei
|
||||
`DragMode = 1` SHALL das Ziehen automatisch beginnen; `DRAG action%`
|
||||
SHALL es manuell beginnen, ablegen oder abbrechen, mit `DragOver` und
|
||||
`DragDrop` am Ziel.
|
||||
|
||||
#### Scenario: Treffer nach Z-Reihenfolge
|
||||
- **WHEN** zwei Steuerelemente überlappen und in den gemeinsamen Bereich geklickt wird
|
||||
- **THEN** erhält das obere das Ereignis
|
||||
|
||||
#### Scenario: Klick ohne Steuerelement
|
||||
- **WHEN** auf eine freie Stelle des Formulars geklickt wird
|
||||
- **THEN** erhält das Formular das Ereignis
|
||||
|
||||
#### Scenario: Ziehen und Ablegen
|
||||
- **WHEN** ein Element mit `DragMode = 1` auf ein anderes gezogen und dort losgelassen wird
|
||||
- **THEN** läuft am Ziel `DragOver` mit dem Zustand Over und danach `DragDrop` mit der Quelle als Argument
|
||||
|
||||
### Requirement: Steuerelemente mit Listeninhalt
|
||||
ListBox und ComboBox SHALL `ADDITEM` und `REMOVEITEM` unterstützen und
|
||||
`List`, `ListCount`, `ListIndex` und `Text` konsistent führen; bei
|
||||
`Sorted = -1` SHALL die Einfügereihenfolge der Sortierung folgen.
|
||||
`ListIndex = -1` SHALL „keine Auswahl" bedeuten. Die ComboBox SHALL die
|
||||
drei Stilarten (Dropdown, Simple, Dropdown List) darstellen.
|
||||
|
||||
#### Scenario: Element hinzufügen
|
||||
- **WHEN** `List1.ADDITEM "b"` und `List1.ADDITEM "a"` bei `Sorted = -1` ausgeführt werden
|
||||
- **THEN** liefert `List1.List(0)` den Wert `a` und `List1.ListCount` den Wert 2
|
||||
|
||||
#### Scenario: Keine Auswahl
|
||||
- **WHEN** eine ListBox ohne Auswahl gelesen wird
|
||||
- **THEN** liefert `ListIndex` den Wert −1
|
||||
|
||||
### Requirement: Timer-Steuerelement
|
||||
Ein Timer SHALL bei `Enabled = -1` und `Interval > 0` sein
|
||||
`Timer`-Ereignis im eingestellten Abstand auslösen, gestützt auf die
|
||||
Zeitquelle der Ereignissteuerung. `Interval = 0` SHALL ihn abschalten.
|
||||
Sind mehrere Timer gleichzeitig fällig, SHALL die Reihenfolge festgelegt
|
||||
und dokumentiert sein.
|
||||
|
||||
#### Scenario: Timer feuert im Abstand
|
||||
- **WHEN** ein Timer mit `Interval = 100` läuft und die Zeit um 250 ms vorrückt
|
||||
- **THEN** ist sein Ereignis zweimal gelaufen
|
||||
|
||||
#### Scenario: Interval 0 schaltet ab
|
||||
- **WHEN** `Timer1.Interval = 0` gesetzt wird
|
||||
- **THEN** läuft kein weiteres Ereignis
|
||||
|
||||
### Requirement: Menüsystem
|
||||
Ein Formular SHALL eine Menüleiste mit bis zu sechs Ebenen tragen.
|
||||
Menüeinträge SHALL Access-Keys (`&`), Shortcuts, `Checked`, `Enabled`,
|
||||
`Visible` und Separatoren (`-`) unterstützen; ein Separator MUST NOT
|
||||
`Checked`, deaktiviert oder mit Shortcut versehen sein, ein Menütitel
|
||||
MUST NOT einen Shortcut tragen. Solange ein Menü geöffnet ist, MUST die
|
||||
Zustellung von Zeitereignissen und klassischen Traps ruhen und danach
|
||||
fortgesetzt werden.
|
||||
|
||||
#### Scenario: Menüauswahl löst Click aus
|
||||
- **WHEN** ein Menüeintrag über seinen Access-Key gewählt wird
|
||||
- **THEN** läuft seine `Click`-Prozedur
|
||||
|
||||
#### Scenario: Traps ruhen im geöffneten Menü
|
||||
- **WHEN** ein Menü geöffnet ist und ein Zeit-Trap fällig wird
|
||||
- **THEN** läuft sein Handler erst, nachdem das Menü geschlossen wurde
|
||||
|
||||
### Requirement: Vordefinierte Dialoge
|
||||
`MSGBOX text$ [, typ% [, titel$]]` SHALL als Anweisung und als Funktion
|
||||
verfügbar sein; die Funktion SHALL die gedrückte Schaltfläche als
|
||||
INTEGER liefern (1 OK, 2 Cancel/Esc, 3 Abort, 4 Retry, 5 Ignore, 6 Yes,
|
||||
7 No). `typ%` SHALL die Schaltflächengruppe (0–5) und die
|
||||
Vorgabeschaltfläche (0/256/512) tragen. `INPUTBOX$(text$ [, titel$
|
||||
[, vorgabe$ [, x%, y%]]])` SHALL eine Zeichenkette liefern und bei
|
||||
Abbruch den leeren String. Beide Dialoge SHALL modal sein; `INPUTBOX$`
|
||||
SHALL 46×16 Zeichen messen und ohne Positionsangabe zentriert
|
||||
erscheinen.
|
||||
|
||||
#### Scenario: MSGBOX als Funktion
|
||||
- **WHEN** `a% = MSGBOX("Weiter?", 4, "Frage")` ausgeführt und `Yes` gewählt wird
|
||||
- **THEN** liefert der Aufruf 6
|
||||
|
||||
#### Scenario: INPUTBOX$ abgebrochen
|
||||
- **WHEN** ein `INPUTBOX$`-Dialog mit Esc geschlossen wird
|
||||
- **THEN** liefert er den leeren String
|
||||
|
||||
#### Scenario: Dialog ist modal
|
||||
- **WHEN** ein Dialog offen ist
|
||||
- **THEN** wird die Anweisung nach dem Aufruf erst nach dem Schließen ausgeführt
|
||||
Reference in New Issue
Block a user