Mercurial > wow > mailopener
view Libs/CallbackHandler-1.0/CallbackHandler-1.0.lua @ 3:c6f0976069c7
Default value for the welcome / bye notification is now set to false
The mailframe checkbox now primarily toggles the mail opening, however if you hold shift you can still disable the entire addon
Now properly removes QuickAuction?s mail count
Now tracks when a mail lost all attachments rather than it being deleted in order to continue processing the next item (mail sent by players containing text should now work properly). This should also be good for a nice speed increase.
Added a variable called ?busy? to the MailOpener object indicating whether or not Mail Opener is currently working. Other addons (or macros) can retrieve it with ?LibStub("AceAddon-3.0"):GetAddon("MailOpener").busy?
A mail refresh from the Postal service should no longer occur while mail is being opened but will happen instantly afterwards.
Postal?s module toggling will now be handled by Postal itself.
Added a short summary to the top of all modules for other developers.
The time remaining until next mail box refresh should be displayed for as long as Mail Opener can be sure.
| author | Zerotorescue |
|---|---|
| date | Tue, 07 Sep 2010 17:46:27 +0200 |
| parents | 823e33465b6e |
| children |
line wrap: on
line source
--[[ $Id: CallbackHandler-1.0.lua 895 2009-12-06 16:28:55Z nevcairiel $ ]] local MAJOR, MINOR = "CallbackHandler-1.0", 5 local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR) if not CallbackHandler then return end -- No upgrade needed local meta = {__index = function(tbl, key) tbl[key] = {} return tbl[key] end} -- Lua APIs local tconcat = table.concat local assert, error, loadstring = assert, error, loadstring local setmetatable, rawset, rawget = setmetatable, rawset, rawget local next, select, pairs, type, tostring = next, select, pairs, type, tostring -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded -- List them here for Mikk's FindGlobals script -- GLOBALS: geterrorhandler local xpcall = xpcall local function errorhandler(err) return geterrorhandler()(err) end local function CreateDispatcher(argCount) local code = [[ local next, xpcall, eh = ... local method, ARGS local function call() method(ARGS) end local function dispatch(handlers, ...) local index index, method = next(handlers) if not method then return end local OLD_ARGS = ARGS ARGS = ... repeat xpcall(call, eh) index, method = next(handlers, index) until not method ARGS = OLD_ARGS end return dispatch ]] local ARGS, OLD_ARGS = {}, {} for i = 1, argCount do ARGS[i], OLD_ARGS[i] = "arg"..i, "old_arg"..i end code = code:gsub("OLD_ARGS", tconcat(OLD_ARGS, ", ")):gsub("ARGS", tconcat(ARGS, ", ")) return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(next, xpcall, errorhandler) end local Dispatchers = setmetatable({}, {__index=function(self, argCount) local dispatcher = CreateDispatcher(argCount) rawset(self, argCount, dispatcher) return dispatcher end}) -------------------------------------------------------------------------- -- CallbackHandler:New -- -- target - target object to embed public APIs in -- RegisterName - name of the callback registration API, default "RegisterCallback" -- UnregisterName - name of the callback unregistration API, default "UnregisterCallback" -- UnregisterAllName - name of the API to unregister all callbacks, default "UnregisterAllCallbacks". false == don't publish this API. function CallbackHandler:New(target, RegisterName, UnregisterName, UnregisterAllName, OnUsed, OnUnused) -- TODO: Remove this after beta has gone out assert(not OnUsed and not OnUnused, "ACE-80: OnUsed/OnUnused are deprecated. Callbacks are now done to registry.OnUsed and registry.OnUnused") RegisterName = RegisterName or "RegisterCallback" UnregisterName = UnregisterName or "UnregisterCallback" if UnregisterAllName==nil then -- false is used to indicate "don't want this method" UnregisterAllName = "UnregisterAllCallbacks" end -- we declare all objects and exported APIs inside this closure to quickly gain access -- to e.g. function names, the "target" parameter, etc -- Create the registry object local events = setmetatable({}, meta) local registry = { recurse=0, events=events } -- registry:Fire() - fires the given event/message into the registry function registry:Fire(eventname, ...) if not rawget(events, eventname) or not next(events[eventname]) then return end local oldrecurse = registry.recurse registry.recurse = oldrecurse + 1 Dispatchers[select('#', ...) + 1](events[eventname], eventname, ...) registry.recurse = oldrecurse if registry.insertQueue and oldrecurse==0 then -- Something in one of our callbacks wanted to register more callbacks; they got queued for eventname,callbacks in pairs(registry.insertQueue) do local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten. for self,func in pairs(callbacks) do events[eventname][self] = func -- fire OnUsed callback? if first and registry.OnUsed then registry.OnUsed(registry, target, eventname) first = nil end end end registry.insertQueue = nil end end -- Registration of a callback, handles: -- self["method"], leads to self["method"](self, ...) -- self with function ref, leads to functionref(...) -- "addonId" (instead of self) with function ref, leads to functionref(...) -- all with an optional arg, which, if present, gets passed as first argument (after self if present) target[RegisterName] = function(self, eventname, method, ... --[[actually just a single arg]]) if type(eventname) ~= "string" then error("Usage: "..RegisterName.."(eventname, method[, arg]): 'eventname' - string expected.", 2) end method = method or eventname local first = not rawget(events, eventname) or not next(events[eventname]) -- test for empty before. not test for one member after. that one member may have been overwritten. if type(method) ~= "string" and type(method) ~= "function" then error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - string or function expected.", 2) end local regfunc if type(method) == "string" then -- self["method"] calling style if type(self) ~= "table" then error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): self was not a table?", 2) elseif self==target then error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): do not use Library:"..RegisterName.."(), use your own 'self'", 2) elseif type(self[method]) ~= "function" then error("Usage: "..RegisterName.."(\"eventname\", \"methodname\"): 'methodname' - method '"..tostring(method).."' not found on self.", 2) end if select("#",...)>=1 then -- this is not the same as testing for arg==nil! local arg=select(1,...) regfunc = function(...) self[method](self,arg,...) end else regfunc = function(...) self[method](self,...) end end else -- function ref with self=object or self="addonId" if type(self)~="table" and type(self)~="string" then error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string expected.", 2) end if select("#",...)>=1 then -- this is not the same as testing for arg==nil! local arg=select(1,...) regfunc = function(...) method(arg,...) end else regfunc = method end end if events[eventname][self] or registry.recurse<1 then -- if registry.recurse<1 then -- we're overwriting an existing entry, or not currently recursing. just set it. events[eventname][self] = regfunc -- fire OnUsed callback? if registry.OnUsed and first then registry.OnUsed(registry, target, eventname) end else -- we're currently processing a callback in this registry, so delay the registration of this new entry! -- yes, we're a bit wasteful on garbage, but this is a fringe case, so we're picking low implementation overhead over garbage efficiency registry.insertQueue = registry.insertQueue or setmetatable({},meta) registry.insertQueue[eventname][self] = regfunc end end -- Unregister a callback target[UnregisterName] = function(self, eventname) if not self or self==target then error("Usage: "..UnregisterName.."(eventname): bad 'self'", 2) end if type(eventname) ~= "string" then error("Usage: "..UnregisterName.."(eventname): 'eventname' - string expected.", 2) end if rawget(events, eventname) and events[eventname][self] then events[eventname][self] = nil -- Fire OnUnused callback? if registry.OnUnused and not next(events[eventname]) then registry.OnUnused(registry, target, eventname) end end if registry.insertQueue and rawget(registry.insertQueue, eventname) and registry.insertQueue[eventname][self] then registry.insertQueue[eventname][self] = nil end end -- OPTIONAL: Unregister all callbacks for given selfs/addonIds if UnregisterAllName then target[UnregisterAllName] = function(...) if select("#",...)<1 then error("Usage: "..UnregisterAllName.."([whatFor]): missing 'self' or \"addonId\" to unregister events for.", 2) end if select("#",...)==1 and ...==target then error("Usage: "..UnregisterAllName.."([whatFor]): supply a meaningful 'self' or \"addonId\"", 2) end for i=1,select("#",...) do local self = select(i,...) if registry.insertQueue then for eventname, callbacks in pairs(registry.insertQueue) do if callbacks[self] then callbacks[self] = nil end end end for eventname, callbacks in pairs(events) do if callbacks[self] then callbacks[self] = nil -- Fire OnUnused callback? if registry.OnUnused and not next(callbacks) then registry.OnUnused(registry, target, eventname) end end end end end end return registry end -- CallbackHandler purposefully does NOT do explicit embedding. Nor does it -- try to upgrade old implicit embeds since the system is selfcontained and -- relies on closures to work.
