Responder
- Object
- Responder
Une instance de Responder envoie automatiquement des messages de notification à une ou plusieurs instances. Des instances de Responder peuvent être liées afin que les notifications soient automatiquement transmises d'un répondeur à un autre.
- #include "So-o.h"
- class Responder;
Charge les déclarations des types de données et des fonctions de So-o. Définit la classe Responder.
- void defclassResponder() {
- property _i_properties[] = {
- "nextResponders",
- 0
- };
- selector _i_messages[] = {
- "addNextResponder", METHOD(i_addNextResponder),
- "removeNextResponder", METHOD(i_removeNextResponder),
- "respondTo", METHOD(i_respondTo),
- 0, 0
- };
- Responder = defclass("Responder", 0, 1, 0, _i_properties, 0, _i_messages);
- }
Définit defclassResponder
, le constructeur de la classe Responder.
La classe Responder hérite de la classe Object. La propriété d'instance nextResponders contient la liste des instances qui ont demandé à être notifiées lorsqu'un événement se produit. La classe Responder ajoute les messages d'instance addNextResponder, removeNextResponder et respondTo.
MÉTHODES D'INSTANCE
addNextResponder
SYNOPSIS
instance addNextResponder(instance self, instance r)
DESCRIPTION
addNextResponder
ajoute r
à la liste des répondeurs de self
.
CODE
- static instance i_addNextResponder(instance self, va_list va) {
- instance r = va_arg(va, instance);
- list responders = sendmsg(self, "get", "nextResponders").p;
- if (!responders) {
- responders = list_new();
- sendmsg(self, "set", "nextResponders", responders);
- list_put(responders, -1, r);
- }
- else if (list_find(responders, r, 0) == -1)
- list_put(responders, -1, r);
- return self;
- }
Extrait l'instance r
de la liste d'arguments va
.
Obtient la liste des répondeurs de self
.
Si la liste est NULL
, crée une nouvelle liste et l'enregistre puis ajoute r
à la liste.
Si la liste n'est pas NULL
, lui ajoute r
si r
n'est pas déjà dans la liste.
removeNextResponder
SYNOPSIS
instance removeNextResponder(instance self, instance r)
DESCRIPTION
removeNextResponder
retire r
de la liste des répondeurs de self
.
CODE
- static instance i_removeNextResponder(instance self, va_list va) {
- instance r = va_arg(va, instance);
- list responders = sendmsg(self, "get", "nextResponders").p;
- if (responders) {
- int i = list_find(responders, r, 0);
- if (i != -1)
- list_delete(responders, i);
- }
- return self;
- }
Extrait l'instance r
de la liste d'arguments va
.
Obtient la liste des répondeurs de self
.
Si la liste n'est pas NULL
, cherche l'index de r
dans liste et si l'index n'est pas -1, retire r
de la liste.
respondTo
SYNOPSIS
instance respondTo(instance self, message msg[, arg ...])
DESCRIPTION
Si self
répond à msg
, respondTo
envoie msg
et ses paramètres arg
à self
.
Si self
ne répond pas à msg
ou si l'exécution du message retourne NULL
, respondTo
transmet le message et ses paramètres à toutes les instances de la liste des répondeurs de self
.
CODE
- static instance i_respondTo(instance self, va_list va) {
- va_list vac;
- va_copy(vac, va);
- message msg = va_arg(vac, message);
- if (sendmsg(self, "respondsTo", msg).i && applymsg(self, msg, vac).i) {
- va_end(vac);
- return self;
- }
- va_end(vac);
- list responders = sendmsg(self, "get", "nextResponders").p;
- if (responders) {
- for (int i = 0; i < list_length(responders); i++) {
- va_copy(vac, va);
- applymsg(list_get(responders, i), "respondTo", vac);
- va_end(vac);
- }
- }
- return self;
- }
Fait une copie de la liste d'arguments va
dans vac
.
Extrait le message msg
de la copie.
Si self
répond à msg
, lui envoie msg
avec vac
.
Si l'exécution du message ne retourne pas NULL
, libère vac
et retourne self
.
Si self
ne répond pas à msg
ou si l'exécution du message par self
retourne NULL
, libère vac
et transmet msg
avec va
à tous les répondeurs de self
.
EXEMPLE
Une instance de Button notifie le message clicked quand elle reçoit le message click :
- class Button;
- static instance i_click(instance self) {
- printf("%s click\n", (char *)sendmsg(self, "toString").p);
- sendmsg(self, "respondTo", "clicked", self);
- return self;
- }
- void defclassButton() {
- selector _i_messages[] = {
- "click", METHOD(i_click),
- 0, 0
- };
- Button = defclass("Button", Responder, 1, 0, 0, 0, _i_messages);
- }
click
affiche un message de trace puis notifie le message clicked.
Une instance de Action répond à clicked :
- class Action;
- static int i_clicked0(instance self, va_list va) {
- instance sender = va_arg(va, instance);
- printf("%s", (char *)sendmsg(self, "toString").p);
- printf(" clicked from ");
- printf("%s", (char *)sendmsg(sender, "toString").p);
- printf("\n");
- return 0;
- }
- void defclassAction() {
- selector _i_messages[] = {
- "clicked", METHOD(i_clicked0),
- 0, 0
- };
- Action = defclass("Action", Responder, 1, 0, 0, 0, _i_messages);
- }
clicked0
affiche le receveur et l'envoyeur de la notification.
Une instance de anotherAction répond à clicked :
- class AnotherAction;
- static int i_clicked1(instance self, va_list va) {
- instance sender = va_arg(va, instance);
- printf("%s", (char *)sendmsg(self, "toString").p);
- printf(" clicked from ");
- printf("%s", (char *)sendmsg(sender, "toString").p);
- printf("\n");
- return 1;
- }
- void defclassAnotherAction() {
- selector _i_messages[] = {
- "clicked", METHOD(i_clicked1),
- 0, 0
- };
- AnotherAction = defclass("AnotherAction", Responder, 1, 0, 0, 0, _i_messages);
- }
clicked1
affiche le receveur et l'envoyeur de la notification.
- int main( int argc, char *argv[] ) {
- defclassResponder();
- defclassButton();
- defclassAction();
- instance button = (instance)sendmsg(Button, "new").p;
- sendmsg(button, "click");
- instance action = (instance)sendmsg(Action, "new").p;
- sendmsg(button, "addNextResponder", action);
- sendmsg(button, "click");
- defclassAnotherAction();
- instance anotheraction = (instance)sendmsg(AnotherAction, "new").p;
- sendmsg(button, "addNextResponder", anotheraction);
- sendmsg(button, "click");
- sendmsg(button, "removeNextResponder", anotheraction);
- sendmsg(button, "click");
- sendmsg(action, "addNextResponder", anotheraction);
- sendmsg(button, "click");
- sendmsg(button, "removeNextResponder", action);
- sendmsg(action, "removeNextResponder", anotheraction);
- sendmsg(button, "addNextResponder", anotheraction);
- sendmsg(anotheraction, "addNextResponder", action);
- sendmsg(button, "click");
- exit( 0 );
- }
Construit les classes Responder, Button et Action.
Crée une instance de Button et la clique.
Crée une instance de Action et l'ajoute comme répondeur à l'instance de Button. Clique l'instance de Button.
Crée une instance de AnotherAction et l'ajoute comme répondeur à l'instance de Button. Clique l'instance de Button.
Retire l'instance de AnotherAction de la liste des répondeurs de l'instance de Button. Clique l'instance de Button.
Ajoute l'instance de AnotherAction à la liste des répondeurs de l'instance de Action. Clique l'instance de Button.
Retire l'instance d'Action de la liste des répondeurs de l'instance de Button. Retire l'instance de AnotherAction de la liste des répondeurs de l'instance de Action. Ajoute l'instance de AnotherAction à la liste des répondeurs de l'instance de Button. Ajoute l'instance de Action à la liste des répondeurs de l'instance de AnotherAction. Clique l'instance de Button.
$ gcc -I/usr/local/include/so-o -O -c test-Responder.c
$ gcc test-Responder.o -lso-o -o test-Responder
$ test-Responder
object(Button) click
object(Button) click
object(Action) clicked from object(Button)
object(Button) click
object(Action) clicked from object(Button)
object(AnotherAction) clicked from object(Button)
object(Button) click
object(Action) clicked from object(Button)
object(Button) click
object(Action) clicked from object(Button)
object(AnotherAction) clicked from object(Button)
object(Button) click
object(AnotherAction) clicked from object(Button)
Commentaires