Mercurial > wow > reaction
comparison modules/FuBar_ReActionFu/lib/AceEvent-2.0/AceEvent-2.0.lua @ 28:21bcaf8215ff
- converted to Ace3
- rearranged file layout
- configGUI menus not working right now
author | Flick <flickerstreak@gmail.com> |
---|---|
date | Mon, 17 Mar 2008 18:24:53 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
27:f1e838841ce1 | 28:21bcaf8215ff |
---|---|
1 --[[ | |
2 Name: AceEvent-2.0 | |
3 Revision: $Rev: 49307 $ | |
4 Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) | |
5 Inspired By: Ace 1.x by Turan (turan@gryphon.com) | |
6 Website: http://www.wowace.com/ | |
7 Documentation: http://www.wowace.com/index.php/AceEvent-2.0 | |
8 SVN: http://svn.wowace.com/root/trunk/Ace2/AceEvent-2.0 | |
9 Description: Mixin to allow for event handling, scheduling, and inter-addon | |
10 communication. | |
11 Dependencies: AceLibrary, AceOO-2.0 | |
12 License: LGPL v2.1 | |
13 ]] | |
14 | |
15 local MAJOR_VERSION = "AceEvent-2.0" | |
16 local MINOR_VERSION = "$Revision: 49307 $" | |
17 | |
18 if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end | |
19 if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end | |
20 | |
21 if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end | |
22 | |
23 local AceOO = AceLibrary:GetInstance("AceOO-2.0") | |
24 local Mixin = AceOO.Mixin | |
25 local AceEvent = Mixin { | |
26 "RegisterEvent", | |
27 "RegisterAllEvents", | |
28 "UnregisterEvent", | |
29 "UnregisterAllEvents", | |
30 "TriggerEvent", | |
31 "ScheduleEvent", | |
32 "ScheduleRepeatingEvent", | |
33 "CancelScheduledEvent", | |
34 "CancelAllScheduledEvents", | |
35 "IsEventRegistered", | |
36 "IsEventScheduled", | |
37 "RegisterBucketEvent", | |
38 "UnregisterBucketEvent", | |
39 "UnregisterAllBucketEvents", | |
40 "IsBucketEventRegistered", | |
41 "ScheduleLeaveCombatAction", | |
42 "CancelAllCombatSchedules", | |
43 } | |
44 | |
45 local weakKey = {__mode="k"} | |
46 | |
47 local FAKE_NIL | |
48 local RATE | |
49 | |
50 local eventsWhichHappenOnce = { | |
51 PLAYER_LOGIN = true, | |
52 AceEvent_FullyInitialized = true, | |
53 VARIABLES_LOADED = true, | |
54 PLAYER_LOGOUT = true, | |
55 } | |
56 local next = next | |
57 local pairs = pairs | |
58 local pcall = pcall | |
59 local type = type | |
60 local GetTime = GetTime | |
61 local gcinfo = gcinfo | |
62 local unpack = unpack | |
63 local geterrorhandler = geterrorhandler | |
64 | |
65 local build = GetBuildInfo() | |
66 local useTablesAsIDs = build:find("^2%.0%.") or build:find("^2%.1%.") or build:find("^0%.1%.") | |
67 | |
68 local new, del | |
69 do | |
70 local cache = setmetatable({}, {__mode='k'}) | |
71 function new(...) | |
72 local t = next(cache) | |
73 if t then | |
74 cache[t] = nil | |
75 for i = 1, select('#', ...) do | |
76 t[i] = select(i, ...) | |
77 end | |
78 return t | |
79 else | |
80 return { ... } | |
81 end | |
82 end | |
83 function del(t) | |
84 for k in pairs(t) do | |
85 t[k] = nil | |
86 end | |
87 cache[t] = true | |
88 return nil | |
89 end | |
90 end | |
91 | |
92 local registeringFromAceEvent | |
93 --[[---------------------------------------------------------------------------------- | |
94 Notes: | |
95 * Registers the addon with a Blizzard event or a custom AceEvent, which will cause the given method to be called when that is triggered. | |
96 Arguments: | |
97 string - name of the event to register | |
98 [optional] string or function - name of the method or function to call. Default: same name as "event". | |
99 [optional] boolean - whether to have method called only once. Default: false | |
100 ------------------------------------------------------------------------------------]] | |
101 function AceEvent:RegisterEvent(event, method, once) | |
102 AceEvent:argCheck(event, 2, "string") | |
103 if self == AceEvent and not registeringFromAceEvent then | |
104 AceEvent:argCheck(method, 3, "function") | |
105 self = method | |
106 else | |
107 AceEvent:argCheck(method, 3, "string", "function", "nil", "boolean", "number") | |
108 if type(method) == "boolean" or type(method) == "number" then | |
109 AceEvent:argCheck(once, 4, "nil") | |
110 once, method = method, event | |
111 end | |
112 end | |
113 AceEvent:argCheck(once, 4, "number", "boolean", "nil") | |
114 if eventsWhichHappenOnce[event] then | |
115 once = true | |
116 end | |
117 local throttleRate | |
118 if type(once) == "number" then | |
119 throttleRate, once = once | |
120 end | |
121 if not method then | |
122 method = event | |
123 end | |
124 if type(method) == "string" and type(self[method]) ~= "function" then | |
125 AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method) | |
126 else | |
127 assert(type(method) == "function" or type(method) == "string") | |
128 end | |
129 | |
130 local AceEvent_registry = AceEvent.registry | |
131 if not AceEvent_registry[event] then | |
132 AceEvent_registry[event] = new() | |
133 AceEvent.frame:RegisterEvent(event) | |
134 end | |
135 | |
136 local remember = true | |
137 if AceEvent_registry[event][self] then | |
138 remember = false | |
139 end | |
140 AceEvent_registry[event][self] = method | |
141 | |
142 local AceEvent_onceRegistry = AceEvent.onceRegistry | |
143 if once then | |
144 if not AceEvent_onceRegistry then | |
145 AceEvent.onceRegistry = {} | |
146 AceEvent_onceRegistry = AceEvent.onceRegistry | |
147 end | |
148 if not AceEvent_onceRegistry[event] then | |
149 AceEvent_onceRegistry[event] = new() | |
150 end | |
151 AceEvent_onceRegistry[event][self] = true | |
152 else | |
153 if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then | |
154 AceEvent_onceRegistry[event][self] = nil | |
155 if not next(AceEvent_onceRegistry[event]) then | |
156 AceEvent_onceRegistry[event] = del(AceEvent_onceRegistry[event]) | |
157 end | |
158 end | |
159 end | |
160 | |
161 local AceEvent_throttleRegistry = AceEvent.throttleRegistry | |
162 if throttleRate then | |
163 if not AceEvent_throttleRegistry then | |
164 AceEvent.throttleRegistry = {} | |
165 AceEvent_throttleRegistry = AceEvent.throttleRegistry | |
166 end | |
167 if not AceEvent_throttleRegistry[event] then | |
168 AceEvent_throttleRegistry[event] = new() | |
169 end | |
170 if AceEvent_throttleRegistry[event][self] then | |
171 AceEvent_throttleRegistry[event][self] = nil | |
172 end | |
173 AceEvent_throttleRegistry[event][self] = setmetatable(new(), weakKey) | |
174 local t = AceEvent_throttleRegistry[event][self] | |
175 t[RATE] = throttleRate | |
176 else | |
177 if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] then | |
178 if AceEvent_throttleRegistry[event][self] then | |
179 AceEvent_throttleRegistry[event][self] = nil | |
180 end | |
181 if not next(AceEvent_throttleRegistry[event]) then | |
182 AceEvent_throttleRegistry[event] = del(AceEvent_throttleRegistry[event]) | |
183 end | |
184 end | |
185 end | |
186 | |
187 if remember then | |
188 AceEvent:TriggerEvent("AceEvent_EventRegistered", self, event) | |
189 end | |
190 end | |
191 | |
192 local ALL_EVENTS | |
193 | |
194 --[[---------------------------------------------------------------------------------- | |
195 Notes: | |
196 * Registers all events to the given method | |
197 * To access the current event, check AceEvent.currentEvent | |
198 * To access the current event's unique identifier, check AceEvent.currentEventUID | |
199 * This is only for debugging purposes. | |
200 Arguments: | |
201 [optional] string or function - name of the method or function to call. Default: same name as "event". | |
202 ------------------------------------------------------------------------------------]] | |
203 function AceEvent:RegisterAllEvents(method) | |
204 if self == AceEvent then | |
205 AceEvent:argCheck(method, 1, "function") | |
206 self = method | |
207 else | |
208 AceEvent:argCheck(method, 1, "string", "function") | |
209 if type(method) == "string" and type(self[method]) ~= "function" then | |
210 AceEvent:error("Cannot register all events to method %q, it does not exist", method) | |
211 end | |
212 end | |
213 | |
214 local AceEvent_registry = AceEvent.registry | |
215 if not AceEvent_registry[ALL_EVENTS] then | |
216 AceEvent_registry[ALL_EVENTS] = new() | |
217 AceEvent.frame:RegisterAllEvents() | |
218 end | |
219 | |
220 local remember = not AceEvent_registry[ALL_EVENTS][self] | |
221 AceEvent_registry[ALL_EVENTS][self] = method | |
222 if remember then | |
223 AceEvent:TriggerEvent("AceEvent_EventRegistered", self, "all") | |
224 end | |
225 end | |
226 | |
227 --[[---------------------------------------------------------------------------------- | |
228 Notes: | |
229 * Trigger a custom AceEvent. | |
230 * This should never be called to simulate fake Blizzard events. | |
231 * Custom events should be in the form of AddonName_SpecificEvent | |
232 Arguments: | |
233 string - name of the event | |
234 tuple - list of arguments to pass along | |
235 ------------------------------------------------------------------------------------]] | |
236 function AceEvent:TriggerEvent(event, ...) | |
237 if type(event) ~= "string" then | |
238 DEFAULT_CHAT_FRAME:AddMessage(debugstack()) | |
239 end | |
240 AceEvent:argCheck(event, 2, "string") | |
241 local AceEvent_registry = AceEvent.registry | |
242 if (not AceEvent_registry[event] or not next(AceEvent_registry[event])) and (not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS])) then | |
243 return | |
244 end | |
245 local lastEvent = AceEvent.currentEvent | |
246 AceEvent.currentEvent = event | |
247 local lastEventUID = AceEvent.currentEventUID | |
248 local uid = AceEvent.UID_NUM + 1 | |
249 AceEvent.UID_NUM = uid | |
250 AceEvent.currentEventUID = uid | |
251 | |
252 local tmp = new() | |
253 | |
254 local AceEvent_onceRegistry = AceEvent.onceRegistry | |
255 if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then | |
256 for obj, method in pairs(AceEvent_onceRegistry[event]) do | |
257 tmp[obj] = AceEvent_registry[event] and AceEvent_registry[event][obj] or nil | |
258 end | |
259 local obj = next(tmp) | |
260 while obj do | |
261 local method = tmp[obj] | |
262 AceEvent.UnregisterEvent(obj, event) | |
263 if type(method) == "string" then | |
264 local obj_method = obj[method] | |
265 if obj_method then | |
266 local success, err = pcall(obj_method, obj, ...) | |
267 if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end | |
268 end | |
269 elseif method then -- function | |
270 local success, err = pcall(method, ...) | |
271 if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end | |
272 end | |
273 tmp[obj] = nil | |
274 obj = next(tmp) | |
275 end | |
276 end | |
277 | |
278 local AceEvent_throttleRegistry = AceEvent.throttleRegistry | |
279 local throttleTable = AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] | |
280 if AceEvent_registry[event] then | |
281 for obj, method in pairs(AceEvent_registry[event]) do | |
282 tmp[obj] = method | |
283 end | |
284 local obj = next(tmp) | |
285 while obj do | |
286 local method = tmp[obj] | |
287 local continue = false | |
288 if throttleTable and throttleTable[obj] then | |
289 local a1 = ... | |
290 if a1 == nil then | |
291 a1 = FAKE_NIL | |
292 end | |
293 if not throttleTable[obj][a1] or GetTime() - throttleTable[obj][a1] >= throttleTable[obj][RATE] then | |
294 throttleTable[obj][a1] = GetTime() | |
295 else | |
296 continue = true | |
297 end | |
298 end | |
299 if not continue then | |
300 if type(method) == "string" then | |
301 local obj_method = obj[method] | |
302 if obj_method then | |
303 local success, err = pcall(obj_method, obj, ...) | |
304 if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end | |
305 end | |
306 elseif method then -- function | |
307 local success, err = pcall(method, ...) | |
308 if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end | |
309 end | |
310 end | |
311 tmp[obj] = nil | |
312 obj = next(tmp) | |
313 end | |
314 end | |
315 if AceEvent_registry[ALL_EVENTS] then | |
316 for obj, method in pairs(AceEvent_registry[ALL_EVENTS]) do | |
317 tmp[obj] = method | |
318 end | |
319 local obj = next(tmp) | |
320 while obj do | |
321 local method = tmp[obj] | |
322 if type(method) == "string" then | |
323 local obj_method = obj[method] | |
324 if obj_method then | |
325 local success, err = pcall(obj_method, obj, ...) | |
326 if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end | |
327 end | |
328 elseif method then -- function | |
329 local success, err = pcall(method, ...) | |
330 if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end | |
331 end | |
332 tmp[obj] = nil | |
333 obj = next(tmp) | |
334 end | |
335 end | |
336 tmp = del(tmp) | |
337 AceEvent.currentEvent = lastEvent | |
338 AceEvent.currentEventUID = lastEventUID | |
339 end | |
340 | |
341 local delayRegistry | |
342 local OnUpdate | |
343 do | |
344 local tmp = {} | |
345 OnUpdate = function() | |
346 local t = GetTime() | |
347 for k,v in pairs(delayRegistry) do | |
348 tmp[k] = true | |
349 end | |
350 for k in pairs(tmp) do | |
351 local v = delayRegistry[k] | |
352 if v then | |
353 local v_time = v.time | |
354 if not v_time then | |
355 delayRegistry[k] = nil | |
356 elseif v_time <= t then | |
357 local v_repeatDelay = v.repeatDelay | |
358 if v_repeatDelay then | |
359 -- use the event time, not the current time, else timing inaccuracies add up over time | |
360 v.time = v_time + v_repeatDelay | |
361 end | |
362 local event = v.event | |
363 if type(event) == "function" then | |
364 local uid = AceEvent.UID_NUM + 1 | |
365 AceEvent.UID_NUM = uid | |
366 AceEvent.currentEventUID = uid | |
367 local success, err = pcall(event, unpack(v, 1, v.n)) | |
368 if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end | |
369 AceEvent.currentEventUID = nil | |
370 else | |
371 AceEvent:TriggerEvent(event, unpack(v, 1, v.n)) | |
372 end | |
373 if not v_repeatDelay then | |
374 local x = delayRegistry[k] | |
375 if x and x.time == v_time then -- check if it was manually reset | |
376 if not useTablesAsIDs or type(k) == "string" then | |
377 del(delayRegistry[k]) | |
378 end | |
379 delayRegistry[k] = nil | |
380 end | |
381 end | |
382 end | |
383 end | |
384 end | |
385 for k in pairs(tmp) do | |
386 tmp[k] = nil | |
387 end | |
388 if not next(delayRegistry) then | |
389 AceEvent.frame:Hide() | |
390 end | |
391 end | |
392 end | |
393 | |
394 local function ScheduleEvent(self, repeating, event, delay, ...) | |
395 local id | |
396 if type(event) == "string" or (useTablesAsIDs and type(event) == "table") then | |
397 if useTablesAsIDs and type(event) == "table" then | |
398 if not delayRegistry or not delayRegistry[event] then | |
399 AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.") | |
400 end | |
401 end | |
402 if type(delay) ~= "number" then | |
403 id, event, delay = event, delay, ... | |
404 AceEvent:argCheck(event, 3, "string", "function", --[[ so message is right ]] "number") | |
405 AceEvent:argCheck(delay, 4, "number") | |
406 self:CancelScheduledEvent(id) | |
407 end | |
408 else | |
409 AceEvent:argCheck(event, 2, "string", "function") | |
410 AceEvent:argCheck(delay, 3, "number") | |
411 end | |
412 | |
413 if not delayRegistry then | |
414 AceEvent.delayRegistry = {} | |
415 delayRegistry = AceEvent.delayRegistry | |
416 AceEvent.frame:SetScript("OnUpdate", OnUpdate) | |
417 end | |
418 local t | |
419 if useTablesAsIDs and type(id) == "table" then | |
420 for k in pairs(id) do | |
421 id[k] = nil | |
422 end | |
423 t = id | |
424 for i = 2, select('#', ...) do | |
425 t[i-1] = select(i, ...) | |
426 end | |
427 t.n = select('#', ...) - 1 | |
428 elseif id then | |
429 t = new(select(2, ...)) | |
430 t.n = select('#', ...) - 1 | |
431 else | |
432 t = new(...) | |
433 t.n = select('#', ...) | |
434 end | |
435 t.event = event | |
436 t.time = GetTime() + delay | |
437 t.self = self | |
438 t.id = id or t | |
439 t.repeatDelay = repeating and delay | |
440 delayRegistry[t.id] = t | |
441 AceEvent.frame:Show() | |
442 if useTablesAsIDs then | |
443 return t.id | |
444 else | |
445 return | |
446 end | |
447 end | |
448 | |
449 --[[---------------------------------------------------------------------------------- | |
450 Notes: | |
451 * Schedule an event to fire. | |
452 * To fire on the next frame, specify a delay of 0. | |
453 Arguments: | |
454 string or function - name of the event to fire, or a function to call. | |
455 number - the amount of time to wait until calling. | |
456 tuple - a list of arguments to pass along. | |
457 ------------------------------------------------------------------------------------]] | |
458 function AceEvent:ScheduleEvent(event, delay, ...) | |
459 if type(event) == "string" or (useTablesAsIDs and type(event) == "table") then | |
460 if useTablesAsIDs and type(event) == "table" then | |
461 if not delayRegistry or not delayRegistry[event] then | |
462 AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.") | |
463 end | |
464 end | |
465 if type(delay) ~= "number" then | |
466 AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number") | |
467 AceEvent:argCheck(..., 4, "number") | |
468 end | |
469 else | |
470 AceEvent:argCheck(event, 2, "string", "function") | |
471 AceEvent:argCheck(delay, 3, "number") | |
472 end | |
473 | |
474 return ScheduleEvent(self, false, event, delay, ...) | |
475 end | |
476 | |
477 function AceEvent:ScheduleRepeatingEvent(event, delay, ...) | |
478 if type(event) == "string" or (useTablesAsIDs and type(event) == "table") then | |
479 if useTablesAsIDs and type(event) == "table" then | |
480 if not delayRegistry or not delayRegistry[event] then | |
481 AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.") | |
482 end | |
483 end | |
484 if type(delay) ~= "number" then | |
485 AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number") | |
486 AceEvent:argCheck(..., 4, "number") | |
487 end | |
488 else | |
489 AceEvent:argCheck(event, 2, "string", "function") | |
490 AceEvent:argCheck(delay, 3, "number") | |
491 end | |
492 | |
493 return ScheduleEvent(self, true, event, delay, ...) | |
494 end | |
495 | |
496 function AceEvent:CancelScheduledEvent(t) | |
497 if useTablesAsIDs then | |
498 AceEvent:argCheck(t, 2, "string", "table") | |
499 else | |
500 AceEvent:argCheck(t, 2, "string") | |
501 end | |
502 if delayRegistry then | |
503 local v = delayRegistry[t] | |
504 if v then | |
505 if not useTablesAsIDs or type(t) == "string" then | |
506 del(delayRegistry[t]) | |
507 end | |
508 delayRegistry[t] = nil | |
509 if not next(delayRegistry) then | |
510 AceEvent.frame:Hide() | |
511 end | |
512 return true | |
513 end | |
514 end | |
515 return false | |
516 end | |
517 | |
518 function AceEvent:IsEventScheduled(t) | |
519 if useTablesAsIDs then | |
520 AceEvent:argCheck(t, 2, "string", "table") | |
521 else | |
522 AceEvent:argCheck(t, 2, "string") | |
523 end | |
524 if delayRegistry then | |
525 local v = delayRegistry[t] | |
526 if v then | |
527 return true, v.time - GetTime() | |
528 end | |
529 end | |
530 return false, nil | |
531 end | |
532 | |
533 function AceEvent:UnregisterEvent(event) | |
534 AceEvent:argCheck(event, 2, "string") | |
535 local AceEvent_registry = AceEvent.registry | |
536 if AceEvent_registry[event] and AceEvent_registry[event][self] then | |
537 AceEvent_registry[event][self] = nil | |
538 local AceEvent_onceRegistry = AceEvent.onceRegistry | |
539 if AceEvent_onceRegistry and AceEvent_onceRegistry[event] and AceEvent_onceRegistry[event][self] then | |
540 AceEvent_onceRegistry[event][self] = nil | |
541 if not next(AceEvent_onceRegistry[event]) then | |
542 AceEvent_onceRegistry[event] = del(AceEvent_onceRegistry[event]) | |
543 end | |
544 end | |
545 local AceEvent_throttleRegistry = AceEvent.throttleRegistry | |
546 if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] and AceEvent_throttleRegistry[event][self] then | |
547 AceEvent_throttleRegistry[event][self] = nil | |
548 if not next(AceEvent_throttleRegistry[event]) then | |
549 AceEvent_throttleRegistry[event] = del(AceEvent_throttleRegistry[event]) | |
550 end | |
551 end | |
552 if not next(AceEvent_registry[event]) then | |
553 AceEvent_registry[event] = del(AceEvent_registry[event]) | |
554 if not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS]) then | |
555 AceEvent.frame:UnregisterEvent(event) | |
556 end | |
557 end | |
558 else | |
559 if self == AceEvent then | |
560 error(("Cannot unregister event %q. Improperly unregistering from AceEvent-2.0."):format(event), 2) | |
561 else | |
562 AceEvent:error("Cannot unregister event %q. %q is not registered with it.", event, self) | |
563 end | |
564 end | |
565 AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event) | |
566 end | |
567 | |
568 function AceEvent:UnregisterAllEvents() | |
569 local AceEvent_registry = AceEvent.registry | |
570 if AceEvent_registry[ALL_EVENTS] and AceEvent_registry[ALL_EVENTS][self] then | |
571 AceEvent_registry[ALL_EVENTS][self] = nil | |
572 if not next(AceEvent_registry[ALL_EVENTS]) then | |
573 AceEvent_registry[ALL_EVENTS] = del(AceEvent_registry[ALL_EVENTS]) | |
574 AceEvent.frame:UnregisterAllEvents() | |
575 for k,v in pairs(AceEvent_registry) do | |
576 AceEvent.frame:RegisterEvent(k) | |
577 end | |
578 end | |
579 end | |
580 if AceEvent_registry.AceEvent_EventUnregistered then | |
581 local event, data = "AceEvent_EventUnregistered", AceEvent_registry.AceEvent_EventUnregistered | |
582 local x = data[self] | |
583 data[self] = nil | |
584 if x then | |
585 if not next(data) then | |
586 if not AceEvent_registry[ALL_EVENTS] then | |
587 AceEvent.frame:UnregisterEvent(event) | |
588 end | |
589 AceEvent_registry[event] = del(AceEvent_registry[event]) | |
590 end | |
591 AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event) | |
592 end | |
593 end | |
594 for event, data in pairs(AceEvent_registry) do | |
595 local x = data[self] | |
596 data[self] = nil | |
597 if x and event ~= ALL_EVENTS then | |
598 if not next(data) then | |
599 if not AceEvent_registry[ALL_EVENTS] then | |
600 AceEvent.frame:UnregisterEvent(event) | |
601 end | |
602 AceEvent_registry[event] = del(AceEvent_registry[event]) | |
603 end | |
604 AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event) | |
605 end | |
606 end | |
607 if AceEvent.onceRegistry then | |
608 for event, data in pairs(AceEvent.onceRegistry) do | |
609 data[self] = nil | |
610 end | |
611 end | |
612 end | |
613 | |
614 function AceEvent:CancelAllScheduledEvents() | |
615 if delayRegistry then | |
616 for k,v in pairs(delayRegistry) do | |
617 if v.self == self then | |
618 if not useTablesAsIDs or type(k) == "string" then | |
619 del(delayRegistry[k]) | |
620 end | |
621 delayRegistry[k] = nil | |
622 end | |
623 end | |
624 if not next(delayRegistry) then | |
625 AceEvent.frame:Hide() | |
626 end | |
627 end | |
628 end | |
629 | |
630 function AceEvent:IsEventRegistered(event) | |
631 AceEvent:argCheck(event, 2, "string") | |
632 local AceEvent_registry = AceEvent.registry | |
633 if self == AceEvent then | |
634 return AceEvent_registry[event] and next(AceEvent_registry[event]) or AceEvent_registry[ALL_EVENTS] and next(AceEvent_registry[ALL_EVENTS]) and true or false | |
635 end | |
636 if AceEvent_registry[event] and AceEvent_registry[event][self] then | |
637 return true, AceEvent_registry[event][self] | |
638 end | |
639 if AceEvent_registry[ALL_EVENTS] and AceEvent_registry[ALL_EVENTS][self] then | |
640 return true, AceEvent_registry[ALL_EVENTS][self] | |
641 end | |
642 return false, nil | |
643 end | |
644 | |
645 local UnitExists = UnitExists | |
646 local bucketfunc | |
647 function AceEvent:RegisterBucketEvent(event, delay, method, ...) | |
648 AceEvent:argCheck(event, 2, "string", "table") | |
649 if type(event) == "table" then | |
650 for k,v in pairs(event) do | |
651 if type(k) ~= "number" then | |
652 AceEvent:error("All keys to argument #2 to `RegisterBucketEvent' must be numbers.") | |
653 elseif type(v) ~= "string" then | |
654 AceEvent:error("All values to argument #2 to `RegisterBucketEvent' must be strings.") | |
655 end | |
656 end | |
657 end | |
658 AceEvent:argCheck(delay, 3, "number") | |
659 if AceEvent == self then | |
660 AceEvent:argCheck(method, 4, "function") | |
661 self = method | |
662 else | |
663 if type(event) == "string" then | |
664 AceEvent:argCheck(method, 4, "string", "function", "nil") | |
665 if not method then | |
666 method = event | |
667 end | |
668 else | |
669 AceEvent:argCheck(method, 4, "string", "function") | |
670 end | |
671 | |
672 if type(method) == "string" and type(self[method]) ~= "function" then | |
673 AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method) | |
674 end | |
675 end | |
676 local buckets = AceEvent.buckets | |
677 if not buckets[event] then | |
678 buckets[event] = new() | |
679 end | |
680 if not buckets[event][self] then | |
681 local t = new() | |
682 t.current = new() | |
683 t.self = self | |
684 buckets[event][self] = t | |
685 else | |
686 AceEvent.CancelScheduledEvent(self, buckets[event][self].id) | |
687 end | |
688 local bucket = buckets[event][self] | |
689 bucket.method = method | |
690 | |
691 local n = select('#', ...) | |
692 if n > 0 then | |
693 for i = 1, n do | |
694 bucket[i] = select(i, ...) | |
695 end | |
696 end | |
697 bucket.n = n | |
698 | |
699 local func = function(arg1) | |
700 bucket.run = true | |
701 if arg1 then | |
702 bucket.current[arg1] = true | |
703 end | |
704 end | |
705 buckets[event][self].func = func | |
706 local isUnitBucket = true | |
707 if type(event) == "string" then | |
708 AceEvent.RegisterEvent(self, event, func) | |
709 if not event:find("^UNIT_") then | |
710 isUnitBucket = false | |
711 end | |
712 else | |
713 for _,v in ipairs(event) do | |
714 AceEvent.RegisterEvent(self, v, func) | |
715 if isUnitBucket and not v:find("^UNIT_") then | |
716 isUnitBucket = false | |
717 end | |
718 end | |
719 end | |
720 bucket.unit = isUnitBucket | |
721 if not bucketfunc then | |
722 bucketfunc = function(bucket) | |
723 local current = bucket.current | |
724 local method = bucket.method | |
725 local self = bucket.self | |
726 if bucket.run then | |
727 if bucket.unit then | |
728 for unit in pairs(current) do | |
729 if not UnitExists(unit) then | |
730 current[unit] = nil | |
731 end | |
732 end | |
733 end | |
734 if type(method) == "string" then | |
735 self[method](self, current, unpack(bucket, 1, bucket.n)) | |
736 elseif method then -- function | |
737 method(current, unpack(bucket, 1, bucket.n)) | |
738 end | |
739 for k in pairs(current) do | |
740 current[k] = nil | |
741 k = nil | |
742 end | |
743 bucket.run = false | |
744 end | |
745 end | |
746 end | |
747 bucket.id = "AceEvent-Bucket-" .. tostring(bucket) | |
748 AceEvent.ScheduleRepeatingEvent(self, bucket.id, bucketfunc, delay, bucket) | |
749 end | |
750 | |
751 function AceEvent:IsBucketEventRegistered(event) | |
752 AceEvent:argCheck(event, 2, "string", "table") | |
753 return AceEvent.buckets and AceEvent.buckets[event] and AceEvent.buckets[event][self] | |
754 end | |
755 | |
756 function AceEvent:UnregisterBucketEvent(event) | |
757 AceEvent:argCheck(event, 2, "string", "table") | |
758 if not AceEvent.buckets or not AceEvent.buckets[event] or not AceEvent.buckets[event][self] then | |
759 AceEvent:error("Cannot unregister bucket event %q. %q is not registered with it.", event, self) | |
760 end | |
761 | |
762 local bucket = AceEvent.buckets[event][self] | |
763 | |
764 if type(event) == "string" then | |
765 AceEvent.UnregisterEvent(self, event) | |
766 else | |
767 for _,v in ipairs(event) do | |
768 AceEvent.UnregisterEvent(self, v) | |
769 end | |
770 end | |
771 AceEvent:CancelScheduledEvent(bucket.id) | |
772 | |
773 bucket.current = del(bucket.current) | |
774 AceEvent.buckets[event][self] = del(bucket) | |
775 if not next(AceEvent.buckets[event]) then | |
776 AceEvent.buckets[event] = del(AceEvent.buckets[event]) | |
777 end | |
778 end | |
779 | |
780 function AceEvent:UnregisterAllBucketEvents() | |
781 if not AceEvent.buckets or not next(AceEvent.buckets) then | |
782 return | |
783 end | |
784 for k,v in pairs(AceEvent.buckets) do | |
785 if v == self then | |
786 AceEvent.UnregisterBucketEvent(self, k) | |
787 k = nil | |
788 end | |
789 end | |
790 end | |
791 | |
792 local combatSchedules | |
793 function AceEvent:CancelAllCombatSchedules() | |
794 local i = 0 | |
795 while true do | |
796 i = i + 1 | |
797 if not combatSchedules[i] then | |
798 break | |
799 end | |
800 local v = combatSchedules[i] | |
801 if v.self == self then | |
802 v = del(v) | |
803 table.remove(combatSchedules, i) | |
804 i = i - 1 | |
805 end | |
806 end | |
807 end | |
808 | |
809 local inCombat = false | |
810 | |
811 function AceEvent:PLAYER_REGEN_DISABLED() | |
812 inCombat = true | |
813 end | |
814 | |
815 do | |
816 local tmp = {} | |
817 function AceEvent:PLAYER_REGEN_ENABLED() | |
818 inCombat = false | |
819 for i, v in ipairs(combatSchedules) do | |
820 tmp[i] = v | |
821 combatSchedules[i] = nil | |
822 end | |
823 for i, v in ipairs(tmp) do | |
824 local func = v.func | |
825 if func then | |
826 local success, err = pcall(func, unpack(v, 1, v.n)) | |
827 if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end | |
828 else | |
829 local obj = v.obj or v.self | |
830 local method = v.method | |
831 local obj_method = obj[method] | |
832 if obj_method then | |
833 local success, err = pcall(obj_method, obj, unpack(v, 1, v.n)) | |
834 if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end | |
835 end | |
836 end | |
837 tmp[i] = del(v) | |
838 end | |
839 end | |
840 end | |
841 | |
842 function AceEvent:ScheduleLeaveCombatAction(method, ...) | |
843 local style = type(method) | |
844 if self == AceEvent then | |
845 if style == "table" then | |
846 local func = (...) | |
847 AceEvent:argCheck(func, 3, "string") | |
848 if type(method[func]) ~= "function" then | |
849 AceEvent:error("Cannot schedule a combat action to method %q, it does not exist", func) | |
850 end | |
851 else | |
852 AceEvent:argCheck(method, 2, "function", --[[so message is right]] "table") | |
853 end | |
854 self = method | |
855 else | |
856 AceEvent:argCheck(method, 2, "function", "string", "table") | |
857 if style == "string" and type(self[method]) ~= "function" then | |
858 AceEvent:error("Cannot schedule a combat action to method %q, it does not exist", method) | |
859 elseif style == "table" then | |
860 local func = (...) | |
861 AceEvent:argCheck(func, 3, "string") | |
862 if type(method[func]) ~= "function" then | |
863 AceEvent:error("Cannot schedule a combat action to method %q, it does not exist", func) | |
864 end | |
865 end | |
866 end | |
867 | |
868 if not inCombat then | |
869 local success, err | |
870 if type(method) == "function" then | |
871 success, err = pcall(method, ...) | |
872 elseif type(method) == "table" then | |
873 local func = (...) | |
874 success, err = pcall(method[func], method, select(2, ...)) | |
875 else | |
876 success, err = pcall(self[method], self, ...) | |
877 end | |
878 if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("(.-: )in.-\n") or "") .. err) end | |
879 return | |
880 end | |
881 local t | |
882 local n = select('#', ...) | |
883 if style == "table" then | |
884 t = new(select(2, ...)) | |
885 t.obj = method | |
886 t.method = (...) | |
887 t.n = n-1 | |
888 else | |
889 t = new(...) | |
890 t.n = n | |
891 if style == "function" then | |
892 t.func = method | |
893 else | |
894 t.method = method | |
895 end | |
896 end | |
897 t.self = self | |
898 table.insert(combatSchedules, t) | |
899 end | |
900 | |
901 function AceEvent:OnEmbedDisable(target) | |
902 self.UnregisterAllEvents(target) | |
903 | |
904 self.CancelAllScheduledEvents(target) | |
905 | |
906 self.UnregisterAllBucketEvents(target) | |
907 | |
908 self.CancelAllCombatSchedules(target) | |
909 end | |
910 | |
911 function AceEvent:IsFullyInitialized() | |
912 return self.postInit or false | |
913 end | |
914 | |
915 function AceEvent:IsPostPlayerLogin() | |
916 return IsLoggedIn() and true or false | |
917 end | |
918 | |
919 local function activate(self, oldLib, oldDeactivate) | |
920 AceEvent = self | |
921 | |
922 self.onceRegistry = oldLib and oldLib.onceRegistry or {} | |
923 self.throttleRegistry = oldLib and oldLib.throttleRegistry or {} | |
924 self.delayRegistry = oldLib and oldLib.delayRegistry or {} | |
925 self.buckets = oldLib and oldLib.buckets or {} | |
926 self.registry = oldLib and oldLib.registry or {} | |
927 self.frame = oldLib and oldLib.frame or CreateFrame("Frame", "AceEvent20Frame") | |
928 self.playerLogin = IsLoggedIn() and true | |
929 self.postInit = oldLib and oldLib.postInit or self.playerLogin and ChatTypeInfo and ChatTypeInfo.WHISPER and ChatTypeInfo.WHISPER.r and true | |
930 self.ALL_EVENTS = oldLib and oldLib.ALL_EVENTS or _G.newproxy() | |
931 self.FAKE_NIL = oldLib and oldLib.FAKE_NIL or _G.newproxy() | |
932 self.RATE = oldLib and oldLib.RATE or _G.newproxy() | |
933 self.combatSchedules = oldLib and oldLib.combatSchedules or {} | |
934 self.UID_NUM = oldLib and oldLib.UID_NUM or 0 | |
935 | |
936 -- Delete this down the road. Makes sure that the addonframes from revisions 33121 - 36174 get their events unregistered. | |
937 local addonframes = oldLib and oldLib.addonframes | |
938 if addonframes then | |
939 for _, v in pairs(addonframes) do | |
940 v:UnregisterAllEvents() | |
941 end | |
942 end | |
943 | |
944 combatSchedules = self.combatSchedules | |
945 ALL_EVENTS = self.ALL_EVENTS | |
946 FAKE_NIL = self.FAKE_NIL | |
947 RATE = self.RATE | |
948 local inPlw = false | |
949 local blacklist = { | |
950 UNIT_INVENTORY_CHANGED = true, | |
951 BAG_UPDATE = true, | |
952 ITEM_LOCK_CHANGED = true, | |
953 ACTIONBAR_SLOT_CHANGED = true, | |
954 } | |
955 self.frame:SetScript("OnEvent", function(_, event, ...) | |
956 if event == "PLAYER_ENTERING_WORLD" then | |
957 inPlw = false | |
958 elseif event == "PLAYER_LEAVING_WORLD" then | |
959 inPlw = true | |
960 end | |
961 if event and (not inPlw or not blacklist[event]) then | |
962 self:TriggerEvent(event, ...) | |
963 end | |
964 end) | |
965 if self.delayRegistry then | |
966 delayRegistry = self.delayRegistry | |
967 self.frame:SetScript("OnUpdate", OnUpdate) | |
968 end | |
969 | |
970 self:UnregisterAllEvents() | |
971 self:CancelAllScheduledEvents() | |
972 | |
973 registeringFromAceEvent = true | |
974 self:RegisterEvent("LOOT_OPENED", function() | |
975 SendAddonMessage("LOOT_OPENED", "", "RAID") | |
976 end) | |
977 registeringFromAceEvent = nil | |
978 | |
979 local function handleFullInit() | |
980 if not self.postInit then | |
981 local function func() | |
982 self.postInit = true | |
983 self:TriggerEvent("AceEvent_FullyInitialized") | |
984 if self.registry["CHAT_MSG_CHANNEL_NOTICE"] and self.registry["CHAT_MSG_CHANNEL_NOTICE"][self] then | |
985 self:UnregisterEvent("CHAT_MSG_CHANNEL_NOTICE") | |
986 end | |
987 if self.registry["MEETINGSTONE_CHANGED"] and self.registry["MEETINGSTONE_CHANGED"][self] then | |
988 self:UnregisterEvent("MEETINGSTONE_CHANGED") | |
989 end | |
990 if self.registry["MINIMAP_ZONE_CHANGED"] and self.registry["MINIMAP_ZONE_CHANGED"][self] then | |
991 self:UnregisterEvent("MINIMAP_ZONE_CHANGED") | |
992 end | |
993 if self.registry["LANGUAGE_LIST_CHANGED"] and self.registry["LANGUAGE_LIST_CHANGED"][self] then | |
994 self:UnregisterEvent("LANGUAGE_LIST_CHANGED") | |
995 end | |
996 collectgarbage('collect') | |
997 end | |
998 registeringFromAceEvent = true | |
999 local f = function() | |
1000 self.playerLogin = true | |
1001 self:ScheduleEvent("AceEvent_FullyInitialized", func, 1) | |
1002 end | |
1003 self:RegisterEvent("MEETINGSTONE_CHANGED", f, true) | |
1004 self:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE", function() | |
1005 self:ScheduleEvent("AceEvent_FullyInitialized", func, 0.15) | |
1006 end) | |
1007 self:RegisterEvent("LANGUAGE_LIST_CHANGED", function() | |
1008 if self.registry["MEETINGSTONE_CHANGED"] and self.registry["MEETINGSTONE_CHANGED"][self] then | |
1009 registeringFromAceEvent = true | |
1010 self:UnregisterEvent("MEETINGSTONE_CHANGED") | |
1011 self:RegisterEvent("MINIMAP_ZONE_CHANGED", fd, true) | |
1012 registeringFromAceEvent = nil | |
1013 end | |
1014 end) | |
1015 self:ScheduleEvent("AceEvent_FullyInitialized", func, 10) | |
1016 registeringFromAceEvent = nil | |
1017 end | |
1018 end | |
1019 | |
1020 if not self.playerLogin then | |
1021 registeringFromAceEvent = true | |
1022 self:RegisterEvent("PLAYER_LOGIN", function() | |
1023 self.playerLogin = true | |
1024 handleFullInit() | |
1025 handleFullInit = nil | |
1026 collectgarbage('collect') | |
1027 end, true) | |
1028 registeringFromAceEvent = nil | |
1029 else | |
1030 handleFullInit() | |
1031 handleFullInit = nil | |
1032 end | |
1033 | |
1034 if not AceEvent20EditBox then | |
1035 CreateFrame("Editbox", "AceEvent20EditBox") | |
1036 end | |
1037 local editbox = AceEvent20EditBox | |
1038 function editbox:Execute(line) | |
1039 local defaulteditbox = DEFAULT_CHAT_FRAME.editBox | |
1040 self:SetAttribute("chatType", defaulteditbox:GetAttribute("chatType")) | |
1041 self:SetAttribute("tellTarget", defaulteditbox:GetAttribute("tellTarget")) | |
1042 self:SetAttribute("channelTarget", defaulteditbox:GetAttribute("channelTarget")) | |
1043 self:SetText(line) | |
1044 ChatEdit_SendText(self) | |
1045 end | |
1046 editbox:Hide() | |
1047 _G["SLASH_IN1"] = "/in" | |
1048 SlashCmdList["IN"] = function(msg) | |
1049 local seconds, command, rest = msg:match("^([^%s]+)%s+(/[^%s]+)(.*)$") | |
1050 seconds = tonumber(seconds) | |
1051 if not seconds then | |
1052 DEFAULT_CHAT_FRAME:AddMessage("Error, bad arguments to /in. Must be in the form of `/in 5 /say hi'") | |
1053 return | |
1054 end | |
1055 if IsSecureCmd(command) then | |
1056 DEFAULT_CHAT_FRAME:AddMessage(("Error, /in cannot call secure command: %s"):format(command)) | |
1057 return | |
1058 end | |
1059 self:ScheduleEvent("AceEventSlashIn-" .. math.random(1, 1000000000), editbox.Execute, seconds, editbox, command .. rest) | |
1060 end | |
1061 registeringFromAceEvent = true | |
1062 self:RegisterEvent("PLAYER_REGEN_ENABLED") | |
1063 self:RegisterEvent("PLAYER_REGEN_DISABLED") | |
1064 inCombat = InCombatLockdown() | |
1065 registeringFromAceEvent = nil | |
1066 | |
1067 -- another hack to make sure that we clean up properly from rev 33121 - 36174 | |
1068 if self.registry[ALL_EVENTS] then | |
1069 self.frame:RegisterAllEvents() | |
1070 else | |
1071 for event in pairs(self.registry) do | |
1072 self.frame:RegisterEvent(event) | |
1073 end | |
1074 end | |
1075 | |
1076 self:activate(oldLib, oldDeactivate) | |
1077 if oldLib then | |
1078 oldDeactivate(oldLib) | |
1079 end | |
1080 end | |
1081 | |
1082 AceLibrary:Register(AceEvent, MAJOR_VERSION, MINOR_VERSION, activate) |