12. Focus und Target
12.1 ÜberblickDas GEOS-System benötigt einen oder mehrere Wege, auf dem Usereingaben zu dem Objekt geleitet werden, für das sie bestimmt sind. Neben dem Weg, den Mausereignisse gehen, und der in einem eigenen Kapitel beschrieben wird, sind das unter GEOS die Focus-Hierarchie und die Target-Hierarchie. Diese beiden Hierarchien arbeiten sehr ähnlich und werden im Folgenden beschrieben.FocusDie Focus-Hierarchie beschreibt, an welches Objekt Tastatureingaben des Nutzers gehen sollen. Das kann z.B. ein Textobjekt oder ein geöffnetes Menü sein. Man sagt, das Objekt, an das letztlich die Tastatureingaben gehen, "hat den Focus".
Eine Arbeit mit der Focus-Hierarchie ist nur sehr selten nötig, da Textobjekte automatisch damit umgehen können.
TargetDie Target-Hierarchie (engl. target = Ziel) beschreibt das Zielobjekt einer Operation, die der Nutzer ausführt. Ein gutes Beispiel ist ein Textobjekt, in das der Nutzer gerade etwas eingibt. Wenn der Nutzer ein Menü benutzt um die Größe des Texts im aktiven Textobjekt zu ändern, dann ist das Textobjekt das Ziel dieser "Operation". da Gleiche gilt, wenn er einen Eintrag aus dem Edit-Menü wählt, um Text in die Zwischenablage zu kopieren oder von dort einzufügen. Man sagt, das Objekt, mit dem gearbeitet werden kann "ist das Target", manchmal auch "hat das Target".Das letzte Beispiel zeigt auch sehr deutlich, warum zwei Hierarchien gebraucht werden. Klickt der User mit der Maus auf ein Menü verliert der Text den Focus, aber nicht das Target. Deswegen kann der Actionhandler des Menüeintrags entscheiden, mit welchem Objekt er interagieren soll - nämlich mit dem Target. Sowohl die Focus- als auch die Target-Hierarchie sind an die Tree-Struktur der Objekte gekoppelt. Jedes Objekt kann genau eins seiner Children für den Focus- und eines für den Target-Pfad auswählen. Dasjenige Objekt, das am Ende dieses Pfades steht hat den Focus bzw. das Target. Das folgende Bild verdeutlicht das.
Bild 1: Aktive und inaktive Targets und Pfade Die linke Abbildung zeigt den Ausgangszustand. Klickt der Nutzer jetzt mit der Maus auf Objekt 2 (z.B. eine Dialogbox) so wird Objekt 9 (z.B. ein Textobjekt in diesem Dialog) zum aktiven Target. Jedes Mal, wenn ein Objekt Teil des aktiven Pfades wird oder den aktiven Pfad verlässt kann es eine Message aussenden (Handler OnFocusChanged oder OnTargetChanged). Auf diese Weise kann ein Programm stets über das aktuelle Target- oder Focus-Objekt informiert sein und bei Bedarf die UI anpassen, z.B. ein Edit-Menü enablen oder disablen. Zur Arbeit mit Focus und Target stehen die folgenden Instancevariablen, Handlertypen und Systemvariablen zur Verfügung:
^12.2 Arbeit mit dem FocusHäufig wird der Hint defaultFocus verwendet um sicherzustellen, dass ein bestimmtes Objekt am Anfang den Focus hat. Eine weitergehende Arbeit mit dem Focus ist nur selten nötig. Alle Objekte können Standardsituationen automatisch handeln.defaultFocusDer Hint defaultFocus bewirkt, dass das Objekt am Anfang den Focus bekommt. Meistens reicht es, dem Objekt selbst diesen Hint zu geben, bei komplexen Baumstrukturen muss man ihn manchmal auch den Parents geben.Syntax UI-Code: defaultFocus DefaultFocus ist auf GenericClass Level definiert und damit für alle Abkömmlinge der GenericClass verfügbar. OnFocusChangedDie Instancevariable OnFocusChanged enthält den Namen des Actionhandlers, der aufgerufen wird, wenn das Objekt den Focus erhält oder verliert. Er wird auch gerufen wenn das Objekt Teil des aktiven Focuspfades wird oder vom aktiven zum inaktiven Pfad wechselt.OnFocusChanged Handler müssen als FocusAction deklariert sein. Der OnFocusChanged Handler ist für folgende Objektklassen definiert:
Beispiel: Wir wollen sicherstellen, dass ein InputLine Objekt disabled wird, wenn der Nutzer es verlassen hat. UI-Code: |
InputLine Text1 defaultFocus OnFocusChanged = HandleFocus End Object |
| BASIC-Code: |
FocusAction HandleFocus
IF hasFocus = FALSE THEN
Text1.enabled = FALSE
End IF
End Action
|
FocusDie globale Systemvariable Focus enthält das Objekt, das aktuell den Focus hat, d.h. das sich am Ende des aktiven Focuspfades befindet. Der Wert kann gelesen und geschrieben werden.Beispiele |
IF Focus = MyObj THEN ... Focus.Capion$ = "Neuer Text" |
'Ein bestimmtes Textobjekt als Focus auswählen, damit der 'User genau in dieses Objket etwas einträgt Focus = MyTextObject |
|
Achtung! Wenn Sie der Variablen Focus ein Objekt zuweisen, dass nicht am Ende eines Objektpfades steht (z.B. Focus = MyGroupWithChildren) kann das zu "komischem" Verhalten oder Systeminstabilität führen.
Hinweis: Es gibt Situationen, in denen R-BASIC das Focus-Objekt nicht identifizieren kann. Insbesondere ist das der Fall, wenn ein Number-Objket oder ein Eintrag in einer DynamicList den "Focus" hat. Die Systemvariable Focus enthält dann einen Verweis auf ein "leeres" oder ein "internes" Objekt. Sie können die Situation prüfen, indem dem Sie die Instancevariable Class$ des Focus-Objekts abfragen. Focus.Class$ liefert in diesem Fall einen leeren String.
View: focusableFür View-Objekte ist die numerische Instancevariable focusable definiert, die TRUE oder FALSE sein kann. Sie muss TRUE sein, damit das View (und damit sein Content) den Focus bekommen kann. Per default ist sie TRUE.
12.3 Arbeit mit dem TargetDie Auswertung des Targets wird häufig benutzt um spezielle Menüs zu implementieren, z.B. das "Bearbeiten" Menü. Ein ausführlich kommentiertes Beispiel finden Sie im nächsten Kapitel. Eine weitergehende Arbeit mit dem Target ist etwas für erfahrende Programmierer und nur selten nötig. Alle Objekte können Standardsituationen automatisch handeln.OnTargetChangedDie Instancevariable OnTargetChanged enthält den Namen des Actionhandlers, der aufgerufen wird, wenn das Objekt zum Target wird oder diesen Status verliert. Er wird auch gerufen, wenn das Objekt Teil des aktiven Targetpfades wird oder vom aktiven zum inaktiven Pfad wechselt.OnTargetChanged Handler müssen als TargetAction deklariert sein. Der OnTargetChanged Handler ist für folgende Objektklassen definiert:
Beispiel: Wenn Sie mehr als ein Textobjekt haben wird dieser Handler oft benutzt um die UI entsprechend den Attributen (Font, Textgröße, Farben usw.) anzupassen, die im Textobjekt dargestellt werden, mit dem der Nutzer gerade interagiert, d.h. dass das Target ist. Der Code zeigt, wie man im OnTargetChanged Handler ein Number-Objekt anspricht, so dass es die Größe des verwendeten Fonts anzeigt. UI-Code: |
Memo Text1 fontSize = 14 fontID = FID_MONO defaultFocus OnTargetChanged = HandleTarget End Object Memo Text2 fontSize = 24 fontID = FID_SANS OnTargetChanged = HandleTarget End Object Number PointInfoNumber Caption$ = "Aktuelle Font Größe:" End Object |
| BASIC-Code: |
TargetAction HandleTarget IF hasTarget THEN PointInfoNumber.value = sender.fontSize ' UI updaten End IF End Action |
TargetDie globale Systemvariable Target enthält das Objekt, das aktuell das Target ist, d.h. das sich am Ende des aktiven Targetpfades befindet. Der Wert kann gelesen und geschrieben werden.Die Variable wird oft in Actionhandlern verwendet, die auf das aktuelle Target wirken sollen. Ein ausführlich kommentiertes Beispiel finden Sie im nächsten Kapitel. Beispiel: Ein Menü enthält eine OptionGroup, deren Actionhandler (namens ChangeSize) die Zeichengröße bei einem Textobjekt ändern soll. |
LISTACTION ChangeSize Target.fontsize = selection END ACTION ' ChangeSize |
| Wenn man nicht sicher sein kann, dass das aktuelle Target ein Textobjekt ist, muss man vorher die Klasse abfragen. |
LISTACTION ChangeSize IF Target.Class$ <> "MEMO" THEN RETURN Target.fontSize = selection END ACTION ' ChangeSize |
Achtung! Wenn Sie der Variablen Target ein Objekt zuweisen (z.B. Target = MyObj), dass nicht am Ende eines Objektpfades steht oder nicht targetable ist, so kann das zu "komischem" Verhalten oder Systeminstabilität führen.
targetable (selten verwendet)Die Instancevariable targetable enthält die Information, ob ein Objekt zum Target werden kann oder nicht. Der Wert ist per default bei allen Objektklassen, für die ein OnTargetChanged Handler definiert ist (siehe oben) auf TRUE gesetzt, für alle anderen Objektklassen ist er per default FALSE. Im Normalfall besteht keine Notwendigkeit, daran etwas zu ändern. Setzen Sie z.B. bei einem der oben genannten Objekte targetable = FALSE, so kann weder dieses Objekt, noch seine Children (bzw. bei einem View sein Content) zum Target werden.Syntax UI-Code: targetable Lesen: <numVar> = <obj>.targetable Schreiben: <obj>.targetable = TRUE ¦ FALSE Targetable ist auf GenericClass Level definiert und damit für alle Abkömmlinge der GenericClass verfügbar. Für View-Objekte gilt: Um mit einem ViewControl zusammenzuarbeiten, muss das View targetable sein. Außerdem muss das Bit VA_CONTROLLED in der Instancevariablen viewAttrs gesetzt sein.
defaultTargetDer Hint defaultTarget bewirkt, dass das Objekt am Anfang das Target ist.Tipp: In vielen Fällen (z.B. Textobjekte) ist es notwendig, statt defaultTarget den Hint defaultFocus zu verwenden. Syntax UI-Code: defaultTarget DefaultTarget ist auf GenericClass Level definiert und damit für alle Abkömmlinge der GenericClass verfügbar. Tipp:
^ |