comparison libs/AceEvent-2.0/AceEvent-2.0.lua @ 1:c11ca1d8ed91

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