4

Responder

  1. Object
    1. 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.

  1. #include "So-o.h"
  2.  
  3. class Responder;

Charge les déclarations des types de données et des fonctions de So-o. Définit la classe Responder.

  1. void defclassResponder() {
  2.     property _i_properties[] = {
  3.         "nextResponders",
  4.         0
  5.     };
  6.     selector _i_messages[] = {
  7.         "addNextResponder",     METHOD(i_addNextResponder),
  8.         "removeNextResponder",  METHOD(i_removeNextResponder),
  9.         "respondTo",            METHOD(i_respondTo),
  10.         0, 0
  11.     };
  12.  
  13.     Responder = defclass("Responder", 0, 1, 0, _i_properties, 0, _i_messages);
  14. }

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
  1. static instance i_addNextResponder(instance self, va_list va) {
  2.     instance r = va_arg(va, instance);
  3.  
  4.     list responders = sendmsg(self, "get", "nextResponders").p;
  5.  
  6.     if (!responders)  {
  7.         responders = list_new();
  8.  
  9.         sendmsg(self, "set", "nextResponders", responders);
  10.  
  11.         list_put(responders, -1, r);
  12.     }
  13.     else if (list_find(responders, r, 0) == -1)
  14.         list_put(responders, -1, r);
  15.  
  16.     return self;
  17. }

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
  1. static instance i_removeNextResponder(instance self, va_list va) {
  2.     instance r = va_arg(va, instance);
  3.  
  4.     list responders = sendmsg(self, "get", "nextResponders").p;
  5.  
  6.     if (responders) {
  7.         int i = list_find(responders, r, 0);
  8.  
  9.         if (i != -1)
  10.             list_delete(responders, i);
  11.     }
  12.  
  13.     return self;
  14. }

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
  1. static instance i_respondTo(instance self, va_list va) {
  2.     va_list vac;
  3.  
  4.     va_copy(vac, va);
  5.     message msg = va_arg(vac, message);
  6.  
  7.     if (sendmsg(self, "respondsTo", msg).i && applymsg(self, msg, vac).i) {
  8.         va_end(vac);
  9.         return self;
  10.     }
  11.  
  12.     va_end(vac);
  13.  
  14.     list responders = sendmsg(self, "get", "nextResponders").p;
  15.  
  16.     if (responders) {
  17.         for (int i = 0; i < list_length(responders); i++) {
  18.             va_copy(vac, va);
  19.             applymsg(list_get(responders, i), "respondTo", vac);
  20.             va_end(vac);
  21.         }
  22.     }
  23.  
  24.     return self;
  25. }

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 :

  1. class Button;
  2.  
  3. static instance i_click(instance self) {
  4.     printf("%s click\n", (char *)sendmsg(self, "toString").p);
  5.  
  6.     sendmsg(self, "respondTo", "clicked", self);
  7.  
  8.     return self;
  9. }
  10.  
  11. void defclassButton() {
  12.     selector _i_messages[] = {
  13.         "click",    METHOD(i_click),
  14.         0, 0
  15.     };
  16.  
  17.     Button = defclass("Button", Responder, 1, 0, 0, 0, _i_messages);
  18. }

click affiche un message de trace puis notifie le message clicked.

Une instance de Action répond à clicked :

  1. class Action;
  2.  
  3. static int i_clicked0(instance self, va_list va) {
  4.     instance sender = va_arg(va, instance);
  5.  
  6.     printf("%s", (char *)sendmsg(self, "toString").p);
  7.     printf(" clicked from ");
  8.     printf("%s", (char *)sendmsg(sender, "toString").p);
  9.     printf("\n");
  10.  
  11.     return 0;
  12. }
  13.  
  14. void defclassAction() {
  15.     selector _i_messages[] = {
  16.         "clicked",  METHOD(i_clicked0),
  17.         0, 0
  18.     };
  19.  
  20.     Action = defclass("Action", Responder, 1, 0, 0, 0, _i_messages);
  21. }

clicked0 affiche le receveur et l'envoyeur de la notification.

Une instance de anotherAction répond à clicked :

  1. class AnotherAction;
  2.  
  3. static int i_clicked1(instance self, va_list va) {
  4.     instance sender = va_arg(va, instance);
  5.  
  6.     printf("%s", (char *)sendmsg(self, "toString").p);
  7.     printf(" clicked from ");
  8.     printf("%s", (char *)sendmsg(sender, "toString").p);
  9.     printf("\n");
  10.  
  11.     return 1;
  12. }
  13.  
  14. void defclassAnotherAction() {
  15.     selector _i_messages[] = {
  16.         "clicked",  METHOD(i_clicked1),
  17.         0, 0
  18.     };
  19.  
  20.     AnotherAction = defclass("AnotherAction", Responder, 1, 0, 0, 0, _i_messages);
  21. }

clicked1 affiche le receveur et l'envoyeur de la notification.

  1. int main( int argc, char *argv[] ) {
  2.     defclassResponder();
  3.  
  4.     defclassButton();
  5.     defclassAction();
  6.  
  7.     instance button = (instance)sendmsg(Button, "new").p;
  8.  
  9.     sendmsg(button, "click");
  10.  
  11.     instance action = (instance)sendmsg(Action, "new").p;
  12.  
  13.     sendmsg(button, "addNextResponder", action);
  14.  
  15.     sendmsg(button, "click");
  16.  
  17.     defclassAnotherAction();
  18.  
  19.     instance anotheraction = (instance)sendmsg(AnotherAction, "new").p;
  20.  
  21.     sendmsg(button, "addNextResponder", anotheraction);
  22.  
  23.     sendmsg(button, "click");
  24.  
  25.     sendmsg(button, "removeNextResponder", anotheraction);
  26.  
  27.     sendmsg(button, "click");
  28.  
  29.     sendmsg(action, "addNextResponder", anotheraction);
  30.  
  31.     sendmsg(button, "click");
  32.  
  33.     sendmsg(button, "removeNextResponder", action);
  34.     sendmsg(action, "removeNextResponder", anotheraction);
  35.  
  36.     sendmsg(button, "addNextResponder", anotheraction);
  37.     sendmsg(anotheraction, "addNextResponder", action);
  38.  
  39.     sendmsg(button, "click");
  40.  
  41.     exit( 0 );
  42. }

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)
VOIR AUSSI

Application

Commentaires

Votre commentaire :
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip aide 2000

Entrez un maximum de 2000 caractères.
Améliorez la présentation de votre texte avec les balises de formatage suivantes :
[p]paragraphe[/p], [b]gras[/b], [i]italique[/i], [u]souligné[/u], [s]barré[/s], [quote]citation[/quote], [pre]tel quel[/pre], [br]à la ligne,
[url]http://www.izend.org[/url], [url=http://www.izend.org]site[/url], [email]izend@izend.org[/email], [email=izend@izend.org]izend[/email],
[code]commande[/code], [code=langage]code source en c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].