Responder
- Object
- 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.
- #include "So-o.h"
- class Responder;
Loads the declarations of the data types and functions of So-o. Defines the class 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);
- }
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
- 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;
- }
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
- 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;
- }
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
- 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;
- }
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:
- 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
displays a trace message then notifies the message clicked.
An instance of Action responds to 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
displays the receiver and the sender of the notification.
An instance of AnotherAction also responds to 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
displays the receiver and the sender of the nofification.
- 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 );
- }
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)
Comments