PageRenderTime 211ms CodeModel.GetById 48ms app.highlight 36ms RepoModel.GetById 114ms app.codeStats 0ms

/libs/AceEvent-2.0/AceEvent-2.0.lua

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