3.4 Die "Apply"-Message3.4.1 Manuelles Auslösen der Apply-Message Einige R-BASIC Objekte enthalten Informationen oder Daten, die vom Nutzer geändert werden können und dann 'zur Anwendung' gebracht werden, indem das Objekt eine Message aussendet (d.h. den zugehörigen ActionHandler aufruft). Diese Message heißt 'Apply-Message' bzw. der Handler 'ApplyHandler' (engl. to apply: anwenden). Das sind konkret die folgenden Objekt-Klassen. Eine ausführliche Beschreibung der Objekte finden Sie im Kapitel 4 dieses Handbuchs.
^3.4.1 Manuelles Auslösen der Apply-MessageDie ApplyHandler der oben angegebenen Objekte sind bei den entsprechenden Objekten definiert und werden dort ausführlich besprochen, da sie je nach Objekt unterschiedliche Parameter haben.Es gibt jedoch eine auf GenericClass-Ebene definierte Methode und zwei dazugehörige Instance-Variablen, die ein manuelles auslösen der Apply-Message bei Bedarf, d.h. vom BASIC-Code aus, ermöglicht. Methoden:
Syntax BASIC-Code: <obj>.Apply Instance-Variablen
Syntax UI-Code: ApplyEvenIfNotModified
ApplyEvenIfNotEnabled
ApplyDie Methode Apply fordert ein Objekt auf, seine Apply-Message zu senden (d.h. seinen ApplyHandler aufzurufen). Objekte, die von Hause aus keinen ApplyHandler haben (wie z.B. Group's, Dialog- und Primary-Objekte) reichen diese Methode an ihre Children weiter. Das heißt konkret, dass es ausreicht die Apply-Methode eines Group-Objekts aufzurufen und alle seine Children bzw. deren Children usw. senden ihre Apply-Message aus, falls sie eine besitzen. Dieses Konzept ist bei genauerer Betrachtung extrem leistungsfähig, da man sich dadurch viel Arbeit ersparen kann.Wichtig 1: Die oben angegeben Objekte (Number, Text- und Listen-Objekte) senden ihre Apply-Message nur dann aus, wenn sie 'modified' (geändert) sind. Ändert der Nutzer das Objekt, klickt er z.B. einen Listeneintrag an, so passiert das automatisch. Vom Basic-Code aus müssen wir aber i.A. selbst dafür sorgen, das Objekt auf 'modified' zu setzen. Alle betroffenen Objekte besitzen eine entsprechende Instance-Variable. Wichtig 2: Nachdem das Objekt seine Apply-Message ausgesendet hat wird der 'modified'-Zustand automatisch zurückgesetzt. Beispiel: Nehmen wir an, wir haben eine Listen-Objekt namens DefaultOptions. Von diesem soll beim Programmstart ein bestimmter Eintrag selektiert werden, der z.B. aus einer Datei gelesen wurde und daher nicht von vorneherein bekannt ist. Dann soll die Liste ihre Apply-Message aussenden um den Rest des Programms über ihren Zustand zu informieren. Das Belegen der passenden Instance-Variable namens 'selection' macht die Liste aber nicht 'modified'. Damit sie ihre Apply-Message aussendet müssen wir das selbst tun. Das Ganze verpacken wir in eine SUB namens InitList: | ||||||||||||||||||||||
SUB InitList (entry as INTEGER)
DefaultOptions.selection = entry
DefaultOptions.modified = TRUE
DefaultOptions.Apply
END SUB
| ||||||||||||||||||||||
ApplyEvenIfNotModified, ApplyEvenIfNotEnabledWie oben erwähnt muss ein Objekt, dass eine Apply-Message aussenden soll 'modified' sein. Die Hints ApplyEvenIfNotModified bzw. ApplyEvenIfNotEnabled sorgen dafür, dass ein Objekt seine Apply-Message beim Aufruf der Apply-Methode auch dann aussendet, wenn es nicht 'modified' oder sogar nicht 'enabled' ist. Diese Hints sind zwar auf GenericClass-Level definiert, zeigen aber nur bei den Objekten, die auch über einen Apply-Handler verfügen, eine Wirkung.^3.4.2 Delayed Mode und Status-MessageDas im Folgenden beschriebenen Eigenschaften und Verhaltensweisen von Objekten sind - richtig eingesetzt - sehr leistungsfähig und können dem Programmierer viel Arbeit ersparen, sie erfordern jedoch ein gutes Überblickswissen über das R-BASIC Objektsystem. Sie sind daher eher etwas für den fortgeschrittenen Programmierer. Meistens ist die gleiche Funktionalität auch anders, dann allerdings mit etwas mehr Programmcode, erreichbar.Wie oben erwähnt senden die anfangs aufgeführten Objekte (Number, Text- und Listen-Objekte) ihre Apply-Message sofort aus, wenn der Nutzer z.B. eine Listeneintrag auswählt oder auf einen 'Pfeil' eines Number-Objekts klickt. Es gibt jedoch auch Situationen, in denen dieses sofortige Reagieren nicht erwünscht ist. In einem komplexen Dialog, in dem z.B. Farbe, Form und Größe eines Objekts eingestellt werden, kann es sinnvoll sein, dass der Nutzer zunächst alle Einstellungen vornimmt und diese Einstellungen dann 'auf einmal' angewendet werden sollen. Hinzu kommt, dass gegebenenfalls zwei oder mehrere Objekte voneinander abhängen. In einen 'Drucken'-Dialog z.B. muss sichergestellt werden, dass die erste zu druckende Seitennummer nicht größer als die letzte zu druckende Seitennummer ist. Die entsprechenden Number-Objekte müssen also miteinander kommunizieren, ohne dass die Änderungen 'angewendet' (d.h. die Seiten gedruckt) werden. In R-BASIC wird dieses Verhalten als Delayed Mode bezeichnet (engl. to delay: verzögern). Die eigentliche Apply-Message der betroffenen Objekte wird verzögert, nämlich erst auf Anforderung, ausgesendet. Statt ihrer Apply-Message senden die entsprechenden Objekte zunächst eine sogenannte Status-Message aus, d.h. es wird der StatusHandler aufgerufen. Dieser kann genutzt werden, um andere Objekte zu informieren. Die entsprechende Instance-Variable (StatusHandler) ist genau wie der ApplyHandler bei den jeweiligen Objekten definiert.
Syntax UI-Code: MakeDelayedApply Die auf GenericClass-Ebene definierte Instance-Variable MakeDelayedApply versetzt ein Objekt und seine Children in den Delayed Mode. Sehr häufig ist es deshalb so, dass ein Group-Objekt diese Anweisung im UI-Code erhält, so das alle seine Children, deren Children usw. im Delayed Mode arbeiten. Um die Apply-Message der betroffenen Objekte auszusenden reicht es, die Apply-Methode des Group-Objekts aufzurufen, da diese, wie im vorherigen Abschnitt beschrieben, an alle Children weitergegeben wird. Beispiel: Eine Gruppe von Objekten innerhalb der Group 'BottomGroup' arbeitet im Delayed Mode. Die beiden Number-Objekte kommunizieren über Status-Handler miteinander. Der ApplyButton löst ein 'Anwenden' (Aufruf der ApplyHandler) aus.
UI-Code | ||||||||||||||||||||||
Group BottomGroup
Children = Memo1, RightGroup
orientChildren = ORIENT_HORIZONTALLY
DrawInBox
MakeDelayedApply ' wird an die Children weitergereicht
END Object
Group RightGroup
Children = Number1, Number2, ApplyButton
orientChildren = ORIENT_VERTICALLY
justifyChildren = J_RIGHT + J_BOTTOM
ExpandHeight
END Object
Number Number1
Caption$ = "Von "
ApplyHandler = NumberVonHandler
StatusHandler = StatusNum1
END Object
Number Number2
Caption$ = "Bis "
ApplyHandler = NumberBisHandler
StatusHandler = StatusNum2
END Object
Button ApplyButton
Caption$ = " Anwenden"
ActionHandler = DoApply
END Object
Memo Memo1
Caption$ = "Note:"
justifyCaption = J_TOP
text$ ="Hier Text eingeben ..."
fixedSize = 30 + ST_AVG_CHAR_WIDTH, 5 + ST_LINES_OF_TEXT
ApplyHandler = txtAction
END Object
| ||||||||||||||||||||||
|
| ||||||||||||||||||||||
NUMBERACTION NumberVonHandler
Print "Von:";value
END ACTION
NUMBERACTION NumberBisHandler
Print "Bis:";value
END ACTION
NUMBERACTION StatusNum1
IF value > Number2.value THEN
Number2.value = value
Number2.modified = TRUE ' wurde verändert!
END IF
END ACTION
NUMBERACTION StatusNum2
IF value < Number1.value THEN
Number1.value = value
Number1.modified = TRUE ' wurde verändert!
END IF
END ACTION
BUTTONACTION DoApply
BottomGroup.Apply
END Action
| ||||||||||||||||||||||
Wenn Sie dieses Beispiel testen werden Sie feststellen, dass
Beispiel UI-Code | ||||||||||||||||||||||
Number Number2
Caption$ = "Bis "
ApplyHandler = NumberBisHandler
StatusHandler = StatusNum2
ApplyEvenIfNotModified
END Object
| ||||||||||||||||||||||
Bei Bedarf ist es möglich, die StatusMessage manuell auszulösen. Dazu wird die Methode SendStatus verwendet. Diese Methode ist für die oben genannten Objektklassen definiert. Das sind: Number, Memo, InputLine, OptionGroup, RadioButtonGroup und DynamicList.
Syntax BASIC-Code: <obj>.SendStatus Hinweis für Dialog-Objekte: Natürlich können Sie ganze Dialogboxen mit dem Hint MakeDelayedApply in den Delayed Mode versetzen. Häufig ist es aber besser stattdessen die Dialog-Instance-Variable dialogType auf den Wert DT_DELAYED_APPLY zu setzen. Dadurch erzeugt der Dialog automatisch einen Apply-Button, und nimmt Ihnen auch sonst viel Arbeit ab. Eine ausführliche Beschreibung zum Dialog-Objekt finden Sie im Kapitel 4.6, der Delayed Mode für Dialoge ist im Kapitel 4.6.6.5 beschrieben. Schlussbemerkung: Der Delayed Mode ist angebracht und sehr effektiv, wenn die betroffenen Objekte ihre Apply-Message einzeln und unabhängig voneinander senden sollen. Für den Fall, dass Sie erst die Informationen von allen beteiligten Objekten sammeln müssen, bevor Sie fortfahren können, ist es eventuell sinnvoller den Objekten gar keinen ApplyHandler zu geben und die Informationen direkt von den Objekten abzufragen, wie in folgendem Codebeispiel gezeigt: | ||||||||||||||||||||||
BUTTONACTION DoApply
DIM von, bis, info$
von = Number1.value
bis = Number2.value
info$ = Memo1.text$
<.. Auswertung ..>
END Action
| ||||||||||||||||||||||
^ |