comparison util/events.lua @ 6638:9d2b56fd6b47

util.events: Add support for event wrappers, functions which can wrap the calling of event handlers to run code before/after an event (for debugging, statistics, logging purposes, etc.)
author Matthew Wild <mwild1@gmail.com>
date Tue, 28 Apr 2015 13:42:59 +0100
parents bd0ff8ae98a8
children b44ebfe81c73
comparison
equal deleted inserted replaced
6637:ecc039288edc 6638:9d2b56fd6b47
15 15
16 module "events" 16 module "events"
17 17
18 function new() 18 function new()
19 local handlers = {}; 19 local handlers = {};
20 local global_wrappers;
21 local wrappers = {};
20 local event_map = {}; 22 local event_map = {};
21 local function _rebuild_index(handlers, event) 23 local function _rebuild_index(handlers, event)
22 local _handlers = event_map[event]; 24 local _handlers = event_map[event];
23 if not _handlers or next(_handlers) == nil then return; end 25 if not _handlers or next(_handlers) == nil then return; end
24 local index = {}; 26 local index = {};
58 local function remove_handlers(handlers) 60 local function remove_handlers(handlers)
59 for event, handler in pairs(handlers) do 61 for event, handler in pairs(handlers) do
60 remove_handler(event, handler); 62 remove_handler(event, handler);
61 end 63 end
62 end; 64 end;
63 local function fire_event(event_name, event_data) 65 local function _fire_event(event_name, event_data)
64 local h = handlers[event_name]; 66 local h = handlers[event_name];
65 if h then 67 if h then
66 for i=1,#h do 68 for i=1,#h do
67 local ret = h[i](event_data); 69 local ret = h[i](event_data);
68 if ret ~= nil then return ret; end 70 if ret ~= nil then return ret; end
69 end 71 end
70 end 72 end
71 end; 73 end;
74 local function fire_event(event_name, event_data)
75 local w = wrappers[event_name] or global_wrappers;
76 if w then
77 local curr_wrapper = #w;
78 local function c(event_name, event_data)
79 curr_wrapper = curr_wrapper - 1;
80 if curr_wrapper == 0 then
81 if global_wrappers == nil or w == global_wrappers then
82 return _fire_event(event_name, event_data);
83 end
84 w, curr_wrapper = global_wrappers, #global_wrappers;
85 return w[curr_wrapper](c, event_name, event_data);
86 else
87 return w[curr_wrapper](c, event_name, event_data);
88 end
89 end
90 return w[curr_wrapper](c, event_name, event_data);
91 end
92 return _fire_event(event_name, event_data);
93 end
94 local function add_wrapper(event_name, wrapper)
95 local w;
96 if event_name == nil then
97 w = global_wrappers;
98 if not w then
99 w = {};
100 global_wrappers = w;
101 end
102 else
103 w = wrappers[event_name];
104 if not w then
105 w = {};
106 wrappers[event_name] = w;
107 end
108 end
109 w[#w+1] = wrapper;
110 end
111 local function remove_wrapper(event_name, wrapper)
112 local w;
113 if event_name == nil then
114 w = global_wrappers;
115 else
116 w = wrappers[event_name];
117 end
118 if not w then return; end
119 for i = #w, 1 do
120 if w[i] == wrapper then
121 table.remove(w, i);
122 end
123 end
124 if #w == 0 then
125 if event_name == nil then
126 global_wrappers = nil;
127 else
128 wrappers[event_name] = nil;
129 end
130 end
131 end
72 return { 132 return {
73 add_handler = add_handler; 133 add_handler = add_handler;
74 remove_handler = remove_handler; 134 remove_handler = remove_handler;
75 add_handlers = add_handlers; 135 add_handlers = add_handlers;
76 remove_handlers = remove_handlers; 136 remove_handlers = remove_handlers;
137 wrappers = {
138 add_handler = add_wrapper;
139 remove_handler = remove_wrapper;
140 };
141 add_wrapper = add_wrapper;
142 remove_wrapper = remove_wrapper;
77 fire_event = fire_event; 143 fire_event = fire_event;
78 _handlers = handlers; 144 _handlers = handlers;
79 _event_map = event_map; 145 _event_map = event_map;
80 }; 146 };
81 end 147 end