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