2 -- Copyright (C) 2008-2010 Matthew Wild
3 -- Copyright (C) 2008-2010 Waqas Hussain
5 -- This project is MIT/X11 licensed. Please see the
6 -- COPYING file in the source package for more information.
11 local t_insert = table.insert;
12 local t_remove = table.remove;
13 local t_sort = table.sort;
14 local setmetatable = setmetatable;
20 -- Map event name to ordered list of handlers (lazily built): handlers[event_name] = array_of_handler_functions
22 -- Array of wrapper functions that wrap all events (nil if empty)
23 local global_wrappers;
24 -- Per-event wrappers: wrappers[event_name] = wrapper_function
26 -- Event map: event_map[handler_function] = priority_number
28 -- Called on-demand to build handlers entries
29 local function _rebuild_index(handlers, event)
30 local _handlers = event_map[event];
31 if not _handlers or next(_handlers) == nil then return; end
33 for handler in pairs(_handlers) do
34 t_insert(index, handler);
36 t_sort(index, function(a, b) return _handlers[a] > _handlers[b]; end);
37 handlers[event] = index;
40 setmetatable(handlers, { __index = _rebuild_index });
41 local function add_handler(event, handler, priority)
42 local map = event_map[event];
44 map[handler] = priority or 0;
46 map = {[handler] = priority or 0};
47 event_map[event] = map;
49 handlers[event] = nil;
51 local function remove_handler(event, handler)
52 local map = event_map[event];
55 handlers[event] = nil;
56 if next(map) == nil then
57 event_map[event] = nil;
61 local function get_handlers(event)
62 return handlers[event];
64 local function add_handlers(handlers)
65 for event, handler in pairs(handlers) do
66 add_handler(event, handler);
69 local function remove_handlers(handlers)
70 for event, handler in pairs(handlers) do
71 remove_handler(event, handler);
74 local function _fire_event(event_name, event_data)
75 local h = handlers[event_name];
78 local ret = h[i](event_data);
79 if ret ~= nil then return ret; end
83 local function fire_event(event_name, event_data)
84 local w = wrappers[event_name] or global_wrappers;
86 local curr_wrapper = #w;
87 local function c(event_name, event_data)
88 curr_wrapper = curr_wrapper - 1;
89 if curr_wrapper == 0 then
90 if global_wrappers == nil or w == global_wrappers then
91 return _fire_event(event_name, event_data);
93 w, curr_wrapper = global_wrappers, #global_wrappers;
94 return w[curr_wrapper](c, event_name, event_data);
96 return w[curr_wrapper](c, event_name, event_data);
99 return w[curr_wrapper](c, event_name, event_data);
101 return _fire_event(event_name, event_data);
103 local function add_wrapper(event_name, wrapper)
105 if event_name == false then
112 w = wrappers[event_name];
115 wrappers[event_name] = w;
120 local function remove_wrapper(event_name, wrapper)
122 if event_name == false then
125 w = wrappers[event_name];
127 if not w then return; end
129 if w[i] == wrapper then
134 if event_name == nil then
135 global_wrappers = nil;
137 wrappers[event_name] = nil;
142 add_handler = add_handler;
143 remove_handler = remove_handler;
144 add_handlers = add_handlers;
145 remove_handlers = remove_handlers;
146 get_handlers = get_handlers;
148 add_handler = add_wrapper;
149 remove_handler = remove_wrapper;
151 add_wrapper = add_wrapper;
152 remove_wrapper = remove_wrapper;
153 fire_event = fire_event;
154 _handlers = handlers;
155 _event_map = event_map;