57a5cdabdf
Imported from /srv/add01/wow-ascension/Interface/AddOns/Bartender4 — the build Ascension's WotLK 3.3.5 client ships. Single vendored drop: Ascension's build process bundles their custom patches with the standard CurseForge packager output (embedded libs), and the individual patches aren't published separately. Net delta vs Nevcairiel 4.4.2, excluding bundled libs and CRLF normalization: 21 files, 2213+/52- — the Ascension-specific adaptations for WotLK 3.3.5 hero classes / custom action systems. License: All rights reserved (per .toc).
347 lines
12 KiB
Lua
347 lines
12 KiB
Lua
--- AceConfigRegistry-3.0 handles central registration of options tables in use by addons and modules.\\
|
|
-- Options tables can be registered as raw tables, OR as function refs that return a table.\\
|
|
-- Such functions receive three arguments: "uiType", "uiName", "appName". \\
|
|
-- * Valid **uiTypes**: "cmd", "dropdown", "dialog". This is verified by the library at call time. \\
|
|
-- * The **uiName** field is expected to contain the full name of the calling addon, including version, e.g. "FooBar-1.0". This is verified by the library at call time.\\
|
|
-- * The **appName** field is the options table name as given at registration time \\
|
|
--
|
|
-- :IterateOptionsTables() (and :GetOptionsTable() if only given one argument) return a function reference that the requesting config handling addon must call with valid "uiType", "uiName".
|
|
-- @class file
|
|
-- @name AceConfigRegistry-3.0
|
|
-- @release $Id: AceConfigRegistry-3.0.lua 921 2010-05-09 15:49:14Z nevcairiel $
|
|
local MAJOR, MINOR = "AceConfigRegistry-3.0", 12
|
|
local AceConfigRegistry = LibStub:NewLibrary(MAJOR, MINOR)
|
|
|
|
if not AceConfigRegistry then return end
|
|
|
|
AceConfigRegistry.tables = AceConfigRegistry.tables or {}
|
|
|
|
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
|
|
|
|
if not AceConfigRegistry.callbacks then
|
|
AceConfigRegistry.callbacks = CallbackHandler:New(AceConfigRegistry)
|
|
end
|
|
|
|
-- Lua APIs
|
|
local tinsert, tconcat = table.insert, table.concat
|
|
local strfind, strmatch = string.find, string.match
|
|
local type, tostring, select, pairs = type, tostring, select, pairs
|
|
local error, assert = error, assert
|
|
|
|
-----------------------------------------------------------------------
|
|
-- Validating options table consistency:
|
|
|
|
|
|
AceConfigRegistry.validated = {
|
|
-- list of options table names ran through :ValidateOptionsTable automatically.
|
|
-- CLEARED ON PURPOSE, since newer versions may have newer validators
|
|
cmd = {},
|
|
dropdown = {},
|
|
dialog = {},
|
|
}
|
|
|
|
|
|
|
|
local function err(msg, errlvl, ...)
|
|
local t = {}
|
|
for i=select("#",...),1,-1 do
|
|
tinsert(t, (select(i, ...)))
|
|
end
|
|
error(MAJOR..":ValidateOptionsTable(): "..tconcat(t,".")..msg, errlvl+2)
|
|
end
|
|
|
|
|
|
local isstring={["string"]=true, _="string"}
|
|
local isstringfunc={["string"]=true,["function"]=true, _="string or funcref"}
|
|
local istable={["table"]=true, _="table"}
|
|
local ismethodtable={["table"]=true,["string"]=true,["function"]=true, _="methodname, funcref or table"}
|
|
local optstring={["nil"]=true,["string"]=true, _="string"}
|
|
local optstringfunc={["nil"]=true,["string"]=true,["function"]=true, _="string or funcref"}
|
|
local optnumber={["nil"]=true,["number"]=true, _="number"}
|
|
local optmethod={["nil"]=true,["string"]=true,["function"]=true, _="methodname or funcref"}
|
|
local optmethodfalse={["nil"]=true,["string"]=true,["function"]=true,["boolean"]={[false]=true}, _="methodname, funcref or false"}
|
|
local optmethodnumber={["nil"]=true,["string"]=true,["function"]=true,["number"]=true, _="methodname, funcref or number"}
|
|
local optmethodtable={["nil"]=true,["string"]=true,["function"]=true,["table"]=true, _="methodname, funcref or table"}
|
|
local optmethodbool={["nil"]=true,["string"]=true,["function"]=true,["boolean"]=true, _="methodname, funcref or boolean"}
|
|
local opttable={["nil"]=true,["table"]=true, _="table"}
|
|
local optbool={["nil"]=true,["boolean"]=true, _="boolean"}
|
|
local optboolnumber={["nil"]=true,["boolean"]=true,["number"]=true, _="boolean or number"}
|
|
|
|
local basekeys={
|
|
type=isstring,
|
|
name=isstringfunc,
|
|
desc=optstringfunc,
|
|
descStyle=optstring,
|
|
order=optmethodnumber,
|
|
validate=optmethodfalse,
|
|
confirm=optmethodbool,
|
|
confirmText=optstring,
|
|
disabled=optmethodbool,
|
|
hidden=optmethodbool,
|
|
guiHidden=optmethodbool,
|
|
dialogHidden=optmethodbool,
|
|
dropdownHidden=optmethodbool,
|
|
cmdHidden=optmethodbool,
|
|
icon=optstringfunc,
|
|
iconCoords=optmethodtable,
|
|
handler=opttable,
|
|
get=optmethodfalse,
|
|
set=optmethodfalse,
|
|
func=optmethodfalse,
|
|
arg={["*"]=true},
|
|
width=optstring,
|
|
}
|
|
|
|
local typedkeys={
|
|
header={},
|
|
description={
|
|
image=optstringfunc,
|
|
imageCoords=optmethodtable,
|
|
imageHeight=optnumber,
|
|
imageWidth=optnumber,
|
|
fontSize=optstringfunc,
|
|
},
|
|
group={
|
|
args=istable,
|
|
plugins=opttable,
|
|
inline=optbool,
|
|
cmdInline=optbool,
|
|
guiInline=optbool,
|
|
dropdownInline=optbool,
|
|
dialogInline=optbool,
|
|
childGroups=optstring,
|
|
},
|
|
execute={
|
|
image=optstringfunc,
|
|
imageCoords=optmethodtable,
|
|
imageHeight=optnumber,
|
|
imageWidth=optnumber,
|
|
},
|
|
input={
|
|
pattern=optstring,
|
|
usage=optstring,
|
|
control=optstring,
|
|
dialogControl=optstring,
|
|
dropdownControl=optstring,
|
|
multiline=optboolnumber,
|
|
},
|
|
toggle={
|
|
tristate=optbool,
|
|
image=optstringfunc,
|
|
imageCoords=optmethodtable,
|
|
},
|
|
tristate={
|
|
},
|
|
range={
|
|
min=optnumber,
|
|
softMin=optnumber,
|
|
max=optnumber,
|
|
softMax=optnumber,
|
|
step=optnumber,
|
|
bigStep=optnumber,
|
|
isPercent=optbool,
|
|
},
|
|
select={
|
|
values=ismethodtable,
|
|
style={
|
|
["nil"]=true,
|
|
["string"]={dropdown=true,radio=true},
|
|
_="string: 'dropdown' or 'radio'"
|
|
},
|
|
control=optstring,
|
|
dialogControl=optstring,
|
|
dropdownControl=optstring,
|
|
},
|
|
multiselect={
|
|
values=ismethodtable,
|
|
style=optstring,
|
|
tristate=optbool,
|
|
control=optstring,
|
|
dialogControl=optstring,
|
|
dropdownControl=optstring,
|
|
},
|
|
color={
|
|
hasAlpha=optbool,
|
|
},
|
|
keybinding={
|
|
-- TODO
|
|
},
|
|
}
|
|
|
|
local function validateKey(k,errlvl,...)
|
|
errlvl=(errlvl or 0)+1
|
|
if type(k)~="string" then
|
|
err("["..tostring(k).."] - key is not a string", errlvl,...)
|
|
end
|
|
if strfind(k, "[%c\127]") then
|
|
err("["..tostring(k).."] - key name contained control characters", errlvl,...)
|
|
end
|
|
end
|
|
|
|
local function validateVal(v, oktypes, errlvl,...)
|
|
errlvl=(errlvl or 0)+1
|
|
local isok=oktypes[type(v)] or oktypes["*"]
|
|
|
|
if not isok then
|
|
err(": expected a "..oktypes._..", got '"..tostring(v).."'", errlvl,...)
|
|
end
|
|
if type(isok)=="table" then -- isok was a table containing specific values to be tested for!
|
|
if not isok[v] then
|
|
err(": did not expect "..type(v).." value '"..tostring(v).."'", errlvl,...)
|
|
end
|
|
end
|
|
end
|
|
|
|
local function validate(options,errlvl,...)
|
|
errlvl=(errlvl or 0)+1
|
|
-- basic consistency
|
|
if type(options)~="table" then
|
|
err(": expected a table, got a "..type(options), errlvl,...)
|
|
end
|
|
if type(options.type)~="string" then
|
|
err(".type: expected a string, got a "..type(options.type), errlvl,...)
|
|
end
|
|
|
|
-- get type and 'typedkeys' member
|
|
local tk = typedkeys[options.type]
|
|
if not tk then
|
|
err(".type: unknown type '"..options.type.."'", errlvl,...)
|
|
end
|
|
|
|
-- make sure that all options[] are known parameters
|
|
for k,v in pairs(options) do
|
|
if not (tk[k] or basekeys[k]) then
|
|
err(": unknown parameter", errlvl,tostring(k),...)
|
|
end
|
|
end
|
|
|
|
-- verify that required params are there, and that everything is the right type
|
|
for k,oktypes in pairs(basekeys) do
|
|
validateVal(options[k], oktypes, errlvl,k,...)
|
|
end
|
|
for k,oktypes in pairs(tk) do
|
|
validateVal(options[k], oktypes, errlvl,k,...)
|
|
end
|
|
|
|
-- extra logic for groups
|
|
if options.type=="group" then
|
|
for k,v in pairs(options.args) do
|
|
validateKey(k,errlvl,"args",...)
|
|
validate(v, errlvl,k,"args",...)
|
|
end
|
|
if options.plugins then
|
|
for plugname,plugin in pairs(options.plugins) do
|
|
if type(plugin)~="table" then
|
|
err(": expected a table, got '"..tostring(plugin).."'", errlvl,tostring(plugname),"plugins",...)
|
|
end
|
|
for k,v in pairs(plugin) do
|
|
validateKey(k,errlvl,tostring(plugname),"plugins",...)
|
|
validate(v, errlvl,k,tostring(plugname),"plugins",...)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
--- Validates basic structure and integrity of an options table \\
|
|
-- Does NOT verify that get/set etc actually exist, since they can be defined at any depth
|
|
-- @param options The table to be validated
|
|
-- @param name The name of the table to be validated (shown in any error message)
|
|
-- @param errlvl (optional number) error level offset, default 0 (=errors point to the function calling :ValidateOptionsTable)
|
|
function AceConfigRegistry:ValidateOptionsTable(options,name,errlvl)
|
|
errlvl=(errlvl or 0)+1
|
|
name = name or "Optionstable"
|
|
if not options.name then
|
|
options.name=name -- bit of a hack, the root level doesn't really need a .name :-/
|
|
end
|
|
validate(options,errlvl,name)
|
|
end
|
|
|
|
--- Fires a "ConfigTableChange" callback for those listening in on it, allowing config GUIs to refresh.
|
|
-- You should call this function if your options table changed from any outside event, like a game event
|
|
-- or a timer.
|
|
-- @param appName The application name as given to `:RegisterOptionsTable()`
|
|
function AceConfigRegistry:NotifyChange(appName)
|
|
if not AceConfigRegistry.tables[appName] then return end
|
|
AceConfigRegistry.callbacks:Fire("ConfigTableChange", appName)
|
|
end
|
|
|
|
-- -------------------------------------------------------------------
|
|
-- Registering and retreiving options tables:
|
|
|
|
|
|
-- validateGetterArgs: helper function for :GetOptionsTable (or, rather, the getter functions returned by it)
|
|
|
|
local function validateGetterArgs(uiType, uiName, errlvl)
|
|
errlvl=(errlvl or 0)+2
|
|
if uiType~="cmd" and uiType~="dropdown" and uiType~="dialog" then
|
|
error(MAJOR..": Requesting options table: 'uiType' - invalid configuration UI type, expected 'cmd', 'dropdown' or 'dialog'", errlvl)
|
|
end
|
|
if not strmatch(uiName, "[A-Za-z]%-[0-9]") then -- Expecting e.g. "MyLib-1.2"
|
|
error(MAJOR..": Requesting options table: 'uiName' - badly formatted or missing version number. Expected e.g. 'MyLib-1.2'", errlvl)
|
|
end
|
|
end
|
|
|
|
--- Register an options table with the config registry.
|
|
-- @param appName The application name as given to `:RegisterOptionsTable()`
|
|
-- @param options The options table, OR a function reference that generates it on demand. \\
|
|
-- See the top of the page for info on arguments passed to such functions.
|
|
function AceConfigRegistry:RegisterOptionsTable(appName, options)
|
|
if type(options)=="table" then
|
|
if options.type~="group" then -- quick sanity checker
|
|
error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - missing type='group' member in root group", 2)
|
|
end
|
|
AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl)
|
|
errlvl=(errlvl or 0)+1
|
|
validateGetterArgs(uiType, uiName, errlvl)
|
|
if not AceConfigRegistry.validated[uiType][appName] then
|
|
AceConfigRegistry:ValidateOptionsTable(options, appName, errlvl) -- upgradable
|
|
AceConfigRegistry.validated[uiType][appName] = true
|
|
end
|
|
return options
|
|
end
|
|
elseif type(options)=="function" then
|
|
AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl)
|
|
errlvl=(errlvl or 0)+1
|
|
validateGetterArgs(uiType, uiName, errlvl)
|
|
local tab = assert(options(uiType, uiName, appName))
|
|
if not AceConfigRegistry.validated[uiType][appName] then
|
|
AceConfigRegistry:ValidateOptionsTable(tab, appName, errlvl) -- upgradable
|
|
AceConfigRegistry.validated[uiType][appName] = true
|
|
end
|
|
return tab
|
|
end
|
|
else
|
|
error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - expected table or function reference", 2)
|
|
end
|
|
end
|
|
|
|
--- Returns an iterator of ["appName"]=funcref pairs
|
|
function AceConfigRegistry:IterateOptionsTables()
|
|
return pairs(AceConfigRegistry.tables)
|
|
end
|
|
|
|
|
|
|
|
|
|
--- Query the registry for a specific options table.
|
|
-- If only appName is given, a function is returned which you
|
|
-- can call with (uiType,uiName) to get the table.\\
|
|
-- If uiType&uiName are given, the table is returned.
|
|
-- @param appName The application name as given to `:RegisterOptionsTable()`
|
|
-- @param uiType The type of UI to get the table for, one of "cmd", "dropdown", "dialog"
|
|
-- @param uiName The name of the library/addon querying for the table, e.g. "MyLib-1.0"
|
|
function AceConfigRegistry:GetOptionsTable(appName, uiType, uiName)
|
|
local f = AceConfigRegistry.tables[appName]
|
|
if not f then
|
|
return nil
|
|
end
|
|
|
|
if uiType then
|
|
return f(uiType,uiName,1) -- get the table for us
|
|
else
|
|
return f -- return the function
|
|
end
|
|
end
|