vanilla-wow-addons – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 --[[
2 Name: AceEvent-2.0
3 Revision: $Rev: 7841 $
4 Author(s): ckknight (ckknight@gmail.com)
5 facboy (<email here>)
6 Inspired By: AceEvent 1.x by Turan (<email here>)
7 Website: http://www.wowace.com/
8 Documentation: http://wiki.wowace.com/index.php/AceEvent-2.0
9 SVN: http://svn.wowace.com/root/trunk/Ace2/AceEvent-2.0
10 Description: Mixin to allow for event handling, scheduling, and inter-addon
11 communication.
12 Dependencies: AceLibrary, AceOO-2.0
13 ]]
14  
15 local MAJOR_VERSION = "AceEvent-2.0"
16 local MINOR_VERSION = "$Revision: 7841 $"
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 }
42  
43 local weakKey = {__mode="k"}
44 local new, del
45 do
46 local list = setmetatable({}, weakKey)
47 function new()
48 local t = next(list)
49 if t then
50 list[t] = nil
51 return t
52 else
53 return {}
54 end
55 end
56  
57 function del(t)
58 setmetatable(t, nil)
59 for k in pairs(t) do
60 t[k] = nil
61 end
62 list[t] = true
63 end
64 end
65  
66 local FAKE_NIL
67 local RATE
68  
69 local registeringFromAceEvent
70 function AceEvent:RegisterEvent(event, method, once)
71 AceEvent:argCheck(event, 2, "string")
72 if self == AceEvent and not registeringFromAceEvent then
73 AceEvent:argCheck(method, 3, "function")
74 self = method
75 else
76 AceEvent:argCheck(method, 3, "string", "function", "nil", "boolean", "number")
77 if type(method) == "boolean" or type(method) == "number" then
78 AceEvent:argCheck(once, 4, "nil")
79 once, method = method, event
80 end
81 end
82 AceEvent:argCheck(once, 4, "number", "boolean", "nil")
83 local throttleRate
84 if type(once) == "number" then
85 throttleRate, once = once
86 end
87 if not method then
88 method = event
89 end
90 if type(method) == "string" and type(self[method]) ~= "function" then
91 AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method)
92 end
93  
94 local AceEvent_registry = AceEvent.registry
95 if not AceEvent_registry[event] then
96 AceEvent_registry[event] = new()
97 AceEvent.frame:RegisterEvent(event)
98 end
99  
100 local remember = true
101 if AceEvent_registry[event][self] then
102 remember = false
103 end
104 AceEvent_registry[event][self] = method
105  
106 local AceEvent_onceRegistry = AceEvent.onceRegistry
107 if once then
108 if not AceEvent_onceRegistry then
109 AceEvent.onceRegistry = new()
110 AceEvent_onceRegistry = AceEvent.onceRegistry
111 end
112 if not AceEvent_onceRegistry[event] then
113 AceEvent_onceRegistry[event] = new()
114 end
115 AceEvent_onceRegistry[event][self] = true
116 else
117 if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then
118 AceEvent_onceRegistry[event][self] = nil
119 if not next(AceEvent_onceRegistry[event]) then
120 AceEvent_onceRegistry[event] = del(AceEvent_onceRegistry[event])
121 end
122 end
123 end
124  
125 local AceEvent_throttleRegistry = AceEvent.throttleRegistry
126 if throttleRate then
127 if not AceEvent_throttleRegistry then
128 AceEvent.throttleRegistry = new()
129 AceEvent_throttleRegistry = AceEvent.throttleRegistry
130 end
131 if not AceEvent_throttleRegistry[event] then
132 AceEvent_throttleRegistry[event] = new()
133 end
134 if AceEvent_throttleRegistry[event][self] then
135 AceEvent_throttleRegistry[event][self] = del(AceEvent_throttleRegistry[event][self])
136 end
137 AceEvent_throttleRegistry[event][self] = setmetatable(new(), weakKey)
138 local t = AceEvent_throttleRegistry[event][self]
139 t[RATE] = throttleRate
140 else
141 if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] then
142 if AceEvent_throttleRegistry[event][self] then
143 AceEvent_throttleRegistry[event][self] = del(AceEvent_throttleRegistry[event][self])
144 end
145 if not next(AceEvent_throttleRegistry[event]) then
146 AceEvent_throttleRegistry[event] = del(AceEvent_throttleRegistry[event])
147 end
148 end
149 end
150  
151 if remember then
152 AceEvent:TriggerEvent("AceEvent_EventRegistered", self, event)
153 end
154 end
155  
156 local ALL_EVENTS
157  
158 function AceEvent:RegisterAllEvents(method)
159 if self == AceEvent then
160 AceEvent:argCheck(method, 1, "function")
161 self = method
162 else
163 AceEvent:argCheck(method, 1, "string", "function")
164 if type(method) == "string" and type(self[method]) ~= "function" then
165 AceEvent:error("Cannot register all events to method %q, it does not exist", method)
166 end
167 end
168  
169 if not AceEvent.registry[ALL_EVENTS] then
170 AceEvent.registry[ALL_EVENTS] = new()
171 AceEvent.frame:RegisterAllEvents()
172 end
173  
174 AceEvent.registry[ALL_EVENTS][self] = method
175 end
176  
177 local _G = getfenv(0)
178 function AceEvent:TriggerEvent(event, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
179 AceEvent:argCheck(event, 2, "string")
180 local AceEvent_registry = AceEvent.registry
181 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
182 return
183 end
184 local _G_event = _G.event
185 _G.event = event
186  
187 local AceEvent_onceRegistry = AceEvent.onceRegistry
188 local AceEvent_debugTable = AceEvent.debugTable
189 if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then
190 local tmp = new()
191 for obj, method in pairs(AceEvent_onceRegistry[event]) do
192 tmp[obj] = AceEvent_registry[event] and AceEvent_registry[event][obj] or nil
193 end
194 local obj = next(tmp)
195 while obj do
196 local mem, time
197 if AceEvent_debugTable then
198 if not AceEvent_debugTable[event] then
199 AceEvent_debugTable[event] = new()
200 end
201 if not AceEvent_debugTable[event][obj] then
202 AceEvent_debugTable[event][obj] = new()
203 AceEvent_debugTable[event][obj].mem = 0
204 AceEvent_debugTable[event][obj].time = 0
205 AceEvent_debugTable[event][obj].count = 0
206 end
207 mem, time = gcinfo(), GetTime()
208 end
209 local method = tmp[obj]
210 AceEvent.UnregisterEvent(obj, event)
211 if type(method) == "string" then
212 local obj_method = obj[method]
213 if obj_method then
214 obj_method(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
215 end
216 elseif method then -- function
217 method(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
218 end
219 if AceEvent_debugTable then
220 mem, time = gcinfo() - mem, GetTime() - time
221 AceEvent_debugTable[event][obj].mem = AceEvent_debugTable[event][obj].mem + mem
222 AceEvent_debugTable[event][obj].time = AceEvent_debugTable[event][obj].time + time
223 AceEvent_debugTable[event][obj].count = AceEvent_debugTable[event][obj].count + 1
224 end
225 tmp[obj] = nil
226 obj = next(tmp)
227 end
228 del(tmp)
229 end
230  
231 local AceEvent_throttleRegistry = AceEvent.throttleRegistry
232 local throttleTable = AceEvent_throttleRegistry and AceEvent_throttleRegistry[event]
233 if AceEvent_registry[event] then
234 local tmp = new()
235 for obj, method in pairs(AceEvent_registry[event]) do
236 tmp[obj] = method
237 end
238 local obj = next(tmp)
239 while obj do
240 local method = tmp[obj]
241 local continue = false
242 if throttleTable and throttleTable[obj] then
243 local a1 = a1
244 if a1 == nil then
245 a1 = FAKE_NIL
246 end
247 if not throttleTable[obj][a1] or GetTime() - throttleTable[obj][a1] >= throttleTable[obj][RATE] then
248 throttleTable[obj][a1] = GetTime()
249 else
250 continue = true
251 end
252 end
253 if not continue then
254 local mem, time
255 if AceEvent_debugTable then
256 if not AceEvent_debugTable[event] then
257 AceEvent_debugTable[event] = new()
258 end
259 if not AceEvent_debugTable[event][obj] then
260 AceEvent_debugTable[event][obj] = new()
261 AceEvent_debugTable[event][obj].mem = 0
262 AceEvent_debugTable[event][obj].time = 0
263 AceEvent_debugTable[event][obj].count = 0
264 end
265 mem, time = gcinfo(), GetTime()
266 end
267 if type(method) == "string" then
268 local obj_method = obj[method]
269 if obj_method then
270 obj_method(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
271 end
272 elseif method then -- function
273 method(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
274 end
275 if AceEvent_debugTable then
276 mem, time = gcinfo() - mem, GetTime() - time
277 AceEvent_debugTable[event][obj].mem = AceEvent_debugTable[event][obj].mem + mem
278 AceEvent_debugTable[event][obj].time = AceEvent_debugTable[event][obj].time + time
279 AceEvent_debugTable[event][obj].count = AceEvent_debugTable[event][obj].count + 1
280 end
281 end
282 tmp[obj] = nil
283 obj = next(tmp)
284 end
285 del(tmp)
286 end
287 if AceEvent_registry[ALL_EVENTS] then
288 local tmp = new()
289 for obj, method in pairs(AceEvent_registry[ALL_EVENTS]) do
290 tmp[obj] = method
291 end
292 local obj = next(tmp)
293 while obj do
294 local method = tmp[obj]
295 local mem, time
296 if AceEvent_debugTable then
297 if not AceEvent_debugTable[event] then
298 AceEvent_debugTable[event] = new()
299 end
300 if not AceEvent_debugTable[event][obj] then
301 AceEvent_debugTable[event][obj] = new()
302 AceEvent_debugTable[event][obj].mem = 0
303 AceEvent_debugTable[event][obj].time = 0
304 AceEvent_debugTable[event][obj].count = 0
305 end
306 mem, time = gcinfo(), GetTime()
307 end
308 if type(method) == "string" then
309 local obj_method = obj[method]
310 if obj_method then
311 obj_method(obj, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
312 end
313 elseif method then -- function
314 method(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
315 end
316 if AceEvent_debugTable then
317 mem, time = gcinfo() - mem, GetTime() - time
318 AceEvent_debugTable[event][obj].mem = AceEvent_debugTable[event][obj].mem + mem
319 AceEvent_debugTable[event][obj].time = AceEvent_debugTable[event][obj].time + time
320 AceEvent_debugTable[event][obj].count = AceEvent_debugTable[event][obj].count + 1
321 end
322 tmp[obj] = nil
323 obj = next(tmp)
324 end
325 del(tmp)
326 end
327 _G.event = _G_event
328 end
329  
330 --------------------
331 -- schedule heap management
332 --------------------
333  
334 -- local accessors
335 local getn = table.getn
336 local setn = table.setn
337 local tinsert = table.insert
338 local tremove = table.remove
339 local floor = math.floor
340  
341 --------------------
342 -- sifting functions
343 local function hSiftUp(heap, pos, schedule)
344 schedule = schedule or heap[pos]
345 local scheduleTime = schedule.time
346  
347 local curr, i = pos, floor(pos/2)
348 local parent = heap[i]
349 while i > 0 and scheduleTime < parent.time do
350 heap[curr], parent.i = parent, curr
351 curr, i = i, floor(i/2)
352 parent = heap[i]
353 end
354 heap[curr], schedule.i = schedule, curr
355 return pos ~= curr
356 end
357  
358 local function hSiftDown(heap, pos, schedule, size)
359 schedule, size = schedule or heap[pos], size or getn(heap)
360 local scheduleTime = schedule.time
361  
362 local curr = pos
363 repeat
364 local child, childTime, c
365 -- determine the child to compare with
366 local j = 2 * curr
367 if j > size then
368 break
369 end
370 local k = j + 1
371 if k > size then
372 child = heap[j]
373 childTime, c = child.time, j
374 else
375 local childj, childk = heap[j], heap[k]
376 local jTime, kTime = childj.time, childk.time
377 if jTime < kTime then
378 child, childTime, c = childj, jTime, j
379 else
380 child, childTime, c = childk, kTime, k
381 end
382 end
383 -- do the comparison
384 if scheduleTime <= childTime then
385 break
386 end
387 heap[curr], child.i = child, curr
388 curr = c
389 until false
390 heap[curr], schedule.i = schedule, curr
391 return pos ~= curr
392 end
393  
394 --------------------
395 -- heap functions
396 local function hMaintain(heap, pos, schedule, size)
397 schedule, size = schedule or heap[pos], size or getn(heap)
398 if not hSiftUp(heap, pos, schedule) then
399 hSiftDown(heap, pos, schedule, size)
400 end
401 end
402  
403 local function hPush(heap, schedule)
404 tinsert(heap, schedule)
405 hSiftUp(heap, getn(heap), schedule)
406 end
407  
408 local function hPop(heap)
409 local head, tail = heap[1], tremove(heap)
410 local size = getn(heap)
411  
412 if size == 1 then
413 heap[1], tail.i = tail, 1
414 elseif size > 1 then
415 hSiftDown(heap, 1, tail, size)
416 end
417 return head
418 end
419  
420 local function hDelete(heap, pos)
421 local size = getn(heap)
422 local tail = tremove(heap)
423 if pos < size then
424 size = size - 1
425 if size == 1 then
426 heap[1], tail.i = tail, 1
427 elseif size > 1 then
428 heap[pos] = tail
429 hMaintain(heap, pos, tail, size)
430 end
431 end
432 end
433  
434 local GetTime = GetTime
435 local delayRegistry
436 local delayHeap
437 local function OnUpdate()
438 local t = GetTime()
439 -- peek at top of heap
440 local v = delayHeap[1]
441 local v_time = v and v.time
442 while v and v_time <= t do
443 local v_repeatDelay = v.repeatDelay
444 if v_repeatDelay then
445 -- use the event time, not the current time, else timing inaccuracies add up over time
446 v.time = v_time + v_repeatDelay
447 -- re-arrange the heap
448 hSiftDown(delayHeap, 1, v)
449 else
450 -- pop the event off the heap, and delete it from the registry
451 hPop(delayHeap)
452 delayRegistry[v.id] = nil
453 end
454 local event = v.event
455 if type(event) == "function" then
456 event(unpack(v))
457 else
458 AceEvent:TriggerEvent(event, unpack(v))
459 end
460 if not v_repeatDelay then
461 del(v)
462 end
463 v = delayHeap[1]
464 v_time = v and v.time
465 end
466 if not v then
467 AceEvent.frame:Hide()
468 end
469 end
470  
471 local function ScheduleEvent(self, repeating, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
472 local id
473 if type(event) == "string" or type(event) == "table" then
474 if type(event) == "table" then
475 if not delayRegistry or not delayRegistry[event] then
476 AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.")
477 end
478 end
479 if type(delay) ~= "number" then
480 id, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20 = event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20
481 AceEvent:argCheck(event, 3, "string", "function", --[[ so message is right ]] "number")
482 AceEvent:argCheck(delay, 4, "number")
483 self:CancelScheduledEvent(id)
484 end
485 else
486 AceEvent:argCheck(event, 2, "string", "function")
487 AceEvent:argCheck(delay, 3, "number")
488 end
489  
490 if not delayRegistry then
491 AceEvent.delayRegistry = new()
492 AceEvent.delayHeap = new()
493 AceEvent.delayHeap.n = 0
494 delayRegistry = AceEvent.delayRegistry
495 delayHeap = AceEvent.delayHeap
496 AceEvent.frame:SetScript("OnUpdate", OnUpdate)
497 end
498 local t
499 if type(id) == "table" then
500 for k in pairs(id) do
501 id[k] = nil
502 end
503 table.setn(id, 0)
504 t = id
505 else
506 t = new()
507 end
508 t.n = 0
509 tinsert(t, a1)
510 tinsert(t, a2)
511 tinsert(t, a3)
512 tinsert(t, a4)
513 tinsert(t, a5)
514 tinsert(t, a6)
515 tinsert(t, a7)
516 tinsert(t, a8)
517 tinsert(t, a9)
518 tinsert(t, a10)
519 tinsert(t, a11)
520 tinsert(t, a12)
521 tinsert(t, a13)
522 tinsert(t, a14)
523 tinsert(t, a15)
524 tinsert(t, a16)
525 tinsert(t, a17)
526 tinsert(t, a18)
527 tinsert(t, a19)
528 tinsert(t, a20)
529 t.event = event
530 t.time = GetTime() + delay
531 t.self = self
532 t.id = id or t
533 t.repeatDelay = repeating and delay
534 delayRegistry[t.id] = t
535 -- insert into heap
536 hPush(delayHeap, t)
537 AceEvent.frame:Show()
538 return t.id
539 end
540  
541 function AceEvent:ScheduleEvent(event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
542 if type(event) == "string" or type(event) == "table" then
543 if type(event) == "table" then
544 if not delayRegistry or not delayRegistry[event] then
545 AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.")
546 end
547 end
548 if type(delay) ~= "number" then
549 AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number")
550 AceEvent:argCheck(a1, 4, "number")
551 end
552 else
553 AceEvent:argCheck(event, 2, "string", "function")
554 AceEvent:argCheck(delay, 3, "number")
555 end
556  
557 return ScheduleEvent(self, false, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
558 end
559  
560 function AceEvent:ScheduleRepeatingEvent(event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
561 if type(event) == "string" or type(event) == "table" then
562 if type(event) == "table" then
563 if not delayRegistry or not delayRegistry[event] then
564 AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.")
565 end
566 end
567 if type(delay) ~= "number" then
568 AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number")
569 AceEvent:argCheck(a1, 4, "number")
570 end
571 else
572 AceEvent:argCheck(event, 2, "string", "function")
573 AceEvent:argCheck(delay, 3, "number")
574 end
575  
576 return ScheduleEvent(self, true, event, delay, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
577 end
578  
579 function AceEvent:CancelScheduledEvent(t)
580 AceEvent:argCheck(t, 2, "string", "table")
581 if delayRegistry then
582 local v = delayRegistry[t]
583 if v then
584 hDelete(delayHeap, v.i)
585 delayRegistry[t] = nil
586 del(v)
587 if not next(delayRegistry) then
588 AceEvent.frame:Hide()
589 end
590 return true
591 end
592 end
593 return false
594 end
595  
596 function AceEvent:IsEventScheduled(t)
597 AceEvent:argCheck(t, 2, "string", "table")
598 if delayRegistry then
599 local v = delayRegistry[t]
600 if v then
601 return true, v.time - GetTime()
602 end
603 end
604 return false, nil
605 end
606  
607  
608 function AceEvent:IsEventRegistered(event)
609 AceEvent:argCheck(event, 2, "string")
610 local AceEvent_registry = AceEvent.registry
611 if self == AceEvent then
612 return AceEvent_registry[event] and next(AceEvent_registry[event]) and true or false
613 end
614 if AceEvent_registry[event] and AceEvent_registry[event][self] then
615 return true, AceEvent_registry[event][self]
616 end
617 return false, nil
618 end
619  
620 function AceEvent:UnregisterEvent(event)
621 AceEvent:argCheck(event, 2, "string")
622 local AceEvent_registry = AceEvent.registry
623 if AceEvent_registry[event] and AceEvent_registry[event][self] then
624 AceEvent_registry[event][self] = nil
625 local AceEvent_onceRegistry = AceEvent.onceRegistry
626 if AceEvent_onceRegistry and AceEvent_onceRegistry[event] and AceEvent_onceRegistry[event][self] then
627 AceEvent_onceRegistry[event][self] = nil
628 if not next(AceEvent_onceRegistry[event]) then
629 AceEvent_onceRegistry[event] = del(AceEvent_onceRegistry[event])
630 end
631 end
632 local AceEvent_throttleRegistry = AceEvent.throttleRegistry
633 if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] and AceEvent_throttleRegistry[event][self] then
634 AceEvent_throttleRegistry[event][self] = del(AceEvent_throttleRegistry[event][self])
635 if not next(AceEvent_throttleRegistry[event]) then
636 AceEvent_throttleRegistry[event] = del(AceEvent_throttleRegistry[event])
637 end
638 end
639 if not next(AceEvent_registry[event]) then
640 AceEvent_registry[event] = del(AceEvent_registry[event])
641 if not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS]) then
642 AceEvent.frame:UnregisterEvent(event)
643 end
644 end
645 else
646 if self == AceEvent then
647 error(string.format("Cannot unregister event %q. Improperly unregistering from AceEvent-2.0.", event), 2)
648 else
649 AceEvent:error("Cannot unregister event %q. %q is not registered with it.", event, self)
650 end
651 end
652 AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event)
653 end
654  
655 function AceEvent:UnregisterAllEvents()
656 local AceEvent_registry = AceEvent.registry
657 if AceEvent_registry[ALL_EVENTS] and AceEvent_registry[ALL_EVENTS][self] then
658 AceEvent_registry[ALL_EVENTS][self] = nil
659 if not next(AceEvent_registry[ALL_EVENTS]) then
660 del(AceEvent_registry[ALL_EVENTS])
661 AceEvent.frame:UnregisterAllEvents()
662 for k,v in pairs(AceEvent_registry) do
663 if k ~= ALL_EVENTS then
664 AceEvent.frame:RegisterEvent(k)
665 end
666 end
667 AceEvent_registry[event] = nil
668 end
669 end
670 local first = true
671 for event, data in pairs(AceEvent_registry) do
672 if first then
673 if AceEvent_registry.AceEvent_EventUnregistered then
674 event = "AceEvent_EventUnregistered"
675 else
676 first = false
677 end
678 end
679 local x = data[self]
680 data[self] = nil
681 if x and event ~= ALL_EVENTS then
682 if not next(data) then
683 del(data)
684 if not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS]) then
685 AceEvent.frame:UnregisterEvent(event)
686 end
687 AceEvent_registry[event] = nil
688 end
689 AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event)
690 end
691 if first then
692 event = nil
693 end
694 end
695 if AceEvent.onceRegistry then
696 for event, data in pairs(AceEvent.onceRegistry) do
697 data[self] = nil
698 end
699 end
700 end
701  
702 function AceEvent:CancelAllScheduledEvents()
703 if delayRegistry then
704 for k,v in pairs(delayRegistry) do
705 if v.self == self then
706 hDelete(delayHeap, v.i)
707 del(v)
708 delayRegistry[k] = nil
709 end
710 end
711 if not next(delayRegistry) then
712 AceEvent.frame:Hide()
713 end
714 end
715 end
716  
717 function AceEvent:IsEventRegistered(event)
718 AceEvent:argCheck(event, 2, "string")
719 local AceEvent_registry = AceEvent.registry
720 if self == AceEvent then
721 return AceEvent_registry[event] and next(AceEvent_registry[event]) and true or false
722 end
723 if AceEvent_registry[event] and AceEvent_registry[event][self] then
724 return true, AceEvent_registry[event][self]
725 end
726 return false, nil
727 end
728  
729 local bucketfunc
730 function AceEvent:RegisterBucketEvent(event, delay, method)
731 AceEvent:argCheck(event, 2, "string", "table")
732 if type(event) == "table" then
733 for k,v in pairs(event) do
734 if type(k) ~= "number" then
735 AceEvent:error("All keys to argument #2 to `RegisterBucketEvent' must be numbers.")
736 elseif type(v) ~= "string" then
737 AceEvent:error("All values to argument #2 to `RegisterBucketEvent' must be strings.")
738 end
739 end
740 end
741 AceEvent:argCheck(delay, 3, "number")
742 if AceEvent == self then
743 AceEvent:argCheck(method, 4, "function")
744 self = method
745 else
746 if type(event) == "string" then
747 AceEvent:argCheck(method, 4, "string", "function", "nil")
748 if not method then
749 method = event
750 end
751 else
752 AceEvent:argCheck(method, 4, "string", "function")
753 end
754  
755 if type(method) == "string" and type(self[method]) ~= "function" then
756 AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method)
757 end
758 end
759 if not AceEvent.buckets then
760 AceEvent.buckets = new()
761 end
762 if not AceEvent.buckets[event] then
763 AceEvent.buckets[event] = new()
764 end
765 if not AceEvent.buckets[event][self] then
766 AceEvent.buckets[event][self] = new()
767 AceEvent.buckets[event][self].current = new()
768 AceEvent.buckets[event][self].self = self
769 else
770 AceEvent.CancelScheduledEvent(self, AceEvent.buckets[event][self].id)
771 end
772 local bucket = AceEvent.buckets[event][self]
773 bucket.method = method
774  
775 local func = function(arg1)
776 bucket.run = true
777 if arg1 then
778 bucket.current[arg1] = true
779 end
780 end
781 AceEvent.buckets[event][self].func = func
782 if type(event) == "string" then
783 AceEvent.RegisterEvent(self, event, func)
784 else
785 for _,v in ipairs(event) do
786 AceEvent.RegisterEvent(self, v, func)
787 end
788 end
789 if not bucketfunc then
790 bucketfunc = function(bucket)
791 local current = bucket.current
792 local method = bucket.method
793 local self = bucket.self
794 if bucket.run then
795 if type(method) == "string" then
796 self[method](self, current)
797 elseif method then -- function
798 method(current)
799 end
800 for k in pairs(current) do
801 current[k] = nil
802 k = nil
803 end
804 bucket.run = false
805 end
806 end
807 end
808 bucket.id = AceEvent.ScheduleRepeatingEvent(self, bucketfunc, delay, bucket)
809 end
810  
811 function AceEvent:IsBucketEventRegistered(event)
812 AceEvent:argCheck(event, 2, "string", "table")
813 return AceEvent.buckets and AceEvent.buckets[event] and AceEvent.buckets[event][self]
814 end
815  
816 function AceEvent:UnregisterBucketEvent(event)
817 AceEvent:argCheck(event, 2, "string", "table")
818 if not AceEvent.buckets or not AceEvent.buckets[event] or not AceEvent.buckets[event][self] then
819 AceEvent:error("Cannot unregister bucket event %q. %q is not registered with it.", event, self)
820 end
821  
822 local bucket = AceEvent.buckets[event][self]
823  
824 if type(event) == "string" then
825 AceEvent.UnregisterEvent(bucket.func, event)
826 else
827 for _,v in ipairs(event) do
828 AceEvent.UnregisterEvent(bucket.func, v)
829 end
830 end
831 AceEvent:CancelScheduledEvent(bucket.id)
832  
833 del(bucket.current)
834 AceEvent.buckets[event][self] = del(AceEvent.buckets[event][self])
835 if not next(AceEvent.buckets[event]) then
836 AceEvent.buckets[event] = del(AceEvent.buckets[event])
837 end
838 end
839  
840 function AceEvent:UnregisterAllBucketEvents()
841 if not AceEvent.buckets or not next(AceEvent.buckets) then
842 return
843 end
844 for k,v in pairs(AceEvent.buckets) do
845 if v == self then
846 AceEvent.UnregisterBucketEvent(self, k)
847 k = nil
848 end
849 end
850 end
851  
852 function AceEvent:OnEmbedDisable(target)
853 self.UnregisterAllEvents(target)
854  
855 self.CancelAllScheduledEvents(target)
856  
857 self.UnregisterAllBucketEvents(target)
858 end
859  
860 function AceEvent:EnableDebugging()
861 if not self.debugTable then
862 self.debugTable = new()
863 end
864 end
865  
866 function AceEvent:IsFullyInitialized()
867 return self.postInit or false
868 end
869  
870 function AceEvent:IsPostPlayerLogin()
871 return self.playerLogin or false
872 end
873  
874 function AceEvent:activate(oldLib, oldDeactivate)
875 AceEvent = self
876  
877 if oldLib then
878 self.onceRegistry = oldLib.onceRegistry
879 self.throttleRegistry = oldLib.throttleRegistry
880 self.delayRegistry = oldLib.delayRegistry
881 self.buckets = oldLib.buckets
882 self.delayHeap = oldLib.delayHeap
883 self.registry = oldLib.registry
884 self.frame = oldLib.frame
885 self.debugTable = oldLib.debugTable
886 self.playerLogin = oldLib.pew or DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.defaultLanguage and true
887 self.postInit = oldLib.postInit or self.playerLogin and ChatTypeInfo and ChatTypeInfo.WHISPER and ChatTypeInfo.WHISPER.r and true
888 self.ALL_EVENTS = oldLib.ALL_EVENTS
889 self.FAKE_NIL = oldLib.FAKE_NIL
890 self.RATE = oldLib.RATE
891 end
892 if not self.registry then
893 self.registry = {}
894 end
895 if not self.frame then
896 self.frame = CreateFrame("Frame", "AceEvent20Frame")
897 end
898 if not self.ALL_EVENTS then
899 self.ALL_EVENTS = {}
900 end
901 if not self.FAKE_NIL then
902 self.FAKE_NIL = {}
903 end
904 if not self.RATE then
905 self.RATE = {}
906 end
907 ALL_EVENTS = self.ALL_EVENTS
908 FAKE_NIL = self.FAKE_NIL
909 RATE = self.RATE
910 local inPlw = false
911 local blacklist = {
912 UNIT_INVENTORY_CHANGED = true,
913 BAG_UPDATE = true,
914 ITEM_LOCK_CHANGED = true,
915 ACTIONBAR_SLOT_CHANGED = true,
916 }
917 self.frame:SetScript("OnEvent", function()
918 local event = event
919 if event == "PLAYER_ENTERING_WORLD" then
920 inPlw = false
921 elseif event == "PLAYER_LEAVING_WORLD" then
922 inPlw = true
923 end
924 if event and (not inPlw or not blacklist[event]) then
925 self:TriggerEvent(event, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9)
926 end
927 end)
928 if self.delayRegistry then
929 delayRegistry = self.delayRegistry
930 delayHeap = self.delayHeap
931 self.frame:SetScript("OnUpdate", OnUpdate)
932 end
933  
934 self:UnregisterAllEvents()
935 self:CancelAllScheduledEvents()
936  
937 if not self.playerLogin then
938 registeringFromAceEvent = true
939 self:RegisterEvent("PLAYER_LOGIN", function()
940 self.playerLogin = true
941 end, true)
942 registeringFromAceEvent = nil
943 end
944  
945 if not self.postInit then
946 local isReload = true
947 local function func()
948 self.postInit = true
949 self:TriggerEvent("AceEvent_FullyInitialized")
950 if self.registry["CHAT_MSG_CHANNEL_NOTICE"] and self.registry["CHAT_MSG_CHANNEL_NOTICE"][self] then
951 self:UnregisterEvent("CHAT_MSG_CHANNEL_NOTICE")
952 end
953 if self.registry["MEETINGSTONE_CHANGED"] and self.registry["MEETINGSTONE_CHANGED"][self] then
954 self:UnregisterEvent("MEETINGSTONE_CHANGED")
955 end
956 if self.registry["MINIMAP_ZONE_CHANGED"] and self.registry["MINIMAP_ZONE_CHANGED"][self] then
957 self:UnregisterEvent("MINIMAP_ZONE_CHANGED")
958 end
959 if self.registry["LANGUAGE_LIST_CHANGED"] and self.registry["LANGUAGE_LIST_CHANGED"][self] then
960 self:UnregisterEvent("LANGUAGE_LIST_CHANGED")
961 end
962 end
963 registeringFromAceEvent = true
964 local f = function()
965 self.playerLogin = true
966 self:ScheduleEvent("AceEvent_FullyInitialized", func, 1)
967 end
968 self:RegisterEvent("MEETINGSTONE_CHANGED", f, true)
969 self:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE", function()
970 self:ScheduleEvent("AceEvent_FullyInitialized", func, 0.05)
971 end)
972 self:RegisterEvent("LANGUAGE_LIST_CHANGED", function()
973 if self.registry["MEETINGSTONE_CHANGED"] and self.registry["MEETINGSTONE_CHANGED"][self] then
974 self:UnregisterEvent("MEETINGSTONE_CHANGED")
975 self:RegisterEvent("MINIMAP_ZONE_CHANGED", f, true)
976 end
977 end)
978 registeringFromAceEvent = nil
979 end
980  
981 self.super.activate(self, oldLib, oldDeactivate)
982 if oldLib then
983 oldDeactivate(oldLib)
984 end
985 end
986  
987 AceLibrary:Register(AceEvent, MAJOR_VERSION, MINOR_VERSION, AceEvent.activate)
988 AceEvent = AceLibrary(MAJOR_VERSION)