Added: util/events.lua: An event handling library
authorWaqas Hussain <waqas20@gmail.com>
Sun, 29 Mar 2009 22:58:59 +0000 (03:58 +0500)
committerWaqas Hussain <waqas20@gmail.com>
Sun, 29 Mar 2009 22:58:59 +0000 (03:58 +0500)
util/events.lua [new file with mode: 0644]

diff --git a/util/events.lua b/util/events.lua
new file mode 100644 (file)
index 0000000..b1f3811
--- /dev/null
@@ -0,0 +1,96 @@
+\r
+local ipairs = ipairs;\r
+local pairs = pairs;\r
+local t_insert = table.insert;\r
+local select = select;\r
+\r
+module "events"\r
+\r
+function new()\r
+       local dispatchers = {};\r
+       local handlers = {};\r
+       local event_map = {};\r
+       local function _rebuild_index() -- TODO optimize index rebuilding\r
+               for event, _handlers in pairs(event_map) do\r
+                       local index = handlers[event];\r
+                       if index then\r
+                               for i=#index,1,-1 do index[i] = nil; end\r
+                       else index = {}; handlers[event] = index; end\r
+                       for handler in pairs(_handlers) do\r
+                               t_insert(index, handler);\r
+                       end\r
+               end\r
+       end;\r
+       local function add_handler(event, handler)\r
+               local map = event_map[event];\r
+               if map then\r
+                       map[handler] = true;\r
+               else\r
+                       map = {[handler] = true};\r
+                       event_map[event] = map;\r
+               end\r
+               _rebuild_index();\r
+       end;\r
+       local function remove_handler(event, handler)\r
+               local map = event_map[event];\r
+               if map then\r
+                       map[handler] = nil;\r
+                       _rebuild_index();\r
+               end\r
+       end;\r
+       local function add_plugin(plugin)\r
+               for event, handler in pairs(plugin) do\r
+                       add_handler(event, handler);\r
+               end\r
+       end;\r
+       local function remove_plugin(plugin)\r
+               for event, handler in pairs(plugin) do\r
+                       remove_handler(event, handler);\r
+               end\r
+       end;\r
+       local function _create_dispatcher(event) -- FIXME duplicate code in fire_event\r
+               local h = handlers[event];\r
+               if not h then h = {}; handlers[event] = h; end\r
+               local dispatcher = function(data)\r
+                       for _, handler in ipairs(h) do\r
+                               handler(data);\r
+                       end\r
+               end;\r
+               dispatchers[event] = dispatcher;\r
+               return dispatcher;\r
+       end;\r
+       local function get_dispatcher(event)\r
+               return dispatchers[event] or _create_dispatcher(event);\r
+       end;\r
+       local function fire_event(event, data) -- FIXME duplicates dispatcher code\r
+               local h = handlers[event];\r
+               if h then\r
+                       for _, handler in ipairs(h) do\r
+                               handler(data);\r
+                       end\r
+               end\r
+       end;\r
+       local function get_named_arg_dispatcher(event, ...)\r
+               local dispatcher = get_dispatcher(event);\r
+               local keys = {...};\r
+               local data = {};\r
+               return function(...)\r
+                       for i, key in ipairs(keys) do data[key] = select(i, ...); end\r
+                       dispatcher(data);\r
+               end;\r
+       end;\r
+       return {\r
+               add_handler = add_handler;\r
+               remove_handler = remove_handler;\r
+               add_plugin = add_plugin;\r
+               remove_plugin = remove_plugin;\r
+               get_dispatcher = get_dispatcher;\r
+               fire_event = fire_event;\r
+               get_named_arg_dispatcher = get_named_arg_dispatcher;\r
+               _dispatchers = dispatchers;\r
+               _handlers = handlers;\r
+               _event_map = event_map;\r
+       };\r
+end\r
+\r
+return _M;\r