annotate Libs/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua @ 8:1b2d819b4fa8

Now using the global MailAddonBusy to indicate MailOpener is busy, read comments in Core.lua for more info. Default status is now ?enabled without automatic mail opening? to let first time users look around before MailOpener messes up their heads. A StaticPopupDialog will be added later to ask if they want to auto-enable. When ?enabled without automatic mail opening? is on and you toggle the mail opening checkbox on, mail opening will automatically start.
author Zerotorescue
date Thu, 09 Sep 2010 10:53:19 +0200
parents 823e33465b6e
children
rev   line source
Zerotorescue@0 1 --- AceConfigRegistry-3.0 handles central registration of options tables in use by addons and modules.\\
Zerotorescue@0 2 -- Options tables can be registered as raw tables, OR as function refs that return a table.\\
Zerotorescue@0 3 -- Such functions receive three arguments: "uiType", "uiName", "appName". \\
Zerotorescue@0 4 -- * Valid **uiTypes**: "cmd", "dropdown", "dialog". This is verified by the library at call time. \\
Zerotorescue@0 5 -- * 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.\\
Zerotorescue@0 6 -- * The **appName** field is the options table name as given at registration time \\
Zerotorescue@0 7 --
Zerotorescue@0 8 -- :IterateOptionsTables() (and :GetOptionsTable() if only given one argument) return a function reference that the requesting config handling addon must call with valid "uiType", "uiName".
Zerotorescue@0 9 -- @class file
Zerotorescue@0 10 -- @name AceConfigRegistry-3.0
Zerotorescue@0 11 -- @release $Id: AceConfigRegistry-3.0.lua 921 2010-05-09 15:49:14Z nevcairiel $
Zerotorescue@0 12 local MAJOR, MINOR = "AceConfigRegistry-3.0", 12
Zerotorescue@0 13 local AceConfigRegistry = LibStub:NewLibrary(MAJOR, MINOR)
Zerotorescue@0 14
Zerotorescue@0 15 if not AceConfigRegistry then return end
Zerotorescue@0 16
Zerotorescue@0 17 AceConfigRegistry.tables = AceConfigRegistry.tables or {}
Zerotorescue@0 18
Zerotorescue@0 19 local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0")
Zerotorescue@0 20
Zerotorescue@0 21 if not AceConfigRegistry.callbacks then
Zerotorescue@0 22 AceConfigRegistry.callbacks = CallbackHandler:New(AceConfigRegistry)
Zerotorescue@0 23 end
Zerotorescue@0 24
Zerotorescue@0 25 -- Lua APIs
Zerotorescue@0 26 local tinsert, tconcat = table.insert, table.concat
Zerotorescue@0 27 local strfind, strmatch = string.find, string.match
Zerotorescue@0 28 local type, tostring, select, pairs = type, tostring, select, pairs
Zerotorescue@0 29 local error, assert = error, assert
Zerotorescue@0 30
Zerotorescue@0 31 -----------------------------------------------------------------------
Zerotorescue@0 32 -- Validating options table consistency:
Zerotorescue@0 33
Zerotorescue@0 34
Zerotorescue@0 35 AceConfigRegistry.validated = {
Zerotorescue@0 36 -- list of options table names ran through :ValidateOptionsTable automatically.
Zerotorescue@0 37 -- CLEARED ON PURPOSE, since newer versions may have newer validators
Zerotorescue@0 38 cmd = {},
Zerotorescue@0 39 dropdown = {},
Zerotorescue@0 40 dialog = {},
Zerotorescue@0 41 }
Zerotorescue@0 42
Zerotorescue@0 43
Zerotorescue@0 44
Zerotorescue@0 45 local function err(msg, errlvl, ...)
Zerotorescue@0 46 local t = {}
Zerotorescue@0 47 for i=select("#",...),1,-1 do
Zerotorescue@0 48 tinsert(t, (select(i, ...)))
Zerotorescue@0 49 end
Zerotorescue@0 50 error(MAJOR..":ValidateOptionsTable(): "..tconcat(t,".")..msg, errlvl+2)
Zerotorescue@0 51 end
Zerotorescue@0 52
Zerotorescue@0 53
Zerotorescue@0 54 local isstring={["string"]=true, _="string"}
Zerotorescue@0 55 local isstringfunc={["string"]=true,["function"]=true, _="string or funcref"}
Zerotorescue@0 56 local istable={["table"]=true, _="table"}
Zerotorescue@0 57 local ismethodtable={["table"]=true,["string"]=true,["function"]=true, _="methodname, funcref or table"}
Zerotorescue@0 58 local optstring={["nil"]=true,["string"]=true, _="string"}
Zerotorescue@0 59 local optstringfunc={["nil"]=true,["string"]=true,["function"]=true, _="string or funcref"}
Zerotorescue@0 60 local optnumber={["nil"]=true,["number"]=true, _="number"}
Zerotorescue@0 61 local optmethod={["nil"]=true,["string"]=true,["function"]=true, _="methodname or funcref"}
Zerotorescue@0 62 local optmethodfalse={["nil"]=true,["string"]=true,["function"]=true,["boolean"]={[false]=true}, _="methodname, funcref or false"}
Zerotorescue@0 63 local optmethodnumber={["nil"]=true,["string"]=true,["function"]=true,["number"]=true, _="methodname, funcref or number"}
Zerotorescue@0 64 local optmethodtable={["nil"]=true,["string"]=true,["function"]=true,["table"]=true, _="methodname, funcref or table"}
Zerotorescue@0 65 local optmethodbool={["nil"]=true,["string"]=true,["function"]=true,["boolean"]=true, _="methodname, funcref or boolean"}
Zerotorescue@0 66 local opttable={["nil"]=true,["table"]=true, _="table"}
Zerotorescue@0 67 local optbool={["nil"]=true,["boolean"]=true, _="boolean"}
Zerotorescue@0 68 local optboolnumber={["nil"]=true,["boolean"]=true,["number"]=true, _="boolean or number"}
Zerotorescue@0 69
Zerotorescue@0 70 local basekeys={
Zerotorescue@0 71 type=isstring,
Zerotorescue@0 72 name=isstringfunc,
Zerotorescue@0 73 desc=optstringfunc,
Zerotorescue@0 74 descStyle=optstring,
Zerotorescue@0 75 order=optmethodnumber,
Zerotorescue@0 76 validate=optmethodfalse,
Zerotorescue@0 77 confirm=optmethodbool,
Zerotorescue@0 78 confirmText=optstring,
Zerotorescue@0 79 disabled=optmethodbool,
Zerotorescue@0 80 hidden=optmethodbool,
Zerotorescue@0 81 guiHidden=optmethodbool,
Zerotorescue@0 82 dialogHidden=optmethodbool,
Zerotorescue@0 83 dropdownHidden=optmethodbool,
Zerotorescue@0 84 cmdHidden=optmethodbool,
Zerotorescue@0 85 icon=optstringfunc,
Zerotorescue@0 86 iconCoords=optmethodtable,
Zerotorescue@0 87 handler=opttable,
Zerotorescue@0 88 get=optmethodfalse,
Zerotorescue@0 89 set=optmethodfalse,
Zerotorescue@0 90 func=optmethodfalse,
Zerotorescue@0 91 arg={["*"]=true},
Zerotorescue@0 92 width=optstring,
Zerotorescue@0 93 }
Zerotorescue@0 94
Zerotorescue@0 95 local typedkeys={
Zerotorescue@0 96 header={},
Zerotorescue@0 97 description={
Zerotorescue@0 98 image=optstringfunc,
Zerotorescue@0 99 imageCoords=optmethodtable,
Zerotorescue@0 100 imageHeight=optnumber,
Zerotorescue@0 101 imageWidth=optnumber,
Zerotorescue@0 102 fontSize=optstringfunc,
Zerotorescue@0 103 },
Zerotorescue@0 104 group={
Zerotorescue@0 105 args=istable,
Zerotorescue@0 106 plugins=opttable,
Zerotorescue@0 107 inline=optbool,
Zerotorescue@0 108 cmdInline=optbool,
Zerotorescue@0 109 guiInline=optbool,
Zerotorescue@0 110 dropdownInline=optbool,
Zerotorescue@0 111 dialogInline=optbool,
Zerotorescue@0 112 childGroups=optstring,
Zerotorescue@0 113 },
Zerotorescue@0 114 execute={
Zerotorescue@0 115 image=optstringfunc,
Zerotorescue@0 116 imageCoords=optmethodtable,
Zerotorescue@0 117 imageHeight=optnumber,
Zerotorescue@0 118 imageWidth=optnumber,
Zerotorescue@0 119 },
Zerotorescue@0 120 input={
Zerotorescue@0 121 pattern=optstring,
Zerotorescue@0 122 usage=optstring,
Zerotorescue@0 123 control=optstring,
Zerotorescue@0 124 dialogControl=optstring,
Zerotorescue@0 125 dropdownControl=optstring,
Zerotorescue@0 126 multiline=optboolnumber,
Zerotorescue@0 127 },
Zerotorescue@0 128 toggle={
Zerotorescue@0 129 tristate=optbool,
Zerotorescue@0 130 image=optstringfunc,
Zerotorescue@0 131 imageCoords=optmethodtable,
Zerotorescue@0 132 },
Zerotorescue@0 133 tristate={
Zerotorescue@0 134 },
Zerotorescue@0 135 range={
Zerotorescue@0 136 min=optnumber,
Zerotorescue@0 137 softMin=optnumber,
Zerotorescue@0 138 max=optnumber,
Zerotorescue@0 139 softMax=optnumber,
Zerotorescue@0 140 step=optnumber,
Zerotorescue@0 141 bigStep=optnumber,
Zerotorescue@0 142 isPercent=optbool,
Zerotorescue@0 143 },
Zerotorescue@0 144 select={
Zerotorescue@0 145 values=ismethodtable,
Zerotorescue@0 146 style={
Zerotorescue@0 147 ["nil"]=true,
Zerotorescue@0 148 ["string"]={dropdown=true,radio=true},
Zerotorescue@0 149 _="string: 'dropdown' or 'radio'"
Zerotorescue@0 150 },
Zerotorescue@0 151 control=optstring,
Zerotorescue@0 152 dialogControl=optstring,
Zerotorescue@0 153 dropdownControl=optstring,
Zerotorescue@0 154 },
Zerotorescue@0 155 multiselect={
Zerotorescue@0 156 values=ismethodtable,
Zerotorescue@0 157 style=optstring,
Zerotorescue@0 158 tristate=optbool,
Zerotorescue@0 159 control=optstring,
Zerotorescue@0 160 dialogControl=optstring,
Zerotorescue@0 161 dropdownControl=optstring,
Zerotorescue@0 162 },
Zerotorescue@0 163 color={
Zerotorescue@0 164 hasAlpha=optbool,
Zerotorescue@0 165 },
Zerotorescue@0 166 keybinding={
Zerotorescue@0 167 -- TODO
Zerotorescue@0 168 },
Zerotorescue@0 169 }
Zerotorescue@0 170
Zerotorescue@0 171 local function validateKey(k,errlvl,...)
Zerotorescue@0 172 errlvl=(errlvl or 0)+1
Zerotorescue@0 173 if type(k)~="string" then
Zerotorescue@0 174 err("["..tostring(k).."] - key is not a string", errlvl,...)
Zerotorescue@0 175 end
Zerotorescue@0 176 if strfind(k, "[%c\127]") then
Zerotorescue@0 177 err("["..tostring(k).."] - key name contained control characters", errlvl,...)
Zerotorescue@0 178 end
Zerotorescue@0 179 end
Zerotorescue@0 180
Zerotorescue@0 181 local function validateVal(v, oktypes, errlvl,...)
Zerotorescue@0 182 errlvl=(errlvl or 0)+1
Zerotorescue@0 183 local isok=oktypes[type(v)] or oktypes["*"]
Zerotorescue@0 184
Zerotorescue@0 185 if not isok then
Zerotorescue@0 186 err(": expected a "..oktypes._..", got '"..tostring(v).."'", errlvl,...)
Zerotorescue@0 187 end
Zerotorescue@0 188 if type(isok)=="table" then -- isok was a table containing specific values to be tested for!
Zerotorescue@0 189 if not isok[v] then
Zerotorescue@0 190 err(": did not expect "..type(v).." value '"..tostring(v).."'", errlvl,...)
Zerotorescue@0 191 end
Zerotorescue@0 192 end
Zerotorescue@0 193 end
Zerotorescue@0 194
Zerotorescue@0 195 local function validate(options,errlvl,...)
Zerotorescue@0 196 errlvl=(errlvl or 0)+1
Zerotorescue@0 197 -- basic consistency
Zerotorescue@0 198 if type(options)~="table" then
Zerotorescue@0 199 err(": expected a table, got a "..type(options), errlvl,...)
Zerotorescue@0 200 end
Zerotorescue@0 201 if type(options.type)~="string" then
Zerotorescue@0 202 err(".type: expected a string, got a "..type(options.type), errlvl,...)
Zerotorescue@0 203 end
Zerotorescue@0 204
Zerotorescue@0 205 -- get type and 'typedkeys' member
Zerotorescue@0 206 local tk = typedkeys[options.type]
Zerotorescue@0 207 if not tk then
Zerotorescue@0 208 err(".type: unknown type '"..options.type.."'", errlvl,...)
Zerotorescue@0 209 end
Zerotorescue@0 210
Zerotorescue@0 211 -- make sure that all options[] are known parameters
Zerotorescue@0 212 for k,v in pairs(options) do
Zerotorescue@0 213 if not (tk[k] or basekeys[k]) then
Zerotorescue@0 214 err(": unknown parameter", errlvl,tostring(k),...)
Zerotorescue@0 215 end
Zerotorescue@0 216 end
Zerotorescue@0 217
Zerotorescue@0 218 -- verify that required params are there, and that everything is the right type
Zerotorescue@0 219 for k,oktypes in pairs(basekeys) do
Zerotorescue@0 220 validateVal(options[k], oktypes, errlvl,k,...)
Zerotorescue@0 221 end
Zerotorescue@0 222 for k,oktypes in pairs(tk) do
Zerotorescue@0 223 validateVal(options[k], oktypes, errlvl,k,...)
Zerotorescue@0 224 end
Zerotorescue@0 225
Zerotorescue@0 226 -- extra logic for groups
Zerotorescue@0 227 if options.type=="group" then
Zerotorescue@0 228 for k,v in pairs(options.args) do
Zerotorescue@0 229 validateKey(k,errlvl,"args",...)
Zerotorescue@0 230 validate(v, errlvl,k,"args",...)
Zerotorescue@0 231 end
Zerotorescue@0 232 if options.plugins then
Zerotorescue@0 233 for plugname,plugin in pairs(options.plugins) do
Zerotorescue@0 234 if type(plugin)~="table" then
Zerotorescue@0 235 err(": expected a table, got '"..tostring(plugin).."'", errlvl,tostring(plugname),"plugins",...)
Zerotorescue@0 236 end
Zerotorescue@0 237 for k,v in pairs(plugin) do
Zerotorescue@0 238 validateKey(k,errlvl,tostring(plugname),"plugins",...)
Zerotorescue@0 239 validate(v, errlvl,k,tostring(plugname),"plugins",...)
Zerotorescue@0 240 end
Zerotorescue@0 241 end
Zerotorescue@0 242 end
Zerotorescue@0 243 end
Zerotorescue@0 244 end
Zerotorescue@0 245
Zerotorescue@0 246
Zerotorescue@0 247 --- Validates basic structure and integrity of an options table \\
Zerotorescue@0 248 -- Does NOT verify that get/set etc actually exist, since they can be defined at any depth
Zerotorescue@0 249 -- @param options The table to be validated
Zerotorescue@0 250 -- @param name The name of the table to be validated (shown in any error message)
Zerotorescue@0 251 -- @param errlvl (optional number) error level offset, default 0 (=errors point to the function calling :ValidateOptionsTable)
Zerotorescue@0 252 function AceConfigRegistry:ValidateOptionsTable(options,name,errlvl)
Zerotorescue@0 253 errlvl=(errlvl or 0)+1
Zerotorescue@0 254 name = name or "Optionstable"
Zerotorescue@0 255 if not options.name then
Zerotorescue@0 256 options.name=name -- bit of a hack, the root level doesn't really need a .name :-/
Zerotorescue@0 257 end
Zerotorescue@0 258 validate(options,errlvl,name)
Zerotorescue@0 259 end
Zerotorescue@0 260
Zerotorescue@0 261 --- Fires a "ConfigTableChange" callback for those listening in on it, allowing config GUIs to refresh.
Zerotorescue@0 262 -- You should call this function if your options table changed from any outside event, like a game event
Zerotorescue@0 263 -- or a timer.
Zerotorescue@0 264 -- @param appName The application name as given to `:RegisterOptionsTable()`
Zerotorescue@0 265 function AceConfigRegistry:NotifyChange(appName)
Zerotorescue@0 266 if not AceConfigRegistry.tables[appName] then return end
Zerotorescue@0 267 AceConfigRegistry.callbacks:Fire("ConfigTableChange", appName)
Zerotorescue@0 268 end
Zerotorescue@0 269
Zerotorescue@0 270 -- -------------------------------------------------------------------
Zerotorescue@0 271 -- Registering and retreiving options tables:
Zerotorescue@0 272
Zerotorescue@0 273
Zerotorescue@0 274 -- validateGetterArgs: helper function for :GetOptionsTable (or, rather, the getter functions returned by it)
Zerotorescue@0 275
Zerotorescue@0 276 local function validateGetterArgs(uiType, uiName, errlvl)
Zerotorescue@0 277 errlvl=(errlvl or 0)+2
Zerotorescue@0 278 if uiType~="cmd" and uiType~="dropdown" and uiType~="dialog" then
Zerotorescue@0 279 error(MAJOR..": Requesting options table: 'uiType' - invalid configuration UI type, expected 'cmd', 'dropdown' or 'dialog'", errlvl)
Zerotorescue@0 280 end
Zerotorescue@0 281 if not strmatch(uiName, "[A-Za-z]%-[0-9]") then -- Expecting e.g. "MyLib-1.2"
Zerotorescue@0 282 error(MAJOR..": Requesting options table: 'uiName' - badly formatted or missing version number. Expected e.g. 'MyLib-1.2'", errlvl)
Zerotorescue@0 283 end
Zerotorescue@0 284 end
Zerotorescue@0 285
Zerotorescue@0 286 --- Register an options table with the config registry.
Zerotorescue@0 287 -- @param appName The application name as given to `:RegisterOptionsTable()`
Zerotorescue@0 288 -- @param options The options table, OR a function reference that generates it on demand. \\
Zerotorescue@0 289 -- See the top of the page for info on arguments passed to such functions.
Zerotorescue@0 290 function AceConfigRegistry:RegisterOptionsTable(appName, options)
Zerotorescue@0 291 if type(options)=="table" then
Zerotorescue@0 292 if options.type~="group" then -- quick sanity checker
Zerotorescue@0 293 error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - missing type='group' member in root group", 2)
Zerotorescue@0 294 end
Zerotorescue@0 295 AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl)
Zerotorescue@0 296 errlvl=(errlvl or 0)+1
Zerotorescue@0 297 validateGetterArgs(uiType, uiName, errlvl)
Zerotorescue@0 298 if not AceConfigRegistry.validated[uiType][appName] then
Zerotorescue@0 299 AceConfigRegistry:ValidateOptionsTable(options, appName, errlvl) -- upgradable
Zerotorescue@0 300 AceConfigRegistry.validated[uiType][appName] = true
Zerotorescue@0 301 end
Zerotorescue@0 302 return options
Zerotorescue@0 303 end
Zerotorescue@0 304 elseif type(options)=="function" then
Zerotorescue@0 305 AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl)
Zerotorescue@0 306 errlvl=(errlvl or 0)+1
Zerotorescue@0 307 validateGetterArgs(uiType, uiName, errlvl)
Zerotorescue@0 308 local tab = assert(options(uiType, uiName, appName))
Zerotorescue@0 309 if not AceConfigRegistry.validated[uiType][appName] then
Zerotorescue@0 310 AceConfigRegistry:ValidateOptionsTable(tab, appName, errlvl) -- upgradable
Zerotorescue@0 311 AceConfigRegistry.validated[uiType][appName] = true
Zerotorescue@0 312 end
Zerotorescue@0 313 return tab
Zerotorescue@0 314 end
Zerotorescue@0 315 else
Zerotorescue@0 316 error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - expected table or function reference", 2)
Zerotorescue@0 317 end
Zerotorescue@0 318 end
Zerotorescue@0 319
Zerotorescue@0 320 --- Returns an iterator of ["appName"]=funcref pairs
Zerotorescue@0 321 function AceConfigRegistry:IterateOptionsTables()
Zerotorescue@0 322 return pairs(AceConfigRegistry.tables)
Zerotorescue@0 323 end
Zerotorescue@0 324
Zerotorescue@0 325
Zerotorescue@0 326
Zerotorescue@0 327
Zerotorescue@0 328 --- Query the registry for a specific options table.
Zerotorescue@0 329 -- If only appName is given, a function is returned which you
Zerotorescue@0 330 -- can call with (uiType,uiName) to get the table.\\
Zerotorescue@0 331 -- If uiType&uiName are given, the table is returned.
Zerotorescue@0 332 -- @param appName The application name as given to `:RegisterOptionsTable()`
Zerotorescue@0 333 -- @param uiType The type of UI to get the table for, one of "cmd", "dropdown", "dialog"
Zerotorescue@0 334 -- @param uiName The name of the library/addon querying for the table, e.g. "MyLib-1.0"
Zerotorescue@0 335 function AceConfigRegistry:GetOptionsTable(appName, uiType, uiName)
Zerotorescue@0 336 local f = AceConfigRegistry.tables[appName]
Zerotorescue@0 337 if not f then
Zerotorescue@0 338 return nil
Zerotorescue@0 339 end
Zerotorescue@0 340
Zerotorescue@0 341 if uiType then
Zerotorescue@0 342 return f(uiType,uiName,1) -- get the table for us
Zerotorescue@0 343 else
Zerotorescue@0 344 return f -- return the function
Zerotorescue@0 345 end
Zerotorescue@0 346 end