26

Responder

  1. Object
    1. Responder

A Responder instance automatically sends notification messages to one or several instances. Responder instances can be linked so notifications are automatically transmitted from one responder to another.

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

Loads the declarations of the data types and functions of So-o. Defines the class 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. }

Defines defclassResponder, the constructeur of the class Responder.

The Responder class inherits from the Object class. The instance property nextResponders holds the list of instances which have asked to be notified when an event occurs. The Responder class adds the instance messages addNextResponder, removeNextResponder and respondTo.

INSTANCE METHODS

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. }

Extracts the instance r from the argument list va. Gets the list of responders of self. If the list is NULL, creates a new list and saves it then adds r to the list. If the list isn't NULL, adds r to it if r isn't already in the list.

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. }

Extracts the instance r from the argument list va. Gets the list of responders of self. If the list isn't NULL, looks for the index of r in the list and if the index isn't -1, removes r from the list.

respondTo
SYNOPSIS

instance respondTo(instance self, message msg[, arg ...])

DESCRIPTION

If self responds to msg, respondTo sends msg and its parameters to self. If self doesn't respond to msg or if the execution of the message returns NULL, respondTo transmits the message and its parameters to all the instances of the list of responders of 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. }

Makes a copy of the list of arguments va in vac. Extracts the message msg from the copy. If self responds to msg, sends it msg with vac. If the execution of the message doesn't return NULL, frees vac and returns self. If self doesn't respond to msg or if the execution of the message by self returns NULL, frees vac and transmits msg with va to all the responders of self.

EXAMPLE

An instance of Button notifies the message clicked when it receives the 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 displays a trace message then notifies the message clicked.

An instance of Action responds to 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 displays the receiver and the sender of the notification.

An instance of AnotherAction also responds to 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 displays the receiver and the sender of the nofification.

  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. }

Builds the classes Responder, Button and Action.

Creates an instance of Button and clicks it.

Creates an instance of Action and adds it as a responder to the instance of Button. Clicks the instance of Button.

Creates an instance of AnotherAction and adds it as a responder to the instance of Button. Clicks the instance of Button.

Removes the instance of AnotherAction from the list of responders of the instance of Button. Clicks the instance of Button.

Adds the instance of AnotherAction to the list of responders of the instance of Action. Clicks the instance of Button.

Removes the instance of Action from the list of responders of the instance of Button. Removes the instance of AnotherAction from the list of responders of the instance of Action. Adds the instance of AnotherAction to the list of responders of the instance of Button. Adds the instance of Action to the list of responders of the instance of AnotherAction. Clicks the instance of 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)
SEE ALSO

Application

Comments

Your comment:
[p] [b] [i] [u] [s] [quote] [pre] [br] [code] [url] [email] strip help 2000

Enter a maximum of 2000 characters.
Improve the presentation of your text with the following formatting tags:
[p]paragraph[/p], [b]bold[/b], [i]italics[/i], [u]underline[/u], [s]strike[/s], [quote]citation[/quote], [pre]as is[/pre], [br]line break,
[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]command[/code], [code=language]source code in c, java, php, html, javascript, xml, css, sql, bash, dos, make, etc.[/code].