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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
local ipairs = ipairs;
local pairs = pairs;
local t_insert = table.insert;
local t_sort = table.sort;
local select = select;
module "events"
function new()
local dispatchers = {};
local handlers = {};
local event_map = {};
local function _rebuild_index(event) -- TODO optimize index rebuilding
local _handlers = event_map[event];
local index = handlers[event];
if index then
for i=#index,1,-1 do index[i] = nil; end
else index = {}; handlers[event] = index; end
for handler in pairs(_handlers) do
t_insert(index, handler);
end
t_sort(index, function(a, b) return _handlers[a] > _handlers[b]; end);
end;
local function add_handler(event, handler, priority)
local map = event_map[event];
if map then
map[handler] = priority or 0;
else
map = {[handler] = priority or 0};
event_map[event] = map;
end
_rebuild_index(event);
end;
local function remove_handler(event, handler)
local map = event_map[event];
if map then
map[handler] = nil;
_rebuild_index(event);
end
end;
local function add_plugin(plugin)
for event, handler in pairs(plugin) do
add_handler(event, handler);
end
end;
local function remove_plugin(plugin)
for event, handler in pairs(plugin) do
remove_handler(event, handler);
end
end;
local function _create_dispatcher(event) -- FIXME duplicate code in fire_event
local h = handlers[event];
if not h then h = {}; handlers[event] = h; end
local dispatcher = function(data)
for _, handler in ipairs(h) do
local ret = handler(data);
if ret ~= nil then return ret; end
end
end;
dispatchers[event] = dispatcher;
return dispatcher;
end;
local function get_dispatcher(event)
return dispatchers[event] or _create_dispatcher(event);
end;
local function fire_event(event, data) -- FIXME duplicates dispatcher code
local h = handlers[event];
if h then
for _, handler in ipairs(h) do
local ret = handler(data);
if ret ~= nil then return ret; end
end
end
end;
local function get_named_arg_dispatcher(event, ...)
local dispatcher = get_dispatcher(event);
local keys = {...};
local data = {};
return function(...)
for i, key in ipairs(keys) do data[key] = select(i, ...); end
dispatcher(data);
end;
end;
return {
add_handler = add_handler;
remove_handler = remove_handler;
add_plugin = add_plugin;
remove_plugin = remove_plugin;
get_dispatcher = get_dispatcher;
fire_event = fire_event;
get_named_arg_dispatcher = get_named_arg_dispatcher;
_dispatchers = dispatchers;
_handlers = handlers;
_event_map = event_map;
};
end
return _M;
|