ooRexx logo
../code/eventable.cls/var/www/html/ooRexx/wip /* --------------------------------------------------------------------------------------- */ /* No freakin' copyright, no stinkin' license, no guarantees or warranties */ /* (implied, explicit or whatever). Usage is totally and completely at your own risk. */ /* Please keep this comment block as is when modifying this code. Thanks in advance, */ /* Ruurd Idenburg */ /* --------------------------------------------------------------------------------------- */ /** The eventable class is a mixin class, that can be used in the inheriting class to define events (by name) and trigger those events so that other classes may act upon those events.

Events are defined as indexes in an events directory. The events directory is created in the events instance init method and is therefore available after the inheriting class instance creation has called it's super class init method, so the logical thing to do is to define the class instance events in the inheriting class init method for new instances. However events can also be defined later on by the inheriting class instance methods.

Event handlers/listeners need to define an instance method with the name of the defined event. That method will be invoked by the triggering of the event. The handler/listener method should return the boolean .true or .false depending on whether possible other handlers/listeners should be given the opportunity to act on the event. Returning .false will allow other handlers/listeners to be invoked as well, returning .true will stop invoking other handlers/listeners.

Handlers/Listeners are kept as members of an array that is the item in the directory entry for the index that has the name of the event. */ ::class eventable public mixinclass object /** The events attribute is a directory, whose entries can only be set privately by the inheriting class instance methods. The directory is created in the init instance method of this (the events) class. */ ::attribute events get ::attribute events set private /** The init method creates the directory that will have the event names as indexes and the array of handlers/listeners as items.
@param eventArray=(.array~new) - optional, an array of event names provided by the inheriting class

If an array with event names is provided, the entries are created in the events directory with empty arrays as items to hold future handlers/listeners. */ ::method init expose events use strict arg eventArray=(.array~new) events = .directory~new if eventArray~class~id==.array then do do a over eventArray events[a] = .array~new end end /** addEventHander is a synonym for addEventListener
@see #addEventListener */ ::method addEventHandler use strict arg event, handler self~addEventListener(event, handler) /** Adds an object to the group of interested parties
@param event - the name of an event @param listener - the object interested in that event

If the array of handlers/listeners does not exist yet for the event it will be created. The handler/listener object is appended to the existing or new array

It is not verified if the event is a valid event for the object, the result for that condition will be that the handler/listener will never be invoked.

The same handler/listener can be added multiple times, if for some reason that would be necessary for proper functioning and provided some earlier handler/listener did not return .true. */ ::method addEventListener expose events --trace i use strict arg event, listener if events[event]==.nil then do events[event] = .array~new end events[event]~append(listener) /** removeEventHandler is a synonym for removeEventListener
@see #removeEventListener */ ::method removeEventHandler use strict arg event, handler self~removeEventListener(event, handler) /** Removes a party from the group interested in an event
@param event - the name of an event @param listener - the handler/listener object to be removed

If the event is not known, the object can not be removed obviously
If the listener is not a member of the interested handlers/listeners, nothing can be removed.
The handlers/listeners will be regenerated to prevent sparseness. */ ::method removeEventListener expose events --trace i use strict arg event, listener if events[event]~class~id==.array then do events[event]~removeItem(listener) events[event] = events[event]~makeArray end /** Returns the list of defined events for the object
@return anArray - an array of event names for the object

The array can be empty if no events have been defined */ ::method eventNames use strict arg return self~events~makeArray /** eventHandlers is a synonym for eventListeners
@see #eventListeners */ ::method eventHandlers use strict arg event return self~eventListeners(event) /** Returns an array of handlers/listeners for an event.
@param event - the name of an event @return anArray - an array of handlers/listeners for an event

The returned array can be empty if there are no listeners for the event or if the event is unknown. */ ::method eventListeners expose events use strict arg event if events[event]~isA(.array) then return events[event] return .array~new /** Invokes the event handling method in the handlers/listeners for an event while successive handlers/listeners return .false, and stops to invoke following handlers/listeners on the first .true return.
@expose events - the directory of triggerable events for the class @param event - the name of the event to be handled @param args=(.array~new) - optional arguments for the handler method

*/ ::method triggerEvent expose events --trace i use strict arg event, args=(.array~new) if events[event]==.nil then do --.error~lineout('Event:' event 'is not defined') return end if events[event]~items==0 then do --.error~lineout('Event:' event 'does not have listeners') return end result = .false do l over events[event] while result==.false if l~hasMethod(event) then do msg = .message~new(l,event,'I',args~makeString('L',',')) --.traceoutput~say(msg~messageName msg~target msg~arguments~makeString('L',',')) msg~send --start result = msg~result end else do --.error~lineout('Event:' event 'is not a defined method in handler/listener:' l) end end

If you feel inclined to make corrections, suggestions etc., please mail me any.
All content © Ruurd Idenburg, 2007–, except where marked otherwise. All rights reserved. This page is primarily for non-commercial use only. The Idenburg website records no personal information and sets no ‘cookies’. This site is hosted on a VPS(Virtual Private System) rented from Transip.nl, a Dutch company, falling under Dutch (privacy) laws (I think).

This page updated on by Ruurd Idenburg.