Mercurial > wow > itemauditor
comparison Libs/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua @ 0:169f5211fc7f
First public revision.
At this point ItemAuditor watches mail for auctions sold or purchased, watches for buy/sell (money and 1 item type change) and conversions/tradeskills. Milling isn't working yet because there is too much time between the first event and the last event.
author | Asa Ayers <Asa.Ayers@Gmail.com> |
---|---|
date | Thu, 20 May 2010 19:22:19 -0700 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:169f5211fc7f |
---|---|
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 890 2009-12-06 12:50:05Z nevcairiel $ | |
12 local MAJOR, MINOR = "AceConfigRegistry-3.0", 11 | |
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 max=optnumber, | |
138 step=optnumber, | |
139 bigStep=optnumber, | |
140 isPercent=optbool, | |
141 }, | |
142 select={ | |
143 values=ismethodtable, | |
144 style={ | |
145 ["nil"]=true, | |
146 ["string"]={dropdown=true,radio=true}, | |
147 _="string: 'dropdown' or 'radio'" | |
148 }, | |
149 control=optstring, | |
150 dialogControl=optstring, | |
151 dropdownControl=optstring, | |
152 }, | |
153 multiselect={ | |
154 values=ismethodtable, | |
155 style=optstring, | |
156 tristate=optbool, | |
157 control=optstring, | |
158 dialogControl=optstring, | |
159 dropdownControl=optstring, | |
160 }, | |
161 color={ | |
162 hasAlpha=optbool, | |
163 }, | |
164 keybinding={ | |
165 -- TODO | |
166 }, | |
167 } | |
168 | |
169 local function validateKey(k,errlvl,...) | |
170 errlvl=(errlvl or 0)+1 | |
171 if type(k)~="string" then | |
172 err("["..tostring(k).."] - key is not a string", errlvl,...) | |
173 end | |
174 if strfind(k, "[%c\127]") then | |
175 err("["..tostring(k).."] - key name contained control characters", errlvl,...) | |
176 end | |
177 end | |
178 | |
179 local function validateVal(v, oktypes, errlvl,...) | |
180 errlvl=(errlvl or 0)+1 | |
181 local isok=oktypes[type(v)] or oktypes["*"] | |
182 | |
183 if not isok then | |
184 err(": expected a "..oktypes._..", got '"..tostring(v).."'", errlvl,...) | |
185 end | |
186 if type(isok)=="table" then -- isok was a table containing specific values to be tested for! | |
187 if not isok[v] then | |
188 err(": did not expect "..type(v).." value '"..tostring(v).."'", errlvl,...) | |
189 end | |
190 end | |
191 end | |
192 | |
193 local function validate(options,errlvl,...) | |
194 errlvl=(errlvl or 0)+1 | |
195 -- basic consistency | |
196 if type(options)~="table" then | |
197 err(": expected a table, got a "..type(options), errlvl,...) | |
198 end | |
199 if type(options.type)~="string" then | |
200 err(".type: expected a string, got a "..type(options.type), errlvl,...) | |
201 end | |
202 | |
203 -- get type and 'typedkeys' member | |
204 local tk = typedkeys[options.type] | |
205 if not tk then | |
206 err(".type: unknown type '"..options.type.."'", errlvl,...) | |
207 end | |
208 | |
209 -- make sure that all options[] are known parameters | |
210 for k,v in pairs(options) do | |
211 if not (tk[k] or basekeys[k]) then | |
212 err(": unknown parameter", errlvl,tostring(k),...) | |
213 end | |
214 end | |
215 | |
216 -- verify that required params are there, and that everything is the right type | |
217 for k,oktypes in pairs(basekeys) do | |
218 validateVal(options[k], oktypes, errlvl,k,...) | |
219 end | |
220 for k,oktypes in pairs(tk) do | |
221 validateVal(options[k], oktypes, errlvl,k,...) | |
222 end | |
223 | |
224 -- extra logic for groups | |
225 if options.type=="group" then | |
226 for k,v in pairs(options.args) do | |
227 validateKey(k,errlvl,"args",...) | |
228 validate(v, errlvl,k,"args",...) | |
229 end | |
230 if options.plugins then | |
231 for plugname,plugin in pairs(options.plugins) do | |
232 if type(plugin)~="table" then | |
233 err(": expected a table, got '"..tostring(plugin).."'", errlvl,tostring(plugname),"plugins",...) | |
234 end | |
235 for k,v in pairs(plugin) do | |
236 validateKey(k,errlvl,tostring(plugname),"plugins",...) | |
237 validate(v, errlvl,k,tostring(plugname),"plugins",...) | |
238 end | |
239 end | |
240 end | |
241 end | |
242 end | |
243 | |
244 | |
245 --- Validates basic structure and integrity of an options table \\ | |
246 -- Does NOT verify that get/set etc actually exist, since they can be defined at any depth | |
247 -- @param options The table to be validated | |
248 -- @param name The name of the table to be validated (shown in any error message) | |
249 -- @param errlvl (optional number) error level offset, default 0 (=errors point to the function calling :ValidateOptionsTable) | |
250 function AceConfigRegistry:ValidateOptionsTable(options,name,errlvl) | |
251 errlvl=(errlvl or 0)+1 | |
252 name = name or "Optionstable" | |
253 if not options.name then | |
254 options.name=name -- bit of a hack, the root level doesn't really need a .name :-/ | |
255 end | |
256 validate(options,errlvl,name) | |
257 end | |
258 | |
259 --- Fires a "ConfigTableChange" callback for those listening in on it, allowing config GUIs to refresh. | |
260 -- You should call this function if your options table changed from any outside event, like a game event | |
261 -- or a timer. | |
262 -- @param appName The application name as given to `:RegisterOptionsTable()` | |
263 function AceConfigRegistry:NotifyChange(appName) | |
264 if not AceConfigRegistry.tables[appName] then return end | |
265 AceConfigRegistry.callbacks:Fire("ConfigTableChange", appName) | |
266 end | |
267 | |
268 -- ------------------------------------------------------------------- | |
269 -- Registering and retreiving options tables: | |
270 | |
271 | |
272 -- validateGetterArgs: helper function for :GetOptionsTable (or, rather, the getter functions returned by it) | |
273 | |
274 local function validateGetterArgs(uiType, uiName, errlvl) | |
275 errlvl=(errlvl or 0)+2 | |
276 if uiType~="cmd" and uiType~="dropdown" and uiType~="dialog" then | |
277 error(MAJOR..": Requesting options table: 'uiType' - invalid configuration UI type, expected 'cmd', 'dropdown' or 'dialog'", errlvl) | |
278 end | |
279 if not strmatch(uiName, "[A-Za-z]%-[0-9]") then -- Expecting e.g. "MyLib-1.2" | |
280 error(MAJOR..": Requesting options table: 'uiName' - badly formatted or missing version number. Expected e.g. 'MyLib-1.2'", errlvl) | |
281 end | |
282 end | |
283 | |
284 --- Register an options table with the config registry. | |
285 -- @param appName The application name as given to `:RegisterOptionsTable()` | |
286 -- @param options The options table, OR a function reference that generates it on demand. \\ | |
287 -- See the top of the page for info on arguments passed to such functions. | |
288 function AceConfigRegistry:RegisterOptionsTable(appName, options) | |
289 if type(options)=="table" then | |
290 if options.type~="group" then -- quick sanity checker | |
291 error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - missing type='group' member in root group", 2) | |
292 end | |
293 AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl) | |
294 errlvl=(errlvl or 0)+1 | |
295 validateGetterArgs(uiType, uiName, errlvl) | |
296 if not AceConfigRegistry.validated[uiType][appName] then | |
297 AceConfigRegistry:ValidateOptionsTable(options, appName, errlvl) -- upgradable | |
298 AceConfigRegistry.validated[uiType][appName] = true | |
299 end | |
300 return options | |
301 end | |
302 elseif type(options)=="function" then | |
303 AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl) | |
304 errlvl=(errlvl or 0)+1 | |
305 validateGetterArgs(uiType, uiName, errlvl) | |
306 local tab = assert(options(uiType, uiName, appName)) | |
307 if not AceConfigRegistry.validated[uiType][appName] then | |
308 AceConfigRegistry:ValidateOptionsTable(tab, appName, errlvl) -- upgradable | |
309 AceConfigRegistry.validated[uiType][appName] = true | |
310 end | |
311 return tab | |
312 end | |
313 else | |
314 error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - expected table or function reference", 2) | |
315 end | |
316 end | |
317 | |
318 --- Returns an iterator of ["appName"]=funcref pairs | |
319 function AceConfigRegistry:IterateOptionsTables() | |
320 return pairs(AceConfigRegistry.tables) | |
321 end | |
322 | |
323 | |
324 | |
325 | |
326 --- Query the registry for a specific options table. | |
327 -- If only appName is given, a function is returned which you | |
328 -- can call with (uiType,uiName) to get the table.\\ | |
329 -- If uiType&uiName are given, the table is returned. | |
330 -- @param appName The application name as given to `:RegisterOptionsTable()` | |
331 -- @param uiType The type of UI to get the table for, one of "cmd", "dropdown", "dialog" | |
332 -- @param uiName The name of the library/addon querying for the table, e.g. "MyLib-1.0" | |
333 function AceConfigRegistry:GetOptionsTable(appName, uiType, uiName) | |
334 local f = AceConfigRegistry.tables[appName] | |
335 if not f then | |
336 return nil | |
337 end | |
338 | |
339 if uiType then | |
340 return f(uiType,uiName,1) -- get the table for us | |
341 else | |
342 return f -- return the function | |
343 end | |
344 end |