-
-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
275 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
202 changes: 202 additions & 0 deletions
202
AzeriteUI/Libs/CallbackHandler-1.0/CallbackHandler-1.0.lua
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,202 @@ | ||
--[[ $Id: CallbackHandler-1.0.lua 26 2022-12-12 15:09:39Z nevcairiel $ ]] | ||
local MAJOR, MINOR = "CallbackHandler-1.0", 8 | ||
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 securecallfunction, error = securecallfunction, error | ||
local setmetatable, rawget = setmetatable, rawget | ||
local next, select, pairs, type, tostring = next, select, pairs, type, tostring | ||
|
||
|
||
local function Dispatch(handlers, ...) | ||
local index, method = next(handlers) | ||
if not method then return end | ||
repeat | ||
securecallfunction(method, ...) | ||
index, method = next(handlers, index) | ||
until not method | ||
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(_self, target, RegisterName, UnregisterName, UnregisterAllName) | ||
|
||
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 | ||
|
||
Dispatch(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 event,callbacks in pairs(registry.insertQueue) do | ||
local first = not rawget(events, event) or not next(events[event]) -- test for empty before. not test for one member after. that one member may have been overwritten. | ||
for object,func in pairs(callbacks) do | ||
events[event][object] = func | ||
-- fire OnUsed callback? | ||
if first and registry.OnUsed then | ||
registry.OnUsed(registry, target, event) | ||
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" or self=thread | ||
if type(self)~="table" and type(self)~="string" and type(self)~="thread" then | ||
error("Usage: "..RegisterName.."(self or \"addonId\", eventname, method): 'self or addonId': table or string or thread 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. | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ | ||
..\FrameXML\UI.xsd"> | ||
<Script file="CallbackHandler-1.0.lua"/> | ||
</Ui> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
-- $Id: LibStub.lua 103 2014-10-16 03:02:50Z mikk $ | ||
-- LibStub is a simple versioning stub meant for use in Libraries. http://www.wowace.com/addons/libstub/ for more info | ||
-- LibStub is hereby placed in the Public Domain | ||
-- Credits: Kaelten, Cladhaire, ckknight, Mikk, Ammo, Nevcairiel, joshborke | ||
local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 2 -- NEVER MAKE THIS AN SVN REVISION! IT NEEDS TO BE USABLE IN ALL REPOS! | ||
local LibStub = _G[LIBSTUB_MAJOR] | ||
|
||
-- Check to see is this version of the stub is obsolete | ||
if not LibStub or LibStub.minor < LIBSTUB_MINOR then | ||
LibStub = LibStub or {libs = {}, minors = {} } | ||
_G[LIBSTUB_MAJOR] = LibStub | ||
LibStub.minor = LIBSTUB_MINOR | ||
|
||
-- LibStub:NewLibrary(major, minor) | ||
-- major (string) - the major version of the library | ||
-- minor (string or number ) - the minor version of the library | ||
-- | ||
-- returns nil if a newer or same version of the lib is already present | ||
-- returns empty library object or old library object if upgrade is needed | ||
function LibStub:NewLibrary(major, minor) | ||
assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)") | ||
minor = assert(tonumber(strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.") | ||
|
||
local oldminor = self.minors[major] | ||
if oldminor and oldminor >= minor then return nil end | ||
self.minors[major], self.libs[major] = minor, self.libs[major] or {} | ||
return self.libs[major], oldminor | ||
end | ||
|
||
-- LibStub:GetLibrary(major, [silent]) | ||
-- major (string) - the major version of the library | ||
-- silent (boolean) - if true, library is optional, silently return nil if its not found | ||
-- | ||
-- throws an error if the library can not be found (except silent is set) | ||
-- returns the library object if found | ||
function LibStub:GetLibrary(major, silent) | ||
if not self.libs[major] and not silent then | ||
error(("Cannot find a library instance of %q."):format(tostring(major)), 2) | ||
end | ||
return self.libs[major], self.minors[major] | ||
end | ||
|
||
-- LibStub:IterateLibraries() | ||
-- | ||
-- Returns an iterator for the currently registered libraries | ||
function LibStub:IterateLibraries() | ||
return pairs(self.libs) | ||
end | ||
|
||
setmetatable(LibStub, { __call = LibStub.GetLibrary }) | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters