Gestion d'événements

Rédigé: Le 6 août 1997
Rédaction: Jean Vaucher
Traduction: Jocelyn Houle
Version courante: 1.1 (mod. 5 oct. 97)


Introduction

Dans WindowTools, il y a deux sortes d'événements:
  1. Les événements expédié par XWindow (les XEvents)
  2. Les événements logiciels envoyés par les widgets de WindowTools à leur fenêtres parentes.

Les événements XEvents contiennent:

Dans WindowTools, nous en avons dérivé des événements:

La version d'Oslo disposait de plusieurs procédures virtuelles, lesquelles pouvaient être redéfinies par le programmeur pour modeler ses désirs. Elles comprenaient:

Malgré leur grande utilité dans les cas particuliers, le manque de [systématisme] les rendait peu compatibles entre elles.

Dans le nouveau WindowTools de Montréal, nous avons fourni ce que nous croyons être un ensemble plus systématique des événements qui permet l'usage de capteurs d'événements (event handlers) ainsi que des routines d'attente d'un ou de plusieurs types d'événements.


Classes d'événement de WindowTools

Il y a maintenant 7 classes d'événements qu'une fenêtre peut recevoir; certaines s'appliquent à la fenêtre elle-même, à ses sous-fenêtres ou aux deux.
- AlarmEvt: une minuterie dans une fenêtre
- ButtonEvt: on a appuyé sur un bouton
- ClickEvt: un clique (à l'extérieur d'un bouton)
- DoubleClickEvt: un double-clique quelque-part
- SelectionEvt: lorsque l'on sélectionne dans une sous-fenêtre (AllowChoice)
- TypingEvt: on a entré du texte dans un champ
- WakeEvt: activation directe d'une fenêtre à l'aide de W.WakeUp


Traitement d'événements

La programmation où l'on doit traiter les événements, vous devez spécifier des capteurs d'événements (event_handlers). Ces procédures sont automatiquement appelées lorsque un événement de ce type s'exécute. Vous pouvez également décider d'attendre pour UN type d'événement ou le PREMIER parmi PLUSIEURS de ce type. Pour bien décrire ces approches, nous allons voir comment coder l'attente d'un bouton par trois approches différentes.

1) Capteurs d'événements

Les capteurs d'événements sont des routines d'interruption (des procédures ayant un nom et des paramètres précis) que vous DÉCLAREZ dons votre déclaration de fenêtre. Ils seront appelés par le systèmes lors De l'exécution. Vous ÉNONCEZ cette déclaration; vous ne l'APPELEZ pas! Par exemple, pour saisir le clique d'un bouton, votre classe doit avoir une déclaration de Handle_ButtonClick. Vous pourriez faire:

    FirstWindow class MyWindow;
    begin
        ref(button) QUIT,YB,NB;
        boolean fini;

        procedure Handle_ButtonClick(B); ref(button) B;
            if B == quit then fini := true;

        YB :- MakeButton("OUI");
        NB :- MakeButton("NON");
        QUIT :- MakeButton("EXIT");

        while not Fini do handle_event;
    end;

Notez que nous n'avons jamais appelé handle_buttonClick... Nous l'avons seulement déclaré, et il a été appelé tout seul.

2) L'attente explicite

Lorsque l'on attend pour un seul type d'événement, il est plus facile de tout simplement APPELER une procédure Wait. On coderait ainsi:

    FirstWindow class MyWindow;
    begin
        ref(button) QUIT,YB,NB, B;

        YB :- MakeButton("OUI");
        NB :- MakeButton("NON");
        QUIT :- MakeButton("EXIT");

        waitForButtonClick(B);
        while B =/= QUIT do begin
            .......
            waitForButtonClick(B);
        end;
    end;

3) L'attente de plusieurs événements

Pour attendre plusieurs événements simultanément, il faut utiliser la procédure WaitFor avec le Event_Mask composé de l'addition des constantes (AlarmEvt, ButtonEvt, etc.). Dans l'exemple qui suit, nous sortons de l'attente dès qu'un bouton est appuyé ou si 30 secondes se sont écoulées:

    FirstWindow class MyWindow;
    begin
        ref(button) QUIT,YB,NB, B;

        YB :- MakeButton("OUI");
        NB :- MakeButton("NON");
        QUIT :- MakeButton("EXIT");
        SetAlarm(30);

        WaitFor( AlarmEvt + ButtonEvt );
        if TimeOut          then outLine("We timed out....");
        if ButtonClicked(B) then OutLine("Button Clicked");
    end;

Activation Directe: Wait & WakeUp

Une fenêtre en attente W peut toujours être éveillée en appelant W.WakeUp, peu importe ce qu'elle attendait. Ceci est également utile pour permettre à un capteur d'événements (Event_Handler) d'interagir avec une procédure d'attente (Wait).


Liste des procédures

Ainsi, chaque classe d'événement peut impliquer jusqu'à 3 procédures: une capteur d'événements (à déclarer), une procédure d'attente (à appeler) et une fonction booléenne pour vérifier le type de l'événement.
TYPE CAPTEUR
(déclaration)
PROC. D'ATTENTE
(appel de proc.)
VERIFICATION
(appel de fonction)
AlarmEvt Handle_Alarm WaitForAlarm TimeOut
ClickEvt Handle_Click WaitForClick Clicked
DoubleClickEvt Handle_DoubleClick WaitForDoubleClick DoubleClicked
ButtonEvt Handle_ButtonClick WaitForButtonClick ButtonClicked
SelectionEvt Handle_Selection WaitForSelection SelectionIn
TypingEvt Handle_Typing WaitForTyping TypingIn
WakeEvt   Wait Woken

Note: Pour tous les types d'événement, le traitement doit se faire SOIT par un capteur d'événement, SOIT par la méthode explicite de l'attente. Si un capteur d'événement est présent, il sera prioritaire à l'attente explicite.

Passons maintenant aux détails... À chaque type, nous donnerons le prototype de la déclaration du capteur d'événement:

AlarmEvt

procedure Handle_Alarm;
Aucun paramètre.
procedure WaitForAlarm;
On attend un TimeOut.
boolean procedure TimeOut;
Retourne TRUE si le dernier événement est un TimeOut.

ButtonEvt

procedure Handle_ButtonClick(B); ref(Button) B;
Est appelé lorsqu'un bouton est pressé.
procedure WaitForButtonClick(B); ref(Button) B;
On attend qu'un bouton soit appuyé.
boolean procedure ButtonClicked(B); ref(Button) B;
Retourne TRUE si un bouton a été appuyé et B pointera vers ce bouton.

Compatibilité: Les procédures suivantes, présentes dans les versions d'Oslo, devraient encore fonctionner:

               ClickInButton(B);
               ButtonChoice

ClickEvt

Il s'agit de clicks dans la fenêtre courante et NON dans une sous-fenêtre ni un bouton. Nous obtiendrons les coordonnées X et Y du click.
procedure Handle_Click(X, Y); integer X, Y;
Est appelé lorsqu'on appuie sur un bouton de la souris.
procedure WaitForClick(X, Y); integer X, Y;
On attend que la souris soit appuyée; les coordonnées (x, y) du click seront retournées.
boolean procedure Clicked(X, Y); integer X, Y;
Retourne TRUE si un a appuyé sur la souris, et X et Y corresponderont aux corrdonnées (x, y) du click.

DoubleClickEvt

Il s'agit de double-clicks dans la fenêtre courante ou dans une sous-fenêtre. Nous obtiendrons les coordonnées X et Y du click.
procedure Handle_DoubleClick(W); ref(XWindow) W;
Est appelé lorsqu'on double-clique dans une fenêtre ou une sous-fenêtre.
procedure WaitForDoubleClick(W); ref(XWindow) W;
On attend un double-clique; W pointera vers la fenêtre dans laquelle on a double-cliqué.
boolean procedure DoubleClicked(W); ref(XWindow) W;
Retourne TRUE si on a appuyé sur la souris, et on changera le paramètre W pour qu'il pointe vers la fenêtre où ça s'est produit.

SelectionEvt

Ces événements sont utiles dans les sous-fenêtres de texte et les menus de différentes sortes. Ils retournent 3 éléments d'information: la fenêtre où ça s'est produit, le texte correspondant à la ligne sélectionnée, ainsi que le numéro de la ligne.
procedure Handle_Selection(W, Item, ItemN); ref(XWindow) W; text Item; integer ItemN;
Est appelé lorsqu'on double-clique dans une fenêtre ou une sous-fenêtre.
W pointera vers la fenêtre oz s'est produit le changement
Item contiendra le texte correspondant à la sélection effectuée
ItemN correspondera au numéro de ligne de la sélection
procedure WaitForSelection(W, Item, ItemN); ref(XWindow) W; text Item; integer ItemN;
On attend une sélection, puis les paramètres prennent les valeurs appropriées.
boolean procedure SelectionIn(W, Item, ItemN); ref(XWindow) W; text Item; integer ItemN;
Vérifie si l'événement est une sélection, puis retourne les valeurs appropriées.

TypingEvt

Cet événement indique à la fenêtre parente qu'une ItemWindow a été modifiée. La fenêtre parente peut alors faire une vérification ultérieure.
procedure Handle_Typing(W); ref(XWindow) W;
Est appelé lorsqu'il y a une insertion effectuée dans une fenêtre ou ses sous-fenêtres.
procedure WaitForTyping(W); ref(XWindow) W;
On attend une insertion dans une ItemWindow, puis on fait pointer W vers cette fenêtre.
boolean procedure TypingIn(W); ref(XWindow) W;
Vérifie s'il y a modification dans une ItemWindow et retourne la fenêtre appropriée.

WakeEvt

N'importe quel Wait peut être interrompu à l'aide de la procédure WakeUp soit directement (par un capteur du type approprié), soit par un autre objet (par notation pointée: W.WakeUp). Les procédures associées sont:
procedure Wait;
Attend un événement WakeUp (d'un capteur d'événement).
boolean procedure Woken;
Retourne TRUE si on a reçu un événement WakeUp.


Délégation d'événements

Si une fenêtre ne fait rien avec les événements qu'elle reçoit, elle peut les déléguer à sa fenêtre parente. Voici les délégations par défaut des différents événements par défaut de WindowTools.
ButtonEvt: Envoyé au parent
DoubleClickEvt: Envoyé au parent
ClickEvt: Envoyé au parent
AlarmEvt: PAS envoyé au parent
SelectionEvt: PAS envoyé au parent
TypingEvt: PAS envoyé au parent
WakeUpEvt: PAS envoyé au parent


XEvents

Les systèmes de gestion d'événements de X-Windows (ou encore X11) génère quelques 30 sortes distinctes d'événements en réaction aux actions de l'usager sur un terminal ainsi qu'aux interactions entre les fenêtres des applications. WindowTools et les widgets en faisant partie se charge de la plupart d'eux de façon automatique. Toutefois, il peut arriver qu'un programmeur ait besoin d'intercepter ces événements. Les événements X ne sont cependant générés que pour les fenêtres en faisant la demande. WindowTools possède donc une série de procédures permettant de filtrer les événements qu'on veut qu'une fenêtre reçoive ou non (e.g. key_sensitize & key_desensitize).

Voici une liste d'événements X et des procédures de WindowTools appelées en ces occasions.

Événements du clavier

KeyPress - Handle_Key_Down(C)
  - Handle_Special_Key_Down(Code)
    - Handle_Left_Arrow
    - Handle_Right_Arrow
    - Handle_Up_Arrow
    - Handle_Down_Arrow
Cet événement se produit lorsqu'une touche du clavier est appuyée. S'il s'agit d'un caractère ASCII, alors handle_key_down sera appelé, sinon handle_special_key_down sera appelé, lequel appelle par défaut les procédures de traitement des flèche.

KeyRelease - Handle_Key_Up(C)
  - Handle_Special_Key_Up(Code)

[Masquage: Key_Sensitize & Key_Desensitize]

Événements de la souris

ButtonPress - Handle_Button_Down ( button_number )
ButtonRelease - Handle_Special_Key_Up ( button_number )
Les boutons, ici, correspondent aux entités physiques de la souris, et non les boutons de WindowTools. Si on appuie, puis relâche un bouton de la souris à moins de 400 ms et 10 pixels d'intervalle, il y a génération d'un autre événement également: un Click. Et si un second suit rapidement, un DoubleClick sera généré.

Click - Handle_Click(X, Y)
  - Handle_DoubleClick(X, Y)

[Masquage: Button_Sensitize & Button_Desensitize]

MotionNotify - Handle_Pointer_Motion(X, Y)
Est appelé régulièrement lorsque le pointeur se déplace, et si la fenêtre est sensible au déplacement du pointeur.

[Masquage: Pointer_Motion_Sensitize & Pointer_Motion_Desensitize]

EnterNotify - Handle_Enter_Window
LeaveNotify - Handle_Leave_Window
Appelé lorsque le pointeur entre ou sort d'une fenêtre.

[Masquage: Enter_And_Leave_Sensitize & Enter_And_Leave_Desensitize]

Visibilité de la fenêtre

MapNotify Appelé par X lorsqu'il a affiché une fenêtre à l'écran
UnmapNotify Appelé par X lorsqu'il a effacé une fenêtre de l'écran
Ces événements sont généré lors des appels Show et Hide. Dans WindowTools, ces événements mettent à jour des flags (Mapped) et les appels Show et Hide attendent que le résultat de leur action se répercutent à l'écran avant de retourner le contrôle au programme.

ConfigureNotify - GetActualGeometry
  - ReplaceSubWindows
Un événement ConfigureEvent est généré lorsque fait un Resize à une fenêtre. Habituellement, le programmeur ne désire pas le savoir, mais dans ce cas, un événement Expose est généré (voir ci-bas).

Expose - Refresh
Cet événement indique que la fenêtre devrait être redessinée en partie au au complet, pour une raison ou une autre. La plupart du temps, c'est qu'une fenêtre est déplacée par dessus une autre... Par défaut, X remplit la fenêtre avec la couleur de fond (background). Pour les widgets de WindowTools, un rafraîssement automatique est effectué, mais les éléments graphiques des fenêtres de l'usager devront être redessinés.


Minuterie & AlarmNotify

X n'a rien à ce sujet, mais WindowTools gère une liste d'alertes et utilise des primitives UNIX pour générer des ALARMS intégrées dans la structure de message-clients de X.

[Retour à l'index de WindowTools...]