flickerstreak@1: --[[ flickerstreak@1: Name: AceEvent-2.0 flickerstreak@1: Revision: $Rev: 19845 $ flickerstreak@1: Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team) flickerstreak@1: Inspired By: Ace 1.x by Turan (turan@gryphon.com) flickerstreak@1: Website: http://www.wowace.com/ flickerstreak@1: Documentation: http://www.wowace.com/index.php/AceEvent-2.0 flickerstreak@1: SVN: http://svn.wowace.com/root/trunk/Ace2/AceEvent-2.0 flickerstreak@1: Description: Mixin to allow for event handling, scheduling, and inter-addon flickerstreak@1: communication. flickerstreak@1: Dependencies: AceLibrary, AceOO-2.0 flickerstreak@1: ]] flickerstreak@1: flickerstreak@1: local MAJOR_VERSION = "AceEvent-2.0" flickerstreak@1: local MINOR_VERSION = "$Revision: 19845 $" flickerstreak@1: flickerstreak@1: if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end flickerstreak@1: if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end flickerstreak@1: flickerstreak@1: if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end flickerstreak@1: flickerstreak@1: local AceOO = AceLibrary:GetInstance("AceOO-2.0") flickerstreak@1: local Mixin = AceOO.Mixin flickerstreak@1: local AceEvent = Mixin { flickerstreak@1: "RegisterEvent", flickerstreak@1: "RegisterAllEvents", flickerstreak@1: "UnregisterEvent", flickerstreak@1: "UnregisterAllEvents", flickerstreak@1: "TriggerEvent", flickerstreak@1: "ScheduleEvent", flickerstreak@1: "ScheduleRepeatingEvent", flickerstreak@1: "CancelScheduledEvent", flickerstreak@1: "CancelAllScheduledEvents", flickerstreak@1: "IsEventRegistered", flickerstreak@1: "IsEventScheduled", flickerstreak@1: "RegisterBucketEvent", flickerstreak@1: "UnregisterBucketEvent", flickerstreak@1: "UnregisterAllBucketEvents", flickerstreak@1: "IsBucketEventRegistered", flickerstreak@1: } flickerstreak@1: flickerstreak@1: local weakKey = {__mode="k"} flickerstreak@1: flickerstreak@1: local FAKE_NIL flickerstreak@1: local RATE flickerstreak@1: flickerstreak@1: local eventsWhichHappenOnce = { flickerstreak@1: PLAYER_LOGIN = true, flickerstreak@1: AceEvent_FullyInitialized = true, flickerstreak@1: VARIABLES_LOADED = true, flickerstreak@1: PLAYER_LOGOUT = true, flickerstreak@1: } flickerstreak@1: local next = next flickerstreak@1: local pairs = pairs flickerstreak@1: local pcall = pcall flickerstreak@1: local type = type flickerstreak@1: local GetTime = GetTime flickerstreak@1: local gcinfo = gcinfo flickerstreak@1: local unpack = unpack flickerstreak@1: local geterrorhandler = geterrorhandler flickerstreak@1: flickerstreak@1: local registeringFromAceEvent flickerstreak@1: function AceEvent:RegisterEvent(event, method, once) flickerstreak@1: AceEvent:argCheck(event, 2, "string") flickerstreak@1: if self == AceEvent and not registeringFromAceEvent then flickerstreak@1: AceEvent:argCheck(method, 3, "function") flickerstreak@1: self = method flickerstreak@1: else flickerstreak@1: AceEvent:argCheck(method, 3, "string", "function", "nil", "boolean", "number") flickerstreak@1: if type(method) == "boolean" or type(method) == "number" then flickerstreak@1: AceEvent:argCheck(once, 4, "nil") flickerstreak@1: once, method = method, event flickerstreak@1: end flickerstreak@1: end flickerstreak@1: AceEvent:argCheck(once, 4, "number", "boolean", "nil") flickerstreak@1: if eventsWhichHappenOnce[event] then flickerstreak@1: once = true flickerstreak@1: end flickerstreak@1: local throttleRate flickerstreak@1: if type(once) == "number" then flickerstreak@1: throttleRate, once = once flickerstreak@1: end flickerstreak@1: if not method then flickerstreak@1: method = event flickerstreak@1: end flickerstreak@1: if type(method) == "string" and type(self[method]) ~= "function" then flickerstreak@1: AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method) flickerstreak@1: else flickerstreak@1: assert(type(method) == "function" or type(method) == "string") flickerstreak@1: end flickerstreak@1: flickerstreak@1: local AceEvent_registry = AceEvent.registry flickerstreak@1: if not AceEvent_registry[event] then flickerstreak@1: AceEvent_registry[event] = {} flickerstreak@1: AceEvent.frame:RegisterEvent(event) flickerstreak@1: end flickerstreak@1: flickerstreak@1: local remember = true flickerstreak@1: if AceEvent_registry[event][self] then flickerstreak@1: remember = false flickerstreak@1: end flickerstreak@1: AceEvent_registry[event][self] = method flickerstreak@1: flickerstreak@1: local AceEvent_onceRegistry = AceEvent.onceRegistry flickerstreak@1: if once then flickerstreak@1: if not AceEvent_onceRegistry then flickerstreak@1: AceEvent.onceRegistry = {} flickerstreak@1: AceEvent_onceRegistry = AceEvent.onceRegistry flickerstreak@1: end flickerstreak@1: if not AceEvent_onceRegistry[event] then flickerstreak@1: AceEvent_onceRegistry[event] = {} flickerstreak@1: end flickerstreak@1: AceEvent_onceRegistry[event][self] = true flickerstreak@1: else flickerstreak@1: if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then flickerstreak@1: AceEvent_onceRegistry[event][self] = nil flickerstreak@1: if not next(AceEvent_onceRegistry[event]) then flickerstreak@1: AceEvent_onceRegistry[event] = nil flickerstreak@1: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: flickerstreak@1: local AceEvent_throttleRegistry = AceEvent.throttleRegistry flickerstreak@1: if throttleRate then flickerstreak@1: if not AceEvent_throttleRegistry then flickerstreak@1: AceEvent.throttleRegistry = {} flickerstreak@1: AceEvent_throttleRegistry = AceEvent.throttleRegistry flickerstreak@1: end flickerstreak@1: if not AceEvent_throttleRegistry[event] then flickerstreak@1: AceEvent_throttleRegistry[event] = {} flickerstreak@1: end flickerstreak@1: if AceEvent_throttleRegistry[event][self] then flickerstreak@1: AceEvent_throttleRegistry[event][self] = nil flickerstreak@1: end flickerstreak@1: AceEvent_throttleRegistry[event][self] = setmetatable({}, weakKey) flickerstreak@1: local t = AceEvent_throttleRegistry[event][self] flickerstreak@1: t[RATE] = throttleRate flickerstreak@1: else flickerstreak@1: if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] then flickerstreak@1: if AceEvent_throttleRegistry[event][self] then flickerstreak@1: AceEvent_throttleRegistry[event][self] = nil flickerstreak@1: end flickerstreak@1: if not next(AceEvent_throttleRegistry[event]) then flickerstreak@1: AceEvent_throttleRegistry[event] = nil flickerstreak@1: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: flickerstreak@1: if remember then flickerstreak@1: AceEvent:TriggerEvent("AceEvent_EventRegistered", self, event) flickerstreak@1: end flickerstreak@1: end flickerstreak@1: flickerstreak@1: local ALL_EVENTS flickerstreak@1: flickerstreak@1: function AceEvent:RegisterAllEvents(method) flickerstreak@1: if self == AceEvent then flickerstreak@1: AceEvent:argCheck(method, 1, "function") flickerstreak@1: self = method flickerstreak@1: else flickerstreak@1: AceEvent:argCheck(method, 1, "string", "function") flickerstreak@1: if type(method) == "string" and type(self[method]) ~= "function" then flickerstreak@1: AceEvent:error("Cannot register all events to method %q, it does not exist", method) flickerstreak@1: end flickerstreak@1: end flickerstreak@1: flickerstreak@1: local AceEvent_registry = AceEvent.registry flickerstreak@1: if not AceEvent_registry[ALL_EVENTS] then flickerstreak@1: AceEvent_registry[ALL_EVENTS] = {} flickerstreak@1: AceEvent.frame:RegisterAllEvents() flickerstreak@1: end flickerstreak@1: flickerstreak@1: AceEvent_registry[ALL_EVENTS][self] = method flickerstreak@1: end flickerstreak@1: flickerstreak@1: local memstack, timestack = {}, {} flickerstreak@1: local memdiff, timediff flickerstreak@1: flickerstreak@1: local stack = setmetatable({}, {__mode='k'}) flickerstreak@1: function AceEvent:TriggerEvent(event, ...) flickerstreak@1: local tmp = next(stack) or {} flickerstreak@1: stack[tmp] = nil flickerstreak@1: if type(event) ~= "string" then flickerstreak@1: DEFAULT_CHAT_FRAME:AddMessage(debugstack()) flickerstreak@1: end flickerstreak@1: AceEvent:argCheck(event, 2, "string") flickerstreak@1: local AceEvent_registry = AceEvent.registry flickerstreak@1: 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 flickerstreak@1: return flickerstreak@1: end flickerstreak@1: local lastEvent = AceEvent.currentEvent flickerstreak@1: AceEvent.currentEvent = event flickerstreak@1: flickerstreak@1: local AceEvent_onceRegistry = AceEvent.onceRegistry flickerstreak@1: local AceEvent_debugTable = AceEvent.debugTable flickerstreak@1: if AceEvent_onceRegistry and AceEvent_onceRegistry[event] then flickerstreak@1: for obj, method in pairs(AceEvent_onceRegistry[event]) do flickerstreak@1: tmp[obj] = AceEvent_registry[event] and AceEvent_registry[event][obj] or nil flickerstreak@1: end flickerstreak@1: local obj = next(tmp) flickerstreak@1: while obj do flickerstreak@1: local mem, time flickerstreak@1: if AceEvent_debugTable then flickerstreak@1: if not AceEvent_debugTable[event] then flickerstreak@1: AceEvent_debugTable[event] = {} flickerstreak@1: end flickerstreak@1: if not AceEvent_debugTable[event][obj] then flickerstreak@1: AceEvent_debugTable[event][obj] = { flickerstreak@1: mem = 0, flickerstreak@1: time = 0, flickerstreak@1: count = 0, flickerstreak@1: } flickerstreak@1: end flickerstreak@1: if memdiff then flickerstreak@1: table.insert(memstack, memdiff) flickerstreak@1: table.insert(timestack, timediff) flickerstreak@1: end flickerstreak@1: memdiff, timediff = 0, 0 flickerstreak@1: mem, time = gcinfo(), GetTime() flickerstreak@1: end flickerstreak@1: local method = tmp[obj] flickerstreak@1: AceEvent.UnregisterEvent(obj, event) flickerstreak@1: if type(method) == "string" then flickerstreak@1: local obj_method = obj[method] flickerstreak@1: if obj_method then flickerstreak@1: local success, err = pcall(obj_method, obj, ...) flickerstreak@1: if not success then geterrorhandler()(err) end flickerstreak@1: end flickerstreak@1: elseif method then -- function flickerstreak@1: local success, err = pcall(method, ...) flickerstreak@1: if not success then geterrorhandler()(err) end flickerstreak@1: end flickerstreak@1: if AceEvent_debugTable then flickerstreak@1: local dmem, dtime = memdiff, timediff flickerstreak@1: mem, time = gcinfo() - mem - memdiff, GetTime() - time - timediff flickerstreak@1: AceEvent_debugTable[event][obj].mem = AceEvent_debugTable[event][obj].mem + mem flickerstreak@1: AceEvent_debugTable[event][obj].time = AceEvent_debugTable[event][obj].time + time flickerstreak@1: AceEvent_debugTable[event][obj].count = AceEvent_debugTable[event][obj].count + 1 flickerstreak@1: flickerstreak@1: memdiff, timediff = table.remove(memstack), table.remove(timestack) flickerstreak@1: if memdiff then flickerstreak@1: memdiff = memdiff + mem + dmem flickerstreak@1: timediff = timediff + time + dtime flickerstreak@1: end flickerstreak@1: end flickerstreak@1: tmp[obj] = nil flickerstreak@1: obj = next(tmp) flickerstreak@1: end flickerstreak@1: end flickerstreak@1: flickerstreak@1: local AceEvent_throttleRegistry = AceEvent.throttleRegistry flickerstreak@1: local throttleTable = AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] flickerstreak@1: if AceEvent_registry[event] then flickerstreak@1: for obj, method in pairs(AceEvent_registry[event]) do flickerstreak@1: tmp[obj] = method flickerstreak@1: end flickerstreak@1: local obj = next(tmp) flickerstreak@1: while obj do flickerstreak@1: local method = tmp[obj] flickerstreak@1: local continue = false flickerstreak@1: if throttleTable and throttleTable[obj] then flickerstreak@1: local a1 = ... flickerstreak@1: if a1 == nil then flickerstreak@1: a1 = FAKE_NIL flickerstreak@1: end flickerstreak@1: if not throttleTable[obj][a1] or GetTime() - throttleTable[obj][a1] >= throttleTable[obj][RATE] then flickerstreak@1: throttleTable[obj][a1] = GetTime() flickerstreak@1: else flickerstreak@1: continue = true flickerstreak@1: end flickerstreak@1: end flickerstreak@1: if not continue then flickerstreak@1: local mem, time flickerstreak@1: if AceEvent_debugTable then flickerstreak@1: if not AceEvent_debugTable[event] then flickerstreak@1: AceEvent_debugTable[event] = {} flickerstreak@1: end flickerstreak@1: if not AceEvent_debugTable[event][obj] then flickerstreak@1: AceEvent_debugTable[event][obj] = { flickerstreak@1: mem = 0, flickerstreak@1: time = 0, flickerstreak@1: count = 0, flickerstreak@1: } flickerstreak@1: end flickerstreak@1: if memdiff then flickerstreak@1: table.insert(memstack, memdiff) flickerstreak@1: table.insert(timestack, timediff) flickerstreak@1: end flickerstreak@1: memdiff, timediff = 0, 0 flickerstreak@1: mem, time = gcinfo(), GetTime() flickerstreak@1: end flickerstreak@1: if type(method) == "string" then flickerstreak@1: local obj_method = obj[method] flickerstreak@1: if obj_method then flickerstreak@1: local success, err = pcall(obj_method, obj, ...) flickerstreak@1: if not success then geterrorhandler()(err) end flickerstreak@1: end flickerstreak@1: elseif method then -- function flickerstreak@1: local success, err = pcall(method, ...) flickerstreak@1: if not success then geterrorhandler()(err) end flickerstreak@1: end flickerstreak@1: if AceEvent_debugTable then flickerstreak@1: local dmem, dtime = memdiff, timediff flickerstreak@1: mem, time = gcinfo() - mem - memdiff, GetTime() - time - timediff flickerstreak@1: AceEvent_debugTable[event][obj].mem = AceEvent_debugTable[event][obj].mem + mem flickerstreak@1: AceEvent_debugTable[event][obj].time = AceEvent_debugTable[event][obj].time + time flickerstreak@1: AceEvent_debugTable[event][obj].count = AceEvent_debugTable[event][obj].count + 1 flickerstreak@1: flickerstreak@1: memdiff, timediff = table.remove(memstack), table.remove(timestack) flickerstreak@1: if memdiff then flickerstreak@1: memdiff = memdiff + mem + dmem flickerstreak@1: timediff = timediff + time + dtime flickerstreak@1: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: tmp[obj] = nil flickerstreak@1: obj = next(tmp) flickerstreak@1: end flickerstreak@1: end flickerstreak@1: if AceEvent_registry[ALL_EVENTS] then flickerstreak@1: for obj, method in pairs(AceEvent_registry[ALL_EVENTS]) do flickerstreak@1: tmp[obj] = method flickerstreak@1: end flickerstreak@1: local obj = next(tmp) flickerstreak@1: while obj do flickerstreak@1: local method = tmp[obj] flickerstreak@1: local mem, time flickerstreak@1: if AceEvent_debugTable then flickerstreak@1: if not AceEvent_debugTable[event] then flickerstreak@1: AceEvent_debugTable[event] = {} flickerstreak@1: end flickerstreak@1: if not AceEvent_debugTable[event][obj] then flickerstreak@1: AceEvent_debugTable[event][obj] = {} flickerstreak@1: AceEvent_debugTable[event][obj].mem = 0 flickerstreak@1: AceEvent_debugTable[event][obj].time = 0 flickerstreak@1: AceEvent_debugTable[event][obj].count = 0 flickerstreak@1: end flickerstreak@1: if memdiff then flickerstreak@1: table.insert(memstack, memdiff) flickerstreak@1: table.insert(timestack, timediff) flickerstreak@1: end flickerstreak@1: memdiff, timediff = 0, 0 flickerstreak@1: mem, time = gcinfo(), GetTime() flickerstreak@1: end flickerstreak@1: if type(method) == "string" then flickerstreak@1: local obj_method = obj[method] flickerstreak@1: if obj_method then flickerstreak@1: obj_method(obj, ...) flickerstreak@1: local success, err = pcall(obj_method, obj, ...) flickerstreak@1: if not success then geterrorhandler()(err) end flickerstreak@1: end flickerstreak@1: elseif method then -- function flickerstreak@1: local success, err = pcall(method, ...) flickerstreak@1: if not success then geterrorhandler()(err) end flickerstreak@1: end flickerstreak@1: if AceEvent_debugTable then flickerstreak@1: local dmem, dtime = memdiff, timediff flickerstreak@1: mem, time = gcinfo() - mem - memdiff, GetTime() - time - timediff flickerstreak@1: AceEvent_debugTable[event][obj].mem = AceEvent_debugTable[event][obj].mem + mem flickerstreak@1: AceEvent_debugTable[event][obj].time = AceEvent_debugTable[event][obj].time + time flickerstreak@1: AceEvent_debugTable[event][obj].count = AceEvent_debugTable[event][obj].count + 1 flickerstreak@1: flickerstreak@1: memdiff, timediff = table.remove(memstack), table.remove(timestack) flickerstreak@1: if memdiff then flickerstreak@1: memdiff = memdiff + mem + dmem flickerstreak@1: timediff = timediff + time + dtime flickerstreak@1: end flickerstreak@1: end flickerstreak@1: tmp[obj] = nil flickerstreak@1: obj = next(tmp) flickerstreak@1: end flickerstreak@1: end flickerstreak@1: stack[tmp] = true flickerstreak@1: AceEvent.currentEvent = lastEvent flickerstreak@1: end flickerstreak@1: flickerstreak@1: local delayRegistry flickerstreak@1: local tmp = {} flickerstreak@1: local function OnUpdate() flickerstreak@1: local t = GetTime() flickerstreak@1: for k,v in pairs(delayRegistry) do flickerstreak@1: tmp[k] = true flickerstreak@1: end flickerstreak@1: for k in pairs(tmp) do flickerstreak@1: local v = delayRegistry[k] flickerstreak@1: if v then flickerstreak@1: local v_time = v.time flickerstreak@1: if not v_time then flickerstreak@1: delayRegistry[k] = nil flickerstreak@1: elseif v_time <= t then flickerstreak@1: local v_repeatDelay = v.repeatDelay flickerstreak@1: if v_repeatDelay then flickerstreak@1: -- use the event time, not the current time, else timing inaccuracies add up over time flickerstreak@1: v.time = v_time + v_repeatDelay flickerstreak@1: end flickerstreak@1: local event = v.event flickerstreak@1: local mem, time flickerstreak@1: if AceEvent_debugTable then flickerstreak@1: mem, time = gcinfo(), GetTime() flickerstreak@1: end flickerstreak@1: if type(event) == "function" then flickerstreak@1: local success, err = pcall(event, unpack(v)) flickerstreak@1: if not success then geterrorhandler()(err) end flickerstreak@1: else flickerstreak@1: AceEvent:TriggerEvent(event, unpack(v)) flickerstreak@1: end flickerstreak@1: if AceEvent_debugTable then flickerstreak@1: mem, time = gcinfo() - mem, GetTime() - time flickerstreak@1: v.mem = v.mem + mem flickerstreak@1: v.timeSpent = v.timeSpent + time flickerstreak@1: v.count = v.count + 1 flickerstreak@1: end flickerstreak@1: if not v_repeatDelay then flickerstreak@1: local x = delayRegistry[k] flickerstreak@1: if x and x.time == v_time then -- check if it was manually reset flickerstreak@1: delayRegistry[k] = nil flickerstreak@1: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: for k in pairs(tmp) do flickerstreak@1: tmp[k] = nil flickerstreak@1: end flickerstreak@1: if not next(delayRegistry) then flickerstreak@1: AceEvent.frame:Hide() flickerstreak@1: end flickerstreak@1: end flickerstreak@1: flickerstreak@1: local function ScheduleEvent(self, repeating, event, delay, ...) flickerstreak@1: local id flickerstreak@1: if type(event) == "string" or type(event) == "table" then flickerstreak@1: if type(event) == "table" then flickerstreak@1: if not delayRegistry or not delayRegistry[event] then flickerstreak@1: AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.") flickerstreak@1: end flickerstreak@1: end flickerstreak@1: if type(delay) ~= "number" then flickerstreak@1: id, event, delay = event, delay, ... flickerstreak@1: AceEvent:argCheck(event, 3, "string", "function", --[[ so message is right ]] "number") flickerstreak@1: AceEvent:argCheck(delay, 4, "number") flickerstreak@1: self:CancelScheduledEvent(id) flickerstreak@1: end flickerstreak@1: else flickerstreak@1: AceEvent:argCheck(event, 2, "string", "function") flickerstreak@1: AceEvent:argCheck(delay, 3, "number") flickerstreak@1: end flickerstreak@1: flickerstreak@1: if not delayRegistry then flickerstreak@1: AceEvent.delayRegistry = {} flickerstreak@1: delayRegistry = AceEvent.delayRegistry flickerstreak@1: AceEvent.frame:SetScript("OnUpdate", OnUpdate) flickerstreak@1: end flickerstreak@1: local t flickerstreak@1: if type(id) == "table" then flickerstreak@1: for k in pairs(id) do flickerstreak@1: id[k] = nil flickerstreak@1: end flickerstreak@1: t = id flickerstreak@1: for i = 2, select('#', ...) do flickerstreak@1: t[i-1] = select(i, ...) flickerstreak@1: end flickerstreak@1: elseif id then flickerstreak@1: t = { select(2, ...) } flickerstreak@1: else flickerstreak@1: t = { ... } flickerstreak@1: end flickerstreak@1: t.event = event flickerstreak@1: t.time = GetTime() + delay flickerstreak@1: t.self = self flickerstreak@1: t.id = id or t flickerstreak@1: t.repeatDelay = repeating and delay flickerstreak@1: if AceEvent_debugTable then flickerstreak@1: t.mem = 0 flickerstreak@1: t.count = 0 flickerstreak@1: t.timeSpent = 0 flickerstreak@1: end flickerstreak@1: delayRegistry[t.id] = t flickerstreak@1: AceEvent.frame:Show() flickerstreak@1: return t.id flickerstreak@1: end flickerstreak@1: flickerstreak@1: function AceEvent:ScheduleEvent(event, delay, ...) flickerstreak@1: if type(event) == "string" or type(event) == "table" then flickerstreak@1: if type(event) == "table" then flickerstreak@1: if not delayRegistry or not delayRegistry[event] then flickerstreak@1: AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.") flickerstreak@1: end flickerstreak@1: end flickerstreak@1: if type(delay) ~= "number" then flickerstreak@1: AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number") flickerstreak@1: AceEvent:argCheck(..., 4, "number") flickerstreak@1: end flickerstreak@1: else flickerstreak@1: AceEvent:argCheck(event, 2, "string", "function") flickerstreak@1: AceEvent:argCheck(delay, 3, "number") flickerstreak@1: end flickerstreak@1: flickerstreak@1: return ScheduleEvent(self, false, event, delay, ...) flickerstreak@1: end flickerstreak@1: flickerstreak@1: function AceEvent:ScheduleRepeatingEvent(event, delay, ...) flickerstreak@1: if type(event) == "string" or type(event) == "table" then flickerstreak@1: if type(event) == "table" then flickerstreak@1: if not delayRegistry or not delayRegistry[event] then flickerstreak@1: AceEvent:error("Bad argument #2 to `ScheduleEvent'. Improper id table fed in.") flickerstreak@1: end flickerstreak@1: end flickerstreak@1: if type(delay) ~= "number" then flickerstreak@1: AceEvent:argCheck(delay, 3, "string", "function", --[[ so message is right ]] "number") flickerstreak@1: AceEvent:argCheck(..., 4, "number") flickerstreak@1: end flickerstreak@1: else flickerstreak@1: AceEvent:argCheck(event, 2, "string", "function") flickerstreak@1: AceEvent:argCheck(delay, 3, "number") flickerstreak@1: end flickerstreak@1: flickerstreak@1: return ScheduleEvent(self, true, event, delay, ...) flickerstreak@1: end flickerstreak@1: flickerstreak@1: function AceEvent:CancelScheduledEvent(t) flickerstreak@1: AceEvent:argCheck(t, 2, "string", "table") flickerstreak@1: if delayRegistry then flickerstreak@1: local v = delayRegistry[t] flickerstreak@1: if v then flickerstreak@1: delayRegistry[t] = nil flickerstreak@1: if not next(delayRegistry) then flickerstreak@1: AceEvent.frame:Hide() flickerstreak@1: end flickerstreak@1: return true flickerstreak@1: end flickerstreak@1: end flickerstreak@1: return false flickerstreak@1: end flickerstreak@1: flickerstreak@1: function AceEvent:IsEventScheduled(t) flickerstreak@1: AceEvent:argCheck(t, 2, "string", "table") flickerstreak@1: if delayRegistry then flickerstreak@1: local v = delayRegistry[t] flickerstreak@1: if v then flickerstreak@1: return true, v.time - GetTime() flickerstreak@1: end flickerstreak@1: end flickerstreak@1: return false, nil flickerstreak@1: end flickerstreak@1: flickerstreak@1: function AceEvent:UnregisterEvent(event) flickerstreak@1: AceEvent:argCheck(event, 2, "string") flickerstreak@1: local AceEvent_registry = AceEvent.registry flickerstreak@1: if AceEvent_registry[event] and AceEvent_registry[event][self] then flickerstreak@1: AceEvent_registry[event][self] = nil flickerstreak@1: local AceEvent_onceRegistry = AceEvent.onceRegistry flickerstreak@1: if AceEvent_onceRegistry and AceEvent_onceRegistry[event] and AceEvent_onceRegistry[event][self] then flickerstreak@1: AceEvent_onceRegistry[event][self] = nil flickerstreak@1: if not next(AceEvent_onceRegistry[event]) then flickerstreak@1: AceEvent_onceRegistry[event] = nil flickerstreak@1: end flickerstreak@1: end flickerstreak@1: local AceEvent_throttleRegistry = AceEvent.throttleRegistry flickerstreak@1: if AceEvent_throttleRegistry and AceEvent_throttleRegistry[event] and AceEvent_throttleRegistry[event][self] then flickerstreak@1: AceEvent_throttleRegistry[event][self] = nil flickerstreak@1: if not next(AceEvent_throttleRegistry[event]) then flickerstreak@1: AceEvent_throttleRegistry[event] = nil flickerstreak@1: end flickerstreak@1: end flickerstreak@1: if not next(AceEvent_registry[event]) then flickerstreak@1: AceEvent_registry[event] = nil flickerstreak@1: if not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS]) then flickerstreak@1: AceEvent.frame:UnregisterEvent(event) flickerstreak@1: end flickerstreak@1: end flickerstreak@1: else flickerstreak@1: if self == AceEvent then flickerstreak@1: error(string.format("Cannot unregister event %q. Improperly unregistering from AceEvent-2.0.", event), 2) flickerstreak@1: else flickerstreak@1: AceEvent:error("Cannot unregister event %q. %q is not registered with it.", event, self) flickerstreak@1: end flickerstreak@1: end flickerstreak@1: AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event) flickerstreak@1: end flickerstreak@1: flickerstreak@1: function AceEvent:UnregisterAllEvents() flickerstreak@1: local AceEvent_registry = AceEvent.registry flickerstreak@1: if AceEvent_registry[ALL_EVENTS] and AceEvent_registry[ALL_EVENTS][self] then flickerstreak@1: AceEvent_registry[ALL_EVENTS][self] = nil flickerstreak@1: if not next(AceEvent_registry[ALL_EVENTS]) then flickerstreak@1: AceEvent.frame:UnregisterAllEvents() flickerstreak@1: for k,v in pairs(AceEvent_registry) do flickerstreak@1: if k ~= ALL_EVENTS then flickerstreak@1: AceEvent.frame:RegisterEvent(k) flickerstreak@1: end flickerstreak@1: end flickerstreak@1: AceEvent_registry[ALL_EVENTS] = nil flickerstreak@1: end flickerstreak@1: end flickerstreak@1: local first = true flickerstreak@1: for event, data in pairs(AceEvent_registry) do flickerstreak@1: if first then flickerstreak@1: if AceEvent_registry.AceEvent_EventUnregistered then flickerstreak@1: event = "AceEvent_EventUnregistered" flickerstreak@1: else flickerstreak@1: first = false flickerstreak@1: end flickerstreak@1: end flickerstreak@1: local x = data[self] flickerstreak@1: data[self] = nil flickerstreak@1: if x and event ~= ALL_EVENTS then flickerstreak@1: if not next(data) then flickerstreak@1: if not AceEvent_registry[ALL_EVENTS] or not next(AceEvent_registry[ALL_EVENTS]) then flickerstreak@1: AceEvent.frame:UnregisterEvent(event) flickerstreak@1: end flickerstreak@1: AceEvent_registry[event] = nil flickerstreak@1: end flickerstreak@1: AceEvent:TriggerEvent("AceEvent_EventUnregistered", self, event) flickerstreak@1: end flickerstreak@1: if first then flickerstreak@1: event = nil flickerstreak@1: end flickerstreak@1: end flickerstreak@1: if AceEvent.onceRegistry then flickerstreak@1: for event, data in pairs(AceEvent.onceRegistry) do flickerstreak@1: data[self] = nil flickerstreak@1: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: flickerstreak@1: function AceEvent:CancelAllScheduledEvents() flickerstreak@1: if delayRegistry then flickerstreak@1: for k,v in pairs(delayRegistry) do flickerstreak@1: if v.self == self then flickerstreak@1: delayRegistry[k] = nil flickerstreak@1: end flickerstreak@1: end flickerstreak@1: if not next(delayRegistry) then flickerstreak@1: AceEvent.frame:Hide() flickerstreak@1: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: flickerstreak@1: function AceEvent:IsEventRegistered(event) flickerstreak@1: AceEvent:argCheck(event, 2, "string") flickerstreak@1: local AceEvent_registry = AceEvent.registry flickerstreak@1: if self == AceEvent then flickerstreak@1: return AceEvent_registry[event] and next(AceEvent_registry[event]) and true or false flickerstreak@1: end flickerstreak@1: if AceEvent_registry[event] and AceEvent_registry[event][self] then flickerstreak@1: return true, AceEvent_registry[event][self] flickerstreak@1: end flickerstreak@1: return false, nil flickerstreak@1: end flickerstreak@1: flickerstreak@1: local bucketfunc flickerstreak@1: function AceEvent:RegisterBucketEvent(event, delay, method) flickerstreak@1: AceEvent:argCheck(event, 2, "string", "table") flickerstreak@1: if type(event) == "table" then flickerstreak@1: for k,v in pairs(event) do flickerstreak@1: if type(k) ~= "number" then flickerstreak@1: AceEvent:error("All keys to argument #2 to `RegisterBucketEvent' must be numbers.") flickerstreak@1: elseif type(v) ~= "string" then flickerstreak@1: AceEvent:error("All values to argument #2 to `RegisterBucketEvent' must be strings.") flickerstreak@1: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: AceEvent:argCheck(delay, 3, "number") flickerstreak@1: if AceEvent == self then flickerstreak@1: AceEvent:argCheck(method, 4, "function") flickerstreak@1: self = method flickerstreak@1: else flickerstreak@1: if type(event) == "string" then flickerstreak@1: AceEvent:argCheck(method, 4, "string", "function", "nil") flickerstreak@1: if not method then flickerstreak@1: method = event flickerstreak@1: end flickerstreak@1: else flickerstreak@1: AceEvent:argCheck(method, 4, "string", "function") flickerstreak@1: end flickerstreak@1: flickerstreak@1: if type(method) == "string" and type(self[method]) ~= "function" then flickerstreak@1: AceEvent:error("Cannot register event %q to method %q, it does not exist", event, method) flickerstreak@1: end flickerstreak@1: end flickerstreak@1: if not AceEvent.buckets then flickerstreak@1: AceEvent.buckets = {} flickerstreak@1: end flickerstreak@1: if not AceEvent.buckets[event] then flickerstreak@1: AceEvent.buckets[event] = {} flickerstreak@1: end flickerstreak@1: if not AceEvent.buckets[event][self] then flickerstreak@1: AceEvent.buckets[event][self] = { flickerstreak@1: current = {}, flickerstreak@1: self = self flickerstreak@1: } flickerstreak@1: else flickerstreak@1: AceEvent.CancelScheduledEvent(self, AceEvent.buckets[event][self].id) flickerstreak@1: end flickerstreak@1: local bucket = AceEvent.buckets[event][self] flickerstreak@1: bucket.method = method flickerstreak@1: flickerstreak@1: local func = function(arg1) flickerstreak@1: bucket.run = true flickerstreak@1: if arg1 then flickerstreak@1: bucket.current[arg1] = true flickerstreak@1: end flickerstreak@1: end flickerstreak@1: AceEvent.buckets[event][self].func = func flickerstreak@1: if type(event) == "string" then flickerstreak@1: AceEvent.RegisterEvent(self, event, func) flickerstreak@1: else flickerstreak@1: for _,v in ipairs(event) do flickerstreak@1: AceEvent.RegisterEvent(self, v, func) flickerstreak@1: end flickerstreak@1: end flickerstreak@1: if not bucketfunc then flickerstreak@1: bucketfunc = function(bucket) flickerstreak@1: local current = bucket.current flickerstreak@1: local method = bucket.method flickerstreak@1: local self = bucket.self flickerstreak@1: if bucket.run then flickerstreak@1: if type(method) == "string" then flickerstreak@1: self[method](self, current) flickerstreak@1: elseif method then -- function flickerstreak@1: method(current) flickerstreak@1: end flickerstreak@1: for k in pairs(current) do flickerstreak@1: current[k] = nil flickerstreak@1: k = nil flickerstreak@1: end flickerstreak@1: bucket.run = false flickerstreak@1: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: bucket.id = AceEvent.ScheduleRepeatingEvent(self, bucketfunc, delay, bucket) flickerstreak@1: end flickerstreak@1: flickerstreak@1: function AceEvent:IsBucketEventRegistered(event) flickerstreak@1: AceEvent:argCheck(event, 2, "string", "table") flickerstreak@1: return AceEvent.buckets and AceEvent.buckets[event] and AceEvent.buckets[event][self] flickerstreak@1: end flickerstreak@1: flickerstreak@1: function AceEvent:UnregisterBucketEvent(event) flickerstreak@1: AceEvent:argCheck(event, 2, "string", "table") flickerstreak@1: if not AceEvent.buckets or not AceEvent.buckets[event] or not AceEvent.buckets[event][self] then flickerstreak@1: AceEvent:error("Cannot unregister bucket event %q. %q is not registered with it.", event, self) flickerstreak@1: end flickerstreak@1: flickerstreak@1: local bucket = AceEvent.buckets[event][self] flickerstreak@1: flickerstreak@1: if type(event) == "string" then flickerstreak@1: AceEvent.UnregisterEvent(self, event) flickerstreak@1: else flickerstreak@1: for _,v in ipairs(event) do flickerstreak@1: AceEvent.UnregisterEvent(self, v) flickerstreak@1: end flickerstreak@1: end flickerstreak@1: AceEvent:CancelScheduledEvent(bucket.id) flickerstreak@1: flickerstreak@1: AceEvent.buckets[event][self] = nil flickerstreak@1: if not next(AceEvent.buckets[event]) then flickerstreak@1: AceEvent.buckets[event] = nil flickerstreak@1: end flickerstreak@1: end flickerstreak@1: flickerstreak@1: function AceEvent:UnregisterAllBucketEvents() flickerstreak@1: if not AceEvent.buckets or not next(AceEvent.buckets) then flickerstreak@1: return flickerstreak@1: end flickerstreak@1: for k,v in pairs(AceEvent.buckets) do flickerstreak@1: if v == self then flickerstreak@1: AceEvent.UnregisterBucketEvent(self, k) flickerstreak@1: k = nil flickerstreak@1: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: flickerstreak@1: function AceEvent:OnEmbedDisable(target) flickerstreak@1: self.UnregisterAllEvents(target) flickerstreak@1: flickerstreak@1: self.CancelAllScheduledEvents(target) flickerstreak@1: flickerstreak@1: self.UnregisterAllBucketEvents(target) flickerstreak@1: end flickerstreak@1: flickerstreak@1: function AceEvent:EnableDebugging() flickerstreak@1: if not self.debugTable then flickerstreak@1: self.debugTable = {} flickerstreak@1: flickerstreak@1: if delayRegistry then flickerstreak@1: for k,v in pairs(self.delayRegistry) do flickerstreak@1: if not v.mem then flickerstreak@1: v.mem = 0 flickerstreak@1: v.count = 0 flickerstreak@1: v.timeSpent = 0 flickerstreak@1: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: end flickerstreak@1: flickerstreak@1: function AceEvent:IsFullyInitialized() flickerstreak@1: return self.postInit or false flickerstreak@1: end flickerstreak@1: flickerstreak@1: function AceEvent:IsPostPlayerLogin() flickerstreak@1: return self.playerLogin or false flickerstreak@1: end flickerstreak@1: flickerstreak@1: local function activate(self, oldLib, oldDeactivate) flickerstreak@1: AceEvent = self flickerstreak@1: flickerstreak@1: if oldLib then flickerstreak@1: self.onceRegistry = oldLib.onceRegistry flickerstreak@1: self.throttleRegistry = oldLib.throttleRegistry flickerstreak@1: self.delayRegistry = oldLib.delayRegistry flickerstreak@1: self.buckets = oldLib.buckets flickerstreak@1: self.registry = oldLib.registry flickerstreak@1: self.frame = oldLib.frame flickerstreak@1: self.debugTable = oldLib.debugTable flickerstreak@1: self.playerLogin = oldLib.pew or DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.defaultLanguage and true flickerstreak@1: self.postInit = oldLib.postInit or self.playerLogin and ChatTypeInfo and ChatTypeInfo.WHISPER and ChatTypeInfo.WHISPER.r and true flickerstreak@1: self.ALL_EVENTS = oldLib.ALL_EVENTS flickerstreak@1: self.FAKE_NIL = oldLib.FAKE_NIL flickerstreak@1: self.RATE = oldLib.RATE flickerstreak@1: end flickerstreak@1: if not self.registry then flickerstreak@1: self.registry = {} flickerstreak@1: end flickerstreak@1: if not self.frame then flickerstreak@1: self.frame = CreateFrame("Frame", "AceEvent20Frame") flickerstreak@1: end flickerstreak@1: if not self.ALL_EVENTS then flickerstreak@1: self.ALL_EVENTS = {} flickerstreak@1: end flickerstreak@1: if not self.FAKE_NIL then flickerstreak@1: self.FAKE_NIL = {} flickerstreak@1: end flickerstreak@1: if not self.RATE then flickerstreak@1: self.RATE = {} flickerstreak@1: end flickerstreak@1: ALL_EVENTS = self.ALL_EVENTS flickerstreak@1: FAKE_NIL = self.FAKE_NIL flickerstreak@1: RATE = self.RATE flickerstreak@1: local inPlw = false flickerstreak@1: local blacklist = { flickerstreak@1: UNIT_INVENTORY_CHANGED = true, flickerstreak@1: BAG_UPDATE = true, flickerstreak@1: ITEM_LOCK_CHANGED = true, flickerstreak@1: ACTIONBAR_SLOT_CHANGED = true, flickerstreak@1: } flickerstreak@1: self.frame:SetScript("OnEvent", function(_, event, ...) flickerstreak@1: if event == "PLAYER_ENTERING_WORLD" then flickerstreak@1: inPlw = false flickerstreak@1: elseif event == "PLAYER_LEAVING_WORLD" then flickerstreak@1: inPlw = true flickerstreak@1: end flickerstreak@1: if event and (not inPlw or not blacklist[event]) then flickerstreak@1: self:TriggerEvent(event, ...) flickerstreak@1: end flickerstreak@1: end) flickerstreak@1: if self.delayRegistry then flickerstreak@1: delayRegistry = self.delayRegistry flickerstreak@1: self.frame:SetScript("OnUpdate", OnUpdate) flickerstreak@1: end flickerstreak@1: flickerstreak@1: self:UnregisterAllEvents() flickerstreak@1: self:CancelAllScheduledEvents() flickerstreak@1: flickerstreak@1: registeringFromAceEvent = true flickerstreak@1: self:RegisterEvent("LOOT_OPENED", function() flickerstreak@1: SendAddonMessage("LOOT_OPENED", "", "RAID") flickerstreak@1: end) flickerstreak@1: registeringFromAceEvent = nil flickerstreak@1: flickerstreak@1: if not self.playerLogin then flickerstreak@1: registeringFromAceEvent = true flickerstreak@1: self:RegisterEvent("PLAYER_LOGIN", function() flickerstreak@1: self.playerLogin = true flickerstreak@1: end, true) flickerstreak@1: registeringFromAceEvent = nil flickerstreak@1: end flickerstreak@1: flickerstreak@1: if not self.postInit then flickerstreak@1: local isReload = true flickerstreak@1: local function func() flickerstreak@1: self.postInit = true flickerstreak@1: self:TriggerEvent("AceEvent_FullyInitialized") flickerstreak@1: if self.registry["CHAT_MSG_CHANNEL_NOTICE"] and self.registry["CHAT_MSG_CHANNEL_NOTICE"][self] then flickerstreak@1: self:UnregisterEvent("CHAT_MSG_CHANNEL_NOTICE") flickerstreak@1: end flickerstreak@1: if self.registry["MEETINGSTONE_CHANGED"] and self.registry["MEETINGSTONE_CHANGED"][self] then flickerstreak@1: self:UnregisterEvent("MEETINGSTONE_CHANGED") flickerstreak@1: end flickerstreak@1: if self.registry["MINIMAP_ZONE_CHANGED"] and self.registry["MINIMAP_ZONE_CHANGED"][self] then flickerstreak@1: self:UnregisterEvent("MINIMAP_ZONE_CHANGED") flickerstreak@1: end flickerstreak@1: if self.registry["LANGUAGE_LIST_CHANGED"] and self.registry["LANGUAGE_LIST_CHANGED"][self] then flickerstreak@1: self:UnregisterEvent("LANGUAGE_LIST_CHANGED") flickerstreak@1: end flickerstreak@1: end flickerstreak@1: registeringFromAceEvent = true flickerstreak@1: local f = function() flickerstreak@1: self.playerLogin = true flickerstreak@1: self:ScheduleEvent("AceEvent_FullyInitialized", func, 1) flickerstreak@1: end flickerstreak@1: self:RegisterEvent("MEETINGSTONE_CHANGED", f, true) flickerstreak@1: self:RegisterEvent("CHAT_MSG_CHANNEL_NOTICE", function() flickerstreak@1: self:ScheduleEvent("AceEvent_FullyInitialized", func, 0.05) flickerstreak@1: end) flickerstreak@1: self:RegisterEvent("LANGUAGE_LIST_CHANGED", function() flickerstreak@1: if self.registry["MEETINGSTONE_CHANGED"] and self.registry["MEETINGSTONE_CHANGED"][self] then flickerstreak@1: registeringFromAceEvent = true flickerstreak@1: self:UnregisterEvent("MEETINGSTONE_CHANGED") flickerstreak@1: self:RegisterEvent("MINIMAP_ZONE_CHANGED", f, true) flickerstreak@1: registeringFromAceEvent = nil flickerstreak@1: end flickerstreak@1: end) flickerstreak@1: self:ScheduleEvent("AceEvent_FullyInitialized", func, 10) flickerstreak@1: registeringFromAceEvent = nil flickerstreak@1: end flickerstreak@1: flickerstreak@1: self:activate(oldLib, oldDeactivate) flickerstreak@1: if oldLib then flickerstreak@1: oldDeactivate(oldLib) flickerstreak@1: end flickerstreak@1: end flickerstreak@1: flickerstreak@1: AceLibrary:Register(AceEvent, MAJOR_VERSION, MINOR_VERSION, activate)