tableRuntimeLocalEventDispatcher

I'd like to solicit feedback about this "tableRuntimeLocalEventDispatcher()" (code attached), which tries to solve the following problem:

When you have a system event like "enterFrame", then you can either register a event handler with the Runtime target that then gets called but doesn't have any context to any object. Or you can use a table event handler, which is attached to the object's table and a self parameter value will give you its reference, or you can use a closure where you wrap the object inside of an normal event handler function. The advantage of the last two are that you have the event handler running within the context of an object without the need for global variables, which is a very common use case.

The disadvantage of the table-event handlers are that you can only install a single one at the event-name slot of the object-table. This is a big limitation if you want to modularize your app and have multiple event handlers taking care of different aspects of the object's behavior.

The closure approach works well, but then you need a factory-function that wraps the object in a closure. It will make a new function instance for each object, which makes it almost impossible to identify those handlers by name because they get created during runtime - just one indirection too many.

The alternative I came up with is different, and I haven't seen it before, which makes me a little nervous. The idea is to use a generic table-event-handler, which simply and only forwards/dispatches, for example, the "enterFrame" events to the object itself. This allows you to write normal multiple "enterFrame" event handlers and register those with the object itself. The table-event-handler gets registered with Runtime for "enterFrame" events, and before forwarding the event on, it adds an event.target property that points to self such that the local event handler can find its local context.

It seems like a trick and costs one extra indirection, but it also seems to work well; you can have multiple "enterFrame" local event handlers registered with an object without a problem, and all handlers can easily be "named" such that we can wire them up thru Tiled-property-values.

Note that this trick is not necessary for "collision" events as you already can register those locally...unfortunately for Runtime's "enterFrame" events we do not seem to be that lucky.

Please take a look and let me know whether there are easier, maybe a little less contrived ways to do this.

Thanks, Frank.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
-------------------------------------------------------------------------------
--- Generic system table-event to local object event dispatcher.
-- A table-event handler that assigns the object-self to the event.target and
-- then redispatches to the object itself. In that way, we can have mutiple
-- system event handlers that are local to an object as the table-mechanism
-- only allows us to register a single system event handler with an object.
-- Usage for "enterFrame" events with a display object "anObject": 
-- anObject[enterFrame] = NamedEventHandlers.tableRuntimeLocalEventDispatcher
-- Then register object-table event handler with Runtime like:
-- Runtime:addEventListener( "enterFrame", anObject ).
-- This table-event-handler will then forward "enterFrame" event to registered
-- object's event handlers like for example "myEnterFrameHandler(event)", which
-- has been registered like:
-- anObject:addEventListener("enterFrame", myEnterFrameHandler)
NamedEventHandlers.tableRuntimeLocalEventDispatcher = function(self, event)
        if (not self.dispatchEvent) then 
                -- poor-man's test for display object existence
                -- if we're here, then only skeleton object exists and we should clean-up
                Runtime:removeEventListener( event.name, self )
                return true 
        else
                -- dispatch event to object itself
                -- copy as we cannot annotate and reuse the event table as bad things will happen
                local event2 = {}
                for k,v in pairs(event)do event2[k]=v end
                -- add self as the target such that the handler can find the self-state
                event2.target = self
                self:dispatchEvent(event2)
                return false
        end
end

Hey Frank, both this and your NamedObjects look great ( sorry I've been very late in replying to both, freelance stuff got in the way again ) however as they are non-lime specific would they not deserve a bit more exposure i.e. posted in the general forums? Don't get me wrong, I'm naturally fine and happy for them to be here, just thinking there will only be other Lime users that see them here whereas in the main forums everyone will do. Just a thought.

views:1548 update:2011/10/13 16:30:09
corona forums © 2003-2011