NAME

Rui::Event::Listenable - base class for listenable objects


SYNOPSIS

  # subclassing
  package Car;
  use base qw(Rui::Event::Listenable);
  ...
  sub openFrontLeftDoor {
     ...
     # DoorOpened is an  event class  
     $self->fireEvent(DoorOpened->new(
        name   => 'FrontLeftDoorOpened',
        source => $self,
        time   => time,
     ));
  }
  ...
  # using
  $car = Car->new(events => {     
     FrontLeftDoorOpened => sub {print shift->time}, # 1st param is event
     FrontLeftDoorClosed => sub {print shift->time},
  });
  $car->addListener(FrontLeftDoorOpened => $listener = sub { 
     my $event = shift;
     print 'name:'. $event->name. ' source:'. $event->source;
  });
  $car->removeListener($listener);
 
  $car->addListener(FrontLeftDoorOpened => $listener = MyListener->new);
  $car->removeListener($listener);
 
  $car->addListener( FrontLeftDoorClosed =>
     [CalledWhenDoorOpened => $listener = MyListener->new]
  );
  $car->removeListener($listener);
  
  # listening
  package MyListener;
  ...
  sub handleEvent_FrontLeftDoorOpened {
     my ($self, $event) = @_;
     ...
  }
  sub CalledWhenDoorClosed {
     my ($self, $event) = @_;
     ...
  }


REQUIRES

the Rui::Event manpage


DESCRIPTION

An implementation of the observer pattern. Listenable objects fire events: different events are fired by different objects. For each event a name and a class are defined. For example: A car class defines an event with a name FrontLeftDoorOpened, and an event class CarSoftware::Event::DoorOpened. The event name is used as the key when adding and removing listeners, and as a hint when the listener needs to find a listener method.

You interface with a listenable object by adding and removing listeners. Listeners are called when an event is fired, with a the Rui::Event manpage as the only parameter.

A listener is a DWIMer and can be one of the following:

  1. callback - code ref to be called

  2. object - the method handleEvent_eventName will be called

  3. array ref with two elements- scalar method name, object

When the listener is an object (listener type 2), the method name to be called is computed from the event name by adding handleEvent_ in front of the event name. For example: a car object will call the method handleEvent_FrontLeftDoorOpened on its listeners that are objects.

When the listener is an array ref (listener type 3), the method name (1st element) is called on the object (2nd element). When removing this type of listener, you do not remove the array ref but the listener object, i.e. exactly like you remove a type 2 listeners.


SUBCLASSING

For implementing listenable functionality, all you need to do is call $self->fireEvent($event) to fire an event. You can also override add/removeListener() to modify events fired by your class.

A listenable also features support for creating listener classes, thus making it possible to create a listenable that is also a listener (as most are). These classes may listen to several events on several listenables. They will want to attach to all of them when created, and attach/detach when specific listenables added or removed. The framework helps you so:

  1. The default implementations of attach()/detach() makes or breaks all connections to the listenables that you specify with the template method explained below. attach() is called by the framework when you create your object, detach() when you destroy it. It is up to you to call them when the listenables are replaced, to give the framework a chance to attach()/detach. If only one of the listenables is set or removed, you can call attachTo()/detachFrom() with one parameter: the name of listenable.

    If you want to use the default attach()/detach() methods, you need to provide one template method: getAttachments(). The results will be used to determine the attachments of this listener to listenable objects. You must return a hash ref of listenable names. For each name you provide a hash ref of event names that interest you on that listenable, and for each event name an event handler name on your object.

    Here is an example of a car listening to its parts: the door and the sun roof:

      sub getAttachments : Protected
      {
         my $self = shift;
         return {
            door            => {
               Open         => 'StateChange',
               Close        => 'StateChange',
            }
            $self->hasSunRoof? (
               sunRoof      => {
                  Open      => 'Open',
                  Close     => 'Close',
               }
            ): ()
         };
      }

    The car listens to the sun roof only if it has one. The car listens to the Open and Close events of both parts. These will call the following methods of the car: handleEvent_door_StateChanged(), handleEvent_sunRoof_Open(), and handleEvent_sunRoof_Close().

    The framework will attach/detach automatically when your listener object is created and destroyed. However you must call attachTo()/detachFrom() when a door is being replaced with a new one, or when changing the sun roof.

    You must provide a getter for each listenable name in getAttachments(), so that the framework can find the listenable by name. Thus in the above example you would need to provide the methods door(), and sunRoof(), that return the named listenables.

  2. You can override the default attachment methods if they are not right for you. the Rui::Model::List manpage, for example, may need to attach to all its children. This is difficult to specify using getAttachments(), so it overrides attach()/detach(), and implements its own mechanism, without using getAttachments().


METHODS

CONSTRUCTING

new

parameters
Hash of named parameters. Keys/values defined here:

events - Optional. Hash ref. keys are event names, values are listeners.

LISTENING

addListener

parameters
eventName - Scalar. What is the name of the event that interests me?

listener - callback, object, or method/object pair.

returns
Self.

description
Add a listener to the event name specified. The listener will be called with event as only parameter.

removeListener

parameters
eventName - Scalar. What is the name of the event that interests me?

listener - callback, object, or method/object pair.

returns
Self.

description
Remove a listener for the named event. Throws exception if listener not found.