annotate Libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua @ 58:0682d738499b v8.0.1.058

- 8.0.1 Update.
author Tercio
date Fri, 20 Jul 2018 19:04:12 -0300
parents dbf04157d63e
children
rev   line source
Tercio@23 1 --- AceConfigDialog-3.0 generates AceGUI-3.0 based windows based on option tables.
Tercio@23 2 -- @class file
Tercio@23 3 -- @name AceConfigDialog-3.0
Tercio@58 4 -- @release $Id: AceConfigDialog-3.0.lua 1169 2018-02-27 16:18:28Z nevcairiel $
Tercio@23 5
Tercio@23 6 local LibStub = LibStub
Tercio@51 7 local gui = LibStub("AceGUI-3.0")
Tercio@51 8 local reg = LibStub("AceConfigRegistry-3.0")
Tercio@51 9
Tercio@58 10 local MAJOR, MINOR = "AceConfigDialog-3.0", 66
Tercio@23 11 local AceConfigDialog, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
Tercio@23 12
Tercio@23 13 if not AceConfigDialog then return end
Tercio@23 14
Tercio@23 15 AceConfigDialog.OpenFrames = AceConfigDialog.OpenFrames or {}
Tercio@23 16 AceConfigDialog.Status = AceConfigDialog.Status or {}
Tercio@23 17 AceConfigDialog.frame = AceConfigDialog.frame or CreateFrame("Frame")
Tercio@23 18
Tercio@23 19 AceConfigDialog.frame.apps = AceConfigDialog.frame.apps or {}
Tercio@23 20 AceConfigDialog.frame.closing = AceConfigDialog.frame.closing or {}
Tercio@23 21 AceConfigDialog.frame.closeAllOverride = AceConfigDialog.frame.closeAllOverride or {}
Tercio@23 22
Tercio@23 23 -- Lua APIs
Tercio@23 24 local tconcat, tinsert, tsort, tremove, tsort = table.concat, table.insert, table.sort, table.remove, table.sort
Tercio@23 25 local strmatch, format = string.match, string.format
Tercio@23 26 local assert, loadstring, error = assert, loadstring, error
Tercio@23 27 local pairs, next, select, type, unpack, wipe, ipairs = pairs, next, select, type, unpack, wipe, ipairs
Tercio@23 28 local rawset, tostring, tonumber = rawset, tostring, tonumber
Tercio@23 29 local math_min, math_max, math_floor = math.min, math.max, math.floor
Tercio@23 30
Tercio@23 31 -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
Tercio@23 32 -- List them here for Mikk's FindGlobals script
Tercio@23 33 -- GLOBALS: NORMAL_FONT_COLOR, GameTooltip, StaticPopupDialogs, ACCEPT, CANCEL, StaticPopup_Show
Tercio@23 34 -- GLOBALS: PlaySound, GameFontHighlight, GameFontHighlightSmall, GameFontHighlightLarge
Tercio@23 35 -- GLOBALS: CloseSpecialWindows, InterfaceOptions_AddCategory, geterrorhandler
Tercio@23 36
Tercio@23 37 local emptyTbl = {}
Tercio@23 38
Tercio@23 39 --[[
Tercio@23 40 xpcall safecall implementation
Tercio@23 41 ]]
Tercio@23 42 local xpcall = xpcall
Tercio@23 43
Tercio@23 44 local function errorhandler(err)
Tercio@23 45 return geterrorhandler()(err)
Tercio@23 46 end
Tercio@23 47
Tercio@23 48 local function CreateDispatcher(argCount)
Tercio@23 49 local code = [[
Tercio@23 50 local xpcall, eh = ...
Tercio@23 51 local method, ARGS
Tercio@23 52 local function call() return method(ARGS) end
Tercio@23 53
Tercio@23 54 local function dispatch(func, ...)
Tercio@23 55 method = func
Tercio@23 56 if not method then return end
Tercio@23 57 ARGS = ...
Tercio@23 58 return xpcall(call, eh)
Tercio@23 59 end
Tercio@23 60
Tercio@23 61 return dispatch
Tercio@23 62 ]]
Tercio@23 63
Tercio@23 64 local ARGS = {}
Tercio@23 65 for i = 1, argCount do ARGS[i] = "arg"..i end
Tercio@23 66 code = code:gsub("ARGS", tconcat(ARGS, ", "))
Tercio@23 67 return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
Tercio@23 68 end
Tercio@23 69
Tercio@23 70 local Dispatchers = setmetatable({}, {__index=function(self, argCount)
Tercio@23 71 local dispatcher = CreateDispatcher(argCount)
Tercio@23 72 rawset(self, argCount, dispatcher)
Tercio@23 73 return dispatcher
Tercio@23 74 end})
Tercio@23 75 Dispatchers[0] = function(func)
Tercio@23 76 return xpcall(func, errorhandler)
Tercio@23 77 end
Tercio@23 78
Tercio@23 79 local function safecall(func, ...)
Tercio@23 80 return Dispatchers[select("#", ...)](func, ...)
Tercio@23 81 end
Tercio@23 82
Tercio@23 83 local width_multiplier = 170
Tercio@23 84
Tercio@23 85 --[[
Tercio@23 86 Group Types
Tercio@23 87 Tree - All Descendant Groups will all become nodes on the tree, direct child options will appear above the tree
Tercio@23 88 - Descendant Groups with inline=true and thier children will not become nodes
Tercio@23 89
Tercio@23 90 Tab - Direct Child Groups will become tabs, direct child options will appear above the tab control
Tercio@23 91 - Grandchild groups will default to inline unless specified otherwise
Tercio@23 92
Tercio@23 93 Select- Same as Tab but with entries in a dropdown rather than tabs
Tercio@23 94
Tercio@23 95
Tercio@23 96 Inline Groups
Tercio@23 97 - Will not become nodes of a select group, they will be effectivly part of thier parent group seperated by a border
Tercio@23 98 - If declared on a direct child of a root node of a select group, they will appear above the group container control
Tercio@23 99 - When a group is displayed inline, all descendants will also be inline members of the group
Tercio@23 100
Tercio@23 101 ]]
Tercio@23 102
Tercio@23 103 -- Recycling functions
Tercio@23 104 local new, del, copy
Tercio@23 105 --newcount, delcount,createdcount,cached = 0,0,0
Tercio@23 106 do
Tercio@23 107 local pool = setmetatable({},{__mode="k"})
Tercio@23 108 function new()
Tercio@23 109 --newcount = newcount + 1
Tercio@23 110 local t = next(pool)
Tercio@23 111 if t then
Tercio@23 112 pool[t] = nil
Tercio@23 113 return t
Tercio@23 114 else
Tercio@23 115 --createdcount = createdcount + 1
Tercio@23 116 return {}
Tercio@23 117 end
Tercio@23 118 end
Tercio@23 119 function copy(t)
Tercio@23 120 local c = new()
Tercio@23 121 for k, v in pairs(t) do
Tercio@23 122 c[k] = v
Tercio@23 123 end
Tercio@23 124 return c
Tercio@23 125 end
Tercio@23 126 function del(t)
Tercio@23 127 --delcount = delcount + 1
Tercio@23 128 wipe(t)
Tercio@23 129 pool[t] = true
Tercio@23 130 end
Tercio@23 131 -- function cached()
Tercio@23 132 -- local n = 0
Tercio@23 133 -- for k in pairs(pool) do
Tercio@23 134 -- n = n + 1
Tercio@23 135 -- end
Tercio@23 136 -- return n
Tercio@23 137 -- end
Tercio@23 138 end
Tercio@23 139
Tercio@23 140 -- picks the first non-nil value and returns it
Tercio@23 141 local function pickfirstset(...)
Tercio@23 142 for i=1,select("#",...) do
Tercio@23 143 if select(i,...)~=nil then
Tercio@23 144 return select(i,...)
Tercio@23 145 end
Tercio@23 146 end
Tercio@23 147 end
Tercio@23 148
Tercio@23 149 --gets an option from a given group, checking plugins
Tercio@23 150 local function GetSubOption(group, key)
Tercio@23 151 if group.plugins then
Tercio@23 152 for plugin, t in pairs(group.plugins) do
Tercio@23 153 if t[key] then
Tercio@23 154 return t[key]
Tercio@23 155 end
Tercio@23 156 end
Tercio@23 157 end
Tercio@23 158
Tercio@23 159 return group.args[key]
Tercio@23 160 end
Tercio@23 161
Tercio@23 162 --Option member type definitions, used to decide how to access it
Tercio@23 163
Tercio@23 164 --Is the member Inherited from parent options
Tercio@23 165 local isInherited = {
Tercio@23 166 set = true,
Tercio@23 167 get = true,
Tercio@23 168 func = true,
Tercio@23 169 confirm = true,
Tercio@23 170 validate = true,
Tercio@23 171 disabled = true,
Tercio@23 172 hidden = true
Tercio@23 173 }
Tercio@23 174
Tercio@23 175 --Does a string type mean a literal value, instead of the default of a method of the handler
Tercio@23 176 local stringIsLiteral = {
Tercio@23 177 name = true,
Tercio@23 178 desc = true,
Tercio@23 179 icon = true,
Tercio@23 180 usage = true,
Tercio@23 181 width = true,
Tercio@23 182 image = true,
Tercio@23 183 fontSize = true,
Tercio@23 184 }
Tercio@23 185
Tercio@23 186 --Is Never a function or method
Tercio@23 187 local allIsLiteral = {
Tercio@23 188 type = true,
Tercio@23 189 descStyle = true,
Tercio@23 190 imageWidth = true,
Tercio@23 191 imageHeight = true,
Tercio@23 192 }
Tercio@23 193
Tercio@23 194 --gets the value for a member that could be a function
Tercio@23 195 --function refs are called with an info arg
Tercio@23 196 --every other type is returned
Tercio@23 197 local function GetOptionsMemberValue(membername, option, options, path, appName, ...)
Tercio@23 198 --get definition for the member
Tercio@23 199 local inherits = isInherited[membername]
Tercio@23 200
Tercio@23 201
Tercio@23 202 --get the member of the option, traversing the tree if it can be inherited
Tercio@23 203 local member
Tercio@23 204
Tercio@23 205 if inherits then
Tercio@23 206 local group = options
Tercio@23 207 if group[membername] ~= nil then
Tercio@23 208 member = group[membername]
Tercio@23 209 end
Tercio@23 210 for i = 1, #path do
Tercio@23 211 group = GetSubOption(group, path[i])
Tercio@23 212 if group[membername] ~= nil then
Tercio@23 213 member = group[membername]
Tercio@23 214 end
Tercio@23 215 end
Tercio@23 216 else
Tercio@23 217 member = option[membername]
Tercio@23 218 end
Tercio@23 219
Tercio@23 220 --check if we need to call a functon, or if we have a literal value
Tercio@23 221 if ( not allIsLiteral[membername] ) and ( type(member) == "function" or ((not stringIsLiteral[membername]) and type(member) == "string") ) then
Tercio@23 222 --We have a function to call
Tercio@23 223 local info = new()
Tercio@23 224 --traverse the options table, picking up the handler and filling the info with the path
Tercio@23 225 local handler
Tercio@23 226 local group = options
Tercio@23 227 handler = group.handler or handler
Tercio@23 228
Tercio@23 229 for i = 1, #path do
Tercio@23 230 group = GetSubOption(group, path[i])
Tercio@23 231 info[i] = path[i]
Tercio@23 232 handler = group.handler or handler
Tercio@23 233 end
Tercio@23 234
Tercio@23 235 info.options = options
Tercio@23 236 info.appName = appName
Tercio@23 237 info[0] = appName
Tercio@23 238 info.arg = option.arg
Tercio@23 239 info.handler = handler
Tercio@23 240 info.option = option
Tercio@23 241 info.type = option.type
Tercio@23 242 info.uiType = "dialog"
Tercio@23 243 info.uiName = MAJOR
Tercio@23 244
Tercio@23 245 local a, b, c ,d
Tercio@23 246 --using 4 returns for the get of a color type, increase if a type needs more
Tercio@23 247 if type(member) == "function" then
Tercio@23 248 --Call the function
Tercio@23 249 a,b,c,d = member(info, ...)
Tercio@23 250 else
Tercio@23 251 --Call the method
Tercio@23 252 if handler and handler[member] then
Tercio@23 253 a,b,c,d = handler[member](handler, info, ...)
Tercio@23 254 else
Tercio@23 255 error(format("Method %s doesn't exist in handler for type %s", member, membername))
Tercio@23 256 end
Tercio@23 257 end
Tercio@23 258 del(info)
Tercio@23 259 return a,b,c,d
Tercio@23 260 else
Tercio@23 261 --The value isnt a function to call, return it
Tercio@23 262 return member
Tercio@23 263 end
Tercio@23 264 end
Tercio@23 265
Tercio@23 266 --[[calls an options function that could be inherited, method name or function ref
Tercio@23 267 local function CallOptionsFunction(funcname ,option, options, path, appName, ...)
Tercio@23 268 local info = new()
Tercio@23 269
Tercio@23 270 local func
Tercio@23 271 local group = options
Tercio@23 272 local handler
Tercio@23 273
Tercio@23 274 --build the info table containing the path
Tercio@23 275 -- pick up functions while traversing the tree
Tercio@23 276 if group[funcname] ~= nil then
Tercio@23 277 func = group[funcname]
Tercio@23 278 end
Tercio@23 279 handler = group.handler or handler
Tercio@23 280
Tercio@23 281 for i, v in ipairs(path) do
Tercio@23 282 group = GetSubOption(group, v)
Tercio@23 283 info[i] = v
Tercio@23 284 if group[funcname] ~= nil then
Tercio@23 285 func = group[funcname]
Tercio@23 286 end
Tercio@23 287 handler = group.handler or handler
Tercio@23 288 end
Tercio@23 289
Tercio@23 290 info.options = options
Tercio@23 291 info[0] = appName
Tercio@23 292 info.arg = option.arg
Tercio@23 293
Tercio@23 294 local a, b, c ,d
Tercio@23 295 if type(func) == "string" then
Tercio@23 296 if handler and handler[func] then
Tercio@23 297 a,b,c,d = handler[func](handler, info, ...)
Tercio@23 298 else
Tercio@23 299 error(string.format("Method %s doesn't exist in handler for type func", func))
Tercio@23 300 end
Tercio@23 301 elseif type(func) == "function" then
Tercio@23 302 a,b,c,d = func(info, ...)
Tercio@23 303 end
Tercio@23 304 del(info)
Tercio@23 305 return a,b,c,d
Tercio@23 306 end
Tercio@23 307 --]]
Tercio@23 308
Tercio@23 309 --tables to hold orders and names for options being sorted, will be created with new()
Tercio@23 310 --prevents needing to call functions repeatedly while sorting
Tercio@23 311 local tempOrders
Tercio@23 312 local tempNames
Tercio@23 313
Tercio@23 314 local function compareOptions(a,b)
Tercio@23 315 if not a then
Tercio@23 316 return true
Tercio@23 317 end
Tercio@23 318 if not b then
Tercio@23 319 return false
Tercio@23 320 end
Tercio@23 321 local OrderA, OrderB = tempOrders[a] or 100, tempOrders[b] or 100
Tercio@23 322 if OrderA == OrderB then
Tercio@23 323 local NameA = (type(tempNames[a]) == "string") and tempNames[a] or ""
Tercio@23 324 local NameB = (type(tempNames[b]) == "string") and tempNames[b] or ""
Tercio@23 325 return NameA:upper() < NameB:upper()
Tercio@23 326 end
Tercio@23 327 if OrderA < 0 then
Tercio@23 328 if OrderB > 0 then
Tercio@23 329 return false
Tercio@23 330 end
Tercio@23 331 else
Tercio@23 332 if OrderB < 0 then
Tercio@23 333 return true
Tercio@23 334 end
Tercio@23 335 end
Tercio@23 336 return OrderA < OrderB
Tercio@23 337 end
Tercio@23 338
Tercio@23 339
Tercio@23 340
Tercio@23 341 --builds 2 tables out of an options group
Tercio@23 342 -- keySort, sorted keys
Tercio@23 343 -- opts, combined options from .plugins and args
Tercio@23 344 local function BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
Tercio@23 345 tempOrders = new()
Tercio@23 346 tempNames = new()
Tercio@23 347
Tercio@23 348 if group.plugins then
Tercio@23 349 for plugin, t in pairs(group.plugins) do
Tercio@23 350 for k, v in pairs(t) do
Tercio@23 351 if not opts[k] then
Tercio@23 352 tinsert(keySort, k)
Tercio@23 353 opts[k] = v
Tercio@23 354
Tercio@23 355 path[#path+1] = k
Tercio@23 356 tempOrders[k] = GetOptionsMemberValue("order", v, options, path, appName)
Tercio@23 357 tempNames[k] = GetOptionsMemberValue("name", v, options, path, appName)
Tercio@23 358 path[#path] = nil
Tercio@23 359 end
Tercio@23 360 end
Tercio@23 361 end
Tercio@23 362 end
Tercio@23 363
Tercio@23 364 for k, v in pairs(group.args) do
Tercio@23 365 if not opts[k] then
Tercio@23 366 tinsert(keySort, k)
Tercio@23 367 opts[k] = v
Tercio@23 368
Tercio@23 369 path[#path+1] = k
Tercio@23 370 tempOrders[k] = GetOptionsMemberValue("order", v, options, path, appName)
Tercio@23 371 tempNames[k] = GetOptionsMemberValue("name", v, options, path, appName)
Tercio@23 372 path[#path] = nil
Tercio@23 373 end
Tercio@23 374 end
Tercio@23 375
Tercio@23 376 tsort(keySort, compareOptions)
Tercio@23 377
Tercio@23 378 del(tempOrders)
Tercio@23 379 del(tempNames)
Tercio@23 380 end
Tercio@23 381
Tercio@23 382 local function DelTree(tree)
Tercio@23 383 if tree.children then
Tercio@23 384 local childs = tree.children
Tercio@23 385 for i = 1, #childs do
Tercio@23 386 DelTree(childs[i])
Tercio@23 387 del(childs[i])
Tercio@23 388 end
Tercio@23 389 del(childs)
Tercio@23 390 end
Tercio@23 391 end
Tercio@23 392
Tercio@23 393 local function CleanUserData(widget, event)
Tercio@23 394
Tercio@23 395 local user = widget:GetUserDataTable()
Tercio@23 396
Tercio@23 397 if user.path then
Tercio@23 398 del(user.path)
Tercio@23 399 end
Tercio@23 400
Tercio@23 401 if widget.type == "TreeGroup" then
Tercio@23 402 local tree = user.tree
Tercio@23 403 widget:SetTree(nil)
Tercio@23 404 if tree then
Tercio@23 405 for i = 1, #tree do
Tercio@23 406 DelTree(tree[i])
Tercio@23 407 del(tree[i])
Tercio@23 408 end
Tercio@23 409 del(tree)
Tercio@23 410 end
Tercio@23 411 end
Tercio@23 412
Tercio@23 413 if widget.type == "TabGroup" then
Tercio@23 414 widget:SetTabs(nil)
Tercio@23 415 if user.tablist then
Tercio@23 416 del(user.tablist)
Tercio@23 417 end
Tercio@23 418 end
Tercio@23 419
Tercio@23 420 if widget.type == "DropdownGroup" then
Tercio@23 421 widget:SetGroupList(nil)
Tercio@23 422 if user.grouplist then
Tercio@23 423 del(user.grouplist)
Tercio@23 424 end
Tercio@23 425 if user.orderlist then
Tercio@23 426 del(user.orderlist)
Tercio@23 427 end
Tercio@23 428 end
Tercio@23 429 end
Tercio@23 430
Tercio@23 431 -- - Gets a status table for the given appname and options path.
Tercio@23 432 -- @param appName The application name as given to `:RegisterOptionsTable()`
Tercio@23 433 -- @param path The path to the options (a table with all group keys)
Tercio@23 434 -- @return
Tercio@23 435 function AceConfigDialog:GetStatusTable(appName, path)
Tercio@23 436 local status = self.Status
Tercio@23 437
Tercio@23 438 if not status[appName] then
Tercio@23 439 status[appName] = {}
Tercio@23 440 status[appName].status = {}
Tercio@23 441 status[appName].children = {}
Tercio@23 442 end
Tercio@23 443
Tercio@23 444 status = status[appName]
Tercio@23 445
Tercio@23 446 if path then
Tercio@23 447 for i = 1, #path do
Tercio@23 448 local v = path[i]
Tercio@23 449 if not status.children[v] then
Tercio@23 450 status.children[v] = {}
Tercio@23 451 status.children[v].status = {}
Tercio@23 452 status.children[v].children = {}
Tercio@23 453 end
Tercio@23 454 status = status.children[v]
Tercio@23 455 end
Tercio@23 456 end
Tercio@23 457
Tercio@23 458 return status.status
Tercio@23 459 end
Tercio@23 460
Tercio@23 461 --- Selects the specified path in the options window.
Tercio@23 462 -- The path specified has to match the keys of the groups in the table.
Tercio@23 463 -- @param appName The application name as given to `:RegisterOptionsTable()`
Tercio@23 464 -- @param ... The path to the key that should be selected
Tercio@23 465 function AceConfigDialog:SelectGroup(appName, ...)
Tercio@23 466 local path = new()
Tercio@23 467
Tercio@23 468
Tercio@23 469 local app = reg:GetOptionsTable(appName)
Tercio@23 470 if not app then
Tercio@23 471 error(("%s isn't registed with AceConfigRegistry, unable to open config"):format(appName), 2)
Tercio@23 472 end
Tercio@23 473 local options = app("dialog", MAJOR)
Tercio@23 474 local group = options
Tercio@23 475 local status = self:GetStatusTable(appName, path)
Tercio@23 476 if not status.groups then
Tercio@23 477 status.groups = {}
Tercio@23 478 end
Tercio@23 479 status = status.groups
Tercio@23 480 local treevalue
Tercio@23 481 local treestatus
Tercio@23 482
Tercio@23 483 for n = 1, select("#",...) do
Tercio@23 484 local key = select(n, ...)
Tercio@23 485
Tercio@23 486 if group.childGroups == "tab" or group.childGroups == "select" then
Tercio@23 487 --if this is a tab or select group, select the group
Tercio@23 488 status.selected = key
Tercio@23 489 --children of this group are no longer extra levels of a tree
Tercio@23 490 treevalue = nil
Tercio@23 491 else
Tercio@23 492 --tree group by default
Tercio@23 493 if treevalue then
Tercio@23 494 --this is an extra level of a tree group, build a uniquevalue for it
Tercio@23 495 treevalue = treevalue.."\001"..key
Tercio@23 496 else
Tercio@23 497 --this is the top level of a tree group, the uniquevalue is the same as the key
Tercio@23 498 treevalue = key
Tercio@23 499 if not status.groups then
Tercio@23 500 status.groups = {}
Tercio@23 501 end
Tercio@23 502 --save this trees status table for any extra levels or groups
Tercio@23 503 treestatus = status
Tercio@23 504 end
Tercio@23 505 --make sure that the tree entry is open, and select it.
Tercio@23 506 --the selected group will be overwritten if a child is the final target but still needs to be open
Tercio@23 507 treestatus.selected = treevalue
Tercio@23 508 treestatus.groups[treevalue] = true
Tercio@23 509
Tercio@23 510 end
Tercio@23 511
Tercio@23 512 --move to the next group in the path
Tercio@23 513 group = GetSubOption(group, key)
Tercio@23 514 if not group then
Tercio@23 515 break
Tercio@23 516 end
Tercio@23 517 tinsert(path, key)
Tercio@23 518 status = self:GetStatusTable(appName, path)
Tercio@23 519 if not status.groups then
Tercio@23 520 status.groups = {}
Tercio@23 521 end
Tercio@23 522 status = status.groups
Tercio@23 523 end
Tercio@23 524
Tercio@23 525 del(path)
Tercio@23 526 reg:NotifyChange(appName)
Tercio@23 527 end
Tercio@23 528
Tercio@23 529 local function OptionOnMouseOver(widget, event)
Tercio@23 530 --show a tooltip/set the status bar to the desc text
Tercio@23 531 local user = widget:GetUserDataTable()
Tercio@23 532 local opt = user.option
Tercio@23 533 local options = user.options
Tercio@23 534 local path = user.path
Tercio@23 535 local appName = user.appName
Tercio@23 536
Tercio@23 537 GameTooltip:SetOwner(widget.frame, "ANCHOR_TOPRIGHT")
Tercio@23 538 local name = GetOptionsMemberValue("name", opt, options, path, appName)
Tercio@23 539 local desc = GetOptionsMemberValue("desc", opt, options, path, appName)
Tercio@23 540 local usage = GetOptionsMemberValue("usage", opt, options, path, appName)
Tercio@23 541 local descStyle = opt.descStyle
Tercio@23 542
Tercio@23 543 if descStyle and descStyle ~= "tooltip" then return end
Tercio@23 544
Tercio@23 545 GameTooltip:SetText(name, 1, .82, 0, true)
Tercio@23 546
Tercio@23 547 if opt.type == "multiselect" then
Tercio@23 548 GameTooltip:AddLine(user.text, 0.5, 0.5, 0.8, true)
Tercio@23 549 end
Tercio@23 550 if type(desc) == "string" then
Tercio@23 551 GameTooltip:AddLine(desc, 1, 1, 1, true)
Tercio@23 552 end
Tercio@23 553 if type(usage) == "string" then
Tercio@23 554 GameTooltip:AddLine("Usage: "..usage, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, true)
Tercio@23 555 end
Tercio@23 556
Tercio@23 557 GameTooltip:Show()
Tercio@23 558 end
Tercio@23 559
Tercio@23 560 local function OptionOnMouseLeave(widget, event)
Tercio@23 561 GameTooltip:Hide()
Tercio@23 562 end
Tercio@23 563
Tercio@23 564 local function GetFuncName(option)
Tercio@23 565 local type = option.type
Tercio@23 566 if type == "execute" then
Tercio@23 567 return "func"
Tercio@23 568 else
Tercio@23 569 return "set"
Tercio@23 570 end
Tercio@23 571 end
Tercio@23 572 local function confirmPopup(appName, rootframe, basepath, info, message, func, ...)
Tercio@23 573 if not StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"] then
Tercio@23 574 StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"] = {}
Tercio@23 575 end
Tercio@23 576 local t = StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"]
Tercio@23 577 for k in pairs(t) do
Tercio@23 578 t[k] = nil
Tercio@23 579 end
Tercio@23 580 t.text = message
Tercio@23 581 t.button1 = ACCEPT
Tercio@23 582 t.button2 = CANCEL
Tercio@23 583 t.preferredIndex = STATICPOPUP_NUMDIALOGS
Tercio@23 584 local dialog, oldstrata
Tercio@23 585 t.OnAccept = function()
Tercio@23 586 safecall(func, unpack(t))
Tercio@23 587 if dialog and oldstrata then
Tercio@23 588 dialog:SetFrameStrata(oldstrata)
Tercio@23 589 end
Tercio@23 590 AceConfigDialog:Open(appName, rootframe, unpack(basepath or emptyTbl))
Tercio@23 591 del(info)
Tercio@23 592 end
Tercio@23 593 t.OnCancel = function()
Tercio@23 594 if dialog and oldstrata then
Tercio@23 595 dialog:SetFrameStrata(oldstrata)
Tercio@23 596 end
Tercio@23 597 AceConfigDialog:Open(appName, rootframe, unpack(basepath or emptyTbl))
Tercio@23 598 del(info)
Tercio@23 599 end
Tercio@23 600 for i = 1, select("#", ...) do
Tercio@23 601 t[i] = select(i, ...) or false
Tercio@23 602 end
Tercio@23 603 t.timeout = 0
Tercio@23 604 t.whileDead = 1
Tercio@23 605 t.hideOnEscape = 1
Tercio@23 606
Tercio@23 607 dialog = StaticPopup_Show("ACECONFIGDIALOG30_CONFIRM_DIALOG")
Tercio@23 608 if dialog then
Tercio@23 609 oldstrata = dialog:GetFrameStrata()
Tercio@23 610 dialog:SetFrameStrata("TOOLTIP")
Tercio@23 611 end
Tercio@23 612 end
Tercio@23 613
Tercio@51 614 local function validationErrorPopup(message)
Tercio@51 615 if not StaticPopupDialogs["ACECONFIGDIALOG30_VALIDATION_ERROR_DIALOG"] then
Tercio@51 616 StaticPopupDialogs["ACECONFIGDIALOG30_VALIDATION_ERROR_DIALOG"] = {}
Tercio@51 617 end
Tercio@51 618 local t = StaticPopupDialogs["ACECONFIGDIALOG30_VALIDATION_ERROR_DIALOG"]
Tercio@51 619 t.text = message
Tercio@51 620 t.button1 = OKAY
Tercio@51 621 t.preferredIndex = STATICPOPUP_NUMDIALOGS
Tercio@51 622 local dialog, oldstrata
Tercio@51 623 t.OnAccept = function()
Tercio@51 624 if dialog and oldstrata then
Tercio@51 625 dialog:SetFrameStrata(oldstrata)
Tercio@51 626 end
Tercio@51 627 end
Tercio@51 628 t.timeout = 0
Tercio@51 629 t.whileDead = 1
Tercio@51 630 t.hideOnEscape = 1
Tercio@51 631
Tercio@51 632 dialog = StaticPopup_Show("ACECONFIGDIALOG30_VALIDATION_ERROR_DIALOG")
Tercio@51 633 if dialog then
Tercio@51 634 oldstrata = dialog:GetFrameStrata()
Tercio@51 635 dialog:SetFrameStrata("TOOLTIP")
Tercio@51 636 end
Tercio@51 637 end
Tercio@51 638
Tercio@23 639 local function ActivateControl(widget, event, ...)
Tercio@23 640 --This function will call the set / execute handler for the widget
Tercio@23 641 --widget:GetUserDataTable() contains the needed info
Tercio@23 642 local user = widget:GetUserDataTable()
Tercio@23 643 local option = user.option
Tercio@23 644 local options = user.options
Tercio@23 645 local path = user.path
Tercio@23 646 local info = new()
Tercio@23 647
Tercio@23 648 local func
Tercio@23 649 local group = options
Tercio@23 650 local funcname = GetFuncName(option)
Tercio@23 651 local handler
Tercio@23 652 local confirm
Tercio@23 653 local validate
Tercio@23 654 --build the info table containing the path
Tercio@23 655 -- pick up functions while traversing the tree
Tercio@23 656 if group[funcname] ~= nil then
Tercio@23 657 func = group[funcname]
Tercio@23 658 end
Tercio@23 659 handler = group.handler or handler
Tercio@23 660 confirm = group.confirm
Tercio@23 661 validate = group.validate
Tercio@23 662 for i = 1, #path do
Tercio@23 663 local v = path[i]
Tercio@23 664 group = GetSubOption(group, v)
Tercio@23 665 info[i] = v
Tercio@23 666 if group[funcname] ~= nil then
Tercio@23 667 func = group[funcname]
Tercio@23 668 end
Tercio@23 669 handler = group.handler or handler
Tercio@23 670 if group.confirm ~= nil then
Tercio@23 671 confirm = group.confirm
Tercio@23 672 end
Tercio@23 673 if group.validate ~= nil then
Tercio@23 674 validate = group.validate
Tercio@23 675 end
Tercio@23 676 end
Tercio@23 677
Tercio@23 678 info.options = options
Tercio@23 679 info.appName = user.appName
Tercio@23 680 info.arg = option.arg
Tercio@23 681 info.handler = handler
Tercio@23 682 info.option = option
Tercio@23 683 info.type = option.type
Tercio@23 684 info.uiType = "dialog"
Tercio@23 685 info.uiName = MAJOR
Tercio@23 686
Tercio@23 687 local name
Tercio@23 688 if type(option.name) == "function" then
Tercio@23 689 name = option.name(info)
Tercio@23 690 elseif type(option.name) == "string" then
Tercio@23 691 name = option.name
Tercio@23 692 else
Tercio@23 693 name = ""
Tercio@23 694 end
Tercio@23 695 local usage = option.usage
Tercio@23 696 local pattern = option.pattern
Tercio@23 697
Tercio@23 698 local validated = true
Tercio@23 699
Tercio@23 700 if option.type == "input" then
Tercio@23 701 if type(pattern)=="string" then
Tercio@23 702 if not strmatch(..., pattern) then
Tercio@23 703 validated = false
Tercio@23 704 end
Tercio@23 705 end
Tercio@23 706 end
Tercio@23 707
Tercio@23 708 local success
Tercio@23 709 if validated and option.type ~= "execute" then
Tercio@23 710 if type(validate) == "string" then
Tercio@23 711 if handler and handler[validate] then
Tercio@23 712 success, validated = safecall(handler[validate], handler, info, ...)
Tercio@23 713 if not success then validated = false end
Tercio@23 714 else
Tercio@23 715 error(format("Method %s doesn't exist in handler for type execute", validate))
Tercio@23 716 end
Tercio@23 717 elseif type(validate) == "function" then
Tercio@23 718 success, validated = safecall(validate, info, ...)
Tercio@23 719 if not success then validated = false end
Tercio@23 720 end
Tercio@23 721 end
Tercio@23 722
Tercio@23 723 local rootframe = user.rootframe
Tercio@51 724 if not validated or type(validated) == "string" then
Tercio@51 725 if not validated then
Tercio@51 726 if usage then
Tercio@51 727 validated = name..": "..usage
Tercio@51 728 else
Tercio@51 729 if pattern then
Tercio@51 730 validated = name..": Expected "..pattern
Tercio@51 731 else
Tercio@51 732 validated = name..": Invalid Value"
Tercio@51 733 end
Tercio@51 734 end
Tercio@51 735 end
Tercio@51 736
Tercio@51 737 -- show validate message
Tercio@23 738 if rootframe.SetStatusText then
Tercio@23 739 rootframe:SetStatusText(validated)
Tercio@23 740 else
Tercio@51 741 validationErrorPopup(validated)
Tercio@23 742 end
Tercio@51 743 PlaySound(882) -- SOUNDKIT.IG_PLAYER_INVITE_DECLINE || _DECLINE is actually missing from the table
Tercio@23 744 del(info)
Tercio@23 745 return true
Tercio@23 746 else
Tercio@23 747
Tercio@23 748 local confirmText = option.confirmText
Tercio@23 749 --call confirm func/method
Tercio@23 750 if type(confirm) == "string" then
Tercio@23 751 if handler and handler[confirm] then
Tercio@23 752 success, confirm = safecall(handler[confirm], handler, info, ...)
Tercio@23 753 if success and type(confirm) == "string" then
Tercio@23 754 confirmText = confirm
Tercio@23 755 confirm = true
Tercio@23 756 elseif not success then
Tercio@23 757 confirm = false
Tercio@23 758 end
Tercio@23 759 else
Tercio@23 760 error(format("Method %s doesn't exist in handler for type confirm", confirm))
Tercio@23 761 end
Tercio@23 762 elseif type(confirm) == "function" then
Tercio@23 763 success, confirm = safecall(confirm, info, ...)
Tercio@23 764 if success and type(confirm) == "string" then
Tercio@23 765 confirmText = confirm
Tercio@23 766 confirm = true
Tercio@23 767 elseif not success then
Tercio@23 768 confirm = false
Tercio@23 769 end
Tercio@23 770 end
Tercio@23 771
Tercio@23 772 --confirm if needed
Tercio@23 773 if type(confirm) == "boolean" then
Tercio@23 774 if confirm then
Tercio@23 775 if not confirmText then
Tercio@23 776 local name, desc = option.name, option.desc
Tercio@23 777 if type(name) == "function" then
Tercio@23 778 name = name(info)
Tercio@23 779 end
Tercio@23 780 if type(desc) == "function" then
Tercio@23 781 desc = desc(info)
Tercio@23 782 end
Tercio@23 783 confirmText = name
Tercio@23 784 if desc then
Tercio@23 785 confirmText = confirmText.." - "..desc
Tercio@23 786 end
Tercio@23 787 end
Tercio@23 788
Tercio@23 789 local iscustom = user.rootframe:GetUserData("iscustom")
Tercio@23 790 local rootframe
Tercio@23 791
Tercio@23 792 if iscustom then
Tercio@23 793 rootframe = user.rootframe
Tercio@23 794 end
Tercio@23 795 local basepath = user.rootframe:GetUserData("basepath")
Tercio@23 796 if type(func) == "string" then
Tercio@23 797 if handler and handler[func] then
Tercio@23 798 confirmPopup(user.appName, rootframe, basepath, info, confirmText, handler[func], handler, info, ...)
Tercio@23 799 else
Tercio@23 800 error(format("Method %s doesn't exist in handler for type func", func))
Tercio@23 801 end
Tercio@23 802 elseif type(func) == "function" then
Tercio@23 803 confirmPopup(user.appName, rootframe, basepath, info, confirmText, func, info, ...)
Tercio@23 804 end
Tercio@23 805 --func will be called and info deleted when the confirm dialog is responded to
Tercio@23 806 return
Tercio@23 807 end
Tercio@23 808 end
Tercio@23 809
Tercio@23 810 --call the function
Tercio@23 811 if type(func) == "string" then
Tercio@23 812 if handler and handler[func] then
Tercio@23 813 safecall(handler[func],handler, info, ...)
Tercio@23 814 else
Tercio@23 815 error(format("Method %s doesn't exist in handler for type func", func))
Tercio@23 816 end
Tercio@23 817 elseif type(func) == "function" then
Tercio@23 818 safecall(func,info, ...)
Tercio@23 819 end
Tercio@23 820
Tercio@23 821
Tercio@23 822
Tercio@23 823 local iscustom = user.rootframe:GetUserData("iscustom")
Tercio@23 824 local basepath = user.rootframe:GetUserData("basepath") or emptyTbl
Tercio@23 825 --full refresh of the frame, some controls dont cause this on all events
Tercio@23 826 if option.type == "color" then
Tercio@23 827 if event == "OnValueConfirmed" then
Tercio@23 828
Tercio@23 829 if iscustom then
Tercio@23 830 AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath))
Tercio@23 831 else
Tercio@23 832 AceConfigDialog:Open(user.appName, unpack(basepath))
Tercio@23 833 end
Tercio@23 834 end
Tercio@23 835 elseif option.type == "range" then
Tercio@23 836 if event == "OnMouseUp" then
Tercio@23 837 if iscustom then
Tercio@23 838 AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath))
Tercio@23 839 else
Tercio@23 840 AceConfigDialog:Open(user.appName, unpack(basepath))
Tercio@23 841 end
Tercio@23 842 end
Tercio@23 843 --multiselects don't cause a refresh on 'OnValueChanged' only 'OnClosed'
Tercio@23 844 elseif option.type == "multiselect" then
Tercio@23 845 user.valuechanged = true
Tercio@23 846 else
Tercio@23 847 if iscustom then
Tercio@23 848 AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath))
Tercio@23 849 else
Tercio@23 850 AceConfigDialog:Open(user.appName, unpack(basepath))
Tercio@23 851 end
Tercio@23 852 end
Tercio@23 853
Tercio@23 854 end
Tercio@23 855 del(info)
Tercio@23 856 end
Tercio@23 857
Tercio@23 858 local function ActivateSlider(widget, event, value)
Tercio@23 859 local option = widget:GetUserData("option")
Tercio@23 860 local min, max, step = option.min or (not option.softMin and 0 or nil), option.max or (not option.softMax and 100 or nil), option.step
Tercio@23 861 if min then
Tercio@23 862 if step then
Tercio@23 863 value = math_floor((value - min) / step + 0.5) * step + min
Tercio@23 864 end
Tercio@23 865 value = math_max(value, min)
Tercio@23 866 end
Tercio@23 867 if max then
Tercio@23 868 value = math_min(value, max)
Tercio@23 869 end
Tercio@23 870 ActivateControl(widget,event,value)
Tercio@23 871 end
Tercio@23 872
Tercio@23 873 --called from a checkbox that is part of an internally created multiselect group
Tercio@23 874 --this type is safe to refresh on activation of one control
Tercio@23 875 local function ActivateMultiControl(widget, event, ...)
Tercio@23 876 ActivateControl(widget, event, widget:GetUserData("value"), ...)
Tercio@23 877 local user = widget:GetUserDataTable()
Tercio@23 878 local iscustom = user.rootframe:GetUserData("iscustom")
Tercio@23 879 local basepath = user.rootframe:GetUserData("basepath") or emptyTbl
Tercio@23 880 if iscustom then
Tercio@23 881 AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath))
Tercio@23 882 else
Tercio@23 883 AceConfigDialog:Open(user.appName, unpack(basepath))
Tercio@23 884 end
Tercio@23 885 end
Tercio@23 886
Tercio@23 887 local function MultiControlOnClosed(widget, event, ...)
Tercio@23 888 local user = widget:GetUserDataTable()
Tercio@23 889 if user.valuechanged then
Tercio@23 890 local iscustom = user.rootframe:GetUserData("iscustom")
Tercio@23 891 local basepath = user.rootframe:GetUserData("basepath") or emptyTbl
Tercio@23 892 if iscustom then
Tercio@23 893 AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath))
Tercio@23 894 else
Tercio@23 895 AceConfigDialog:Open(user.appName, unpack(basepath))
Tercio@23 896 end
Tercio@23 897 end
Tercio@23 898 end
Tercio@23 899
Tercio@23 900 local function FrameOnClose(widget, event)
Tercio@23 901 local appName = widget:GetUserData("appName")
Tercio@23 902 AceConfigDialog.OpenFrames[appName] = nil
Tercio@23 903 gui:Release(widget)
Tercio@23 904 end
Tercio@23 905
Tercio@23 906 local function CheckOptionHidden(option, options, path, appName)
Tercio@23 907 --check for a specific boolean option
Tercio@23 908 local hidden = pickfirstset(option.dialogHidden,option.guiHidden)
Tercio@23 909 if hidden ~= nil then
Tercio@23 910 return hidden
Tercio@23 911 end
Tercio@23 912
Tercio@23 913 return GetOptionsMemberValue("hidden", option, options, path, appName)
Tercio@23 914 end
Tercio@23 915
Tercio@23 916 local function CheckOptionDisabled(option, options, path, appName)
Tercio@23 917 --check for a specific boolean option
Tercio@23 918 local disabled = pickfirstset(option.dialogDisabled,option.guiDisabled)
Tercio@23 919 if disabled ~= nil then
Tercio@23 920 return disabled
Tercio@23 921 end
Tercio@23 922
Tercio@23 923 return GetOptionsMemberValue("disabled", option, options, path, appName)
Tercio@23 924 end
Tercio@23 925 --[[
Tercio@23 926 local function BuildTabs(group, options, path, appName)
Tercio@23 927 local tabs = new()
Tercio@23 928 local text = new()
Tercio@23 929 local keySort = new()
Tercio@23 930 local opts = new()
Tercio@23 931
Tercio@23 932 BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
Tercio@23 933
Tercio@23 934 for i = 1, #keySort do
Tercio@23 935 local k = keySort[i]
Tercio@23 936 local v = opts[k]
Tercio@23 937 if v.type == "group" then
Tercio@23 938 path[#path+1] = k
Tercio@23 939 local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
Tercio@23 940 local hidden = CheckOptionHidden(v, options, path, appName)
Tercio@23 941 if not inline and not hidden then
Tercio@23 942 tinsert(tabs, k)
Tercio@23 943 text[k] = GetOptionsMemberValue("name", v, options, path, appName)
Tercio@23 944 end
Tercio@23 945 path[#path] = nil
Tercio@23 946 end
Tercio@23 947 end
Tercio@23 948
Tercio@23 949 del(keySort)
Tercio@23 950 del(opts)
Tercio@23 951
Tercio@23 952 return tabs, text
Tercio@23 953 end
Tercio@23 954 ]]
Tercio@23 955 local function BuildSelect(group, options, path, appName)
Tercio@23 956 local groups = new()
Tercio@23 957 local order = new()
Tercio@23 958 local keySort = new()
Tercio@23 959 local opts = new()
Tercio@23 960
Tercio@23 961 BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
Tercio@23 962
Tercio@23 963 for i = 1, #keySort do
Tercio@23 964 local k = keySort[i]
Tercio@23 965 local v = opts[k]
Tercio@23 966 if v.type == "group" then
Tercio@23 967 path[#path+1] = k
Tercio@23 968 local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
Tercio@23 969 local hidden = CheckOptionHidden(v, options, path, appName)
Tercio@23 970 if not inline and not hidden then
Tercio@23 971 groups[k] = GetOptionsMemberValue("name", v, options, path, appName)
Tercio@23 972 tinsert(order, k)
Tercio@23 973 end
Tercio@23 974 path[#path] = nil
Tercio@23 975 end
Tercio@23 976 end
Tercio@23 977
Tercio@23 978 del(opts)
Tercio@23 979 del(keySort)
Tercio@23 980
Tercio@23 981 return groups, order
Tercio@23 982 end
Tercio@23 983
Tercio@23 984 local function BuildSubGroups(group, tree, options, path, appName)
Tercio@23 985 local keySort = new()
Tercio@23 986 local opts = new()
Tercio@23 987
Tercio@23 988 BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
Tercio@23 989
Tercio@23 990 for i = 1, #keySort do
Tercio@23 991 local k = keySort[i]
Tercio@23 992 local v = opts[k]
Tercio@23 993 if v.type == "group" then
Tercio@23 994 path[#path+1] = k
Tercio@23 995 local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
Tercio@23 996 local hidden = CheckOptionHidden(v, options, path, appName)
Tercio@23 997 if not inline and not hidden then
Tercio@23 998 local entry = new()
Tercio@23 999 entry.value = k
Tercio@23 1000 entry.text = GetOptionsMemberValue("name", v, options, path, appName)
Tercio@23 1001 entry.icon = GetOptionsMemberValue("icon", v, options, path, appName)
Tercio@23 1002 entry.iconCoords = GetOptionsMemberValue("iconCoords", v, options, path, appName)
Tercio@23 1003 entry.disabled = CheckOptionDisabled(v, options, path, appName)
Tercio@23 1004 if not tree.children then tree.children = new() end
Tercio@23 1005 tinsert(tree.children,entry)
Tercio@23 1006 if (v.childGroups or "tree") == "tree" then
Tercio@23 1007 BuildSubGroups(v,entry, options, path, appName)
Tercio@23 1008 end
Tercio@23 1009 end
Tercio@23 1010 path[#path] = nil
Tercio@23 1011 end
Tercio@23 1012 end
Tercio@23 1013
Tercio@23 1014 del(keySort)
Tercio@23 1015 del(opts)
Tercio@23 1016 end
Tercio@23 1017
Tercio@23 1018 local function BuildGroups(group, options, path, appName, recurse)
Tercio@23 1019 local tree = new()
Tercio@23 1020 local keySort = new()
Tercio@23 1021 local opts = new()
Tercio@23 1022
Tercio@23 1023 BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
Tercio@23 1024
Tercio@23 1025 for i = 1, #keySort do
Tercio@23 1026 local k = keySort[i]
Tercio@23 1027 local v = opts[k]
Tercio@23 1028 if v.type == "group" then
Tercio@23 1029 path[#path+1] = k
Tercio@23 1030 local inline = pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
Tercio@23 1031 local hidden = CheckOptionHidden(v, options, path, appName)
Tercio@23 1032 if not inline and not hidden then
Tercio@23 1033 local entry = new()
Tercio@23 1034 entry.value = k
Tercio@23 1035 entry.text = GetOptionsMemberValue("name", v, options, path, appName)
Tercio@23 1036 entry.icon = GetOptionsMemberValue("icon", v, options, path, appName)
Tercio@58 1037 entry.iconCoords = GetOptionsMemberValue("iconCoords", v, options, path, appName)
Tercio@23 1038 entry.disabled = CheckOptionDisabled(v, options, path, appName)
Tercio@23 1039 tinsert(tree,entry)
Tercio@23 1040 if recurse and (v.childGroups or "tree") == "tree" then
Tercio@23 1041 BuildSubGroups(v,entry, options, path, appName)
Tercio@23 1042 end
Tercio@23 1043 end
Tercio@23 1044 path[#path] = nil
Tercio@23 1045 end
Tercio@23 1046 end
Tercio@23 1047 del(keySort)
Tercio@23 1048 del(opts)
Tercio@23 1049 return tree
Tercio@23 1050 end
Tercio@23 1051
Tercio@23 1052 local function InjectInfo(control, options, option, path, rootframe, appName)
Tercio@23 1053 local user = control:GetUserDataTable()
Tercio@23 1054 for i = 1, #path do
Tercio@23 1055 user[i] = path[i]
Tercio@23 1056 end
Tercio@23 1057 user.rootframe = rootframe
Tercio@23 1058 user.option = option
Tercio@23 1059 user.options = options
Tercio@23 1060 user.path = copy(path)
Tercio@23 1061 user.appName = appName
Tercio@23 1062 control:SetCallback("OnRelease", CleanUserData)
Tercio@23 1063 control:SetCallback("OnLeave", OptionOnMouseLeave)
Tercio@23 1064 control:SetCallback("OnEnter", OptionOnMouseOver)
Tercio@23 1065 end
Tercio@23 1066
Tercio@23 1067
Tercio@23 1068 --[[
Tercio@23 1069 options - root of the options table being fed
Tercio@23 1070 container - widget that controls will be placed in
Tercio@23 1071 rootframe - Frame object the options are in
Tercio@23 1072 path - table with the keys to get to the group being fed
Tercio@23 1073 --]]
Tercio@23 1074
Tercio@23 1075 local function FeedOptions(appName, options,container,rootframe,path,group,inline)
Tercio@23 1076 local keySort = new()
Tercio@23 1077 local opts = new()
Tercio@23 1078
Tercio@23 1079 BuildSortedOptionsTable(group, keySort, opts, options, path, appName)
Tercio@23 1080
Tercio@23 1081 for i = 1, #keySort do
Tercio@23 1082 local k = keySort[i]
Tercio@23 1083 local v = opts[k]
Tercio@23 1084 tinsert(path, k)
Tercio@23 1085 local hidden = CheckOptionHidden(v, options, path, appName)
Tercio@23 1086 local name = GetOptionsMemberValue("name", v, options, path, appName)
Tercio@23 1087 if not hidden then
Tercio@23 1088 if v.type == "group" then
Tercio@23 1089 if inline or pickfirstset(v.dialogInline,v.guiInline,v.inline, false) then
Tercio@23 1090 --Inline group
Tercio@23 1091 local GroupContainer
Tercio@23 1092 if name and name ~= "" then
Tercio@23 1093 GroupContainer = gui:Create("InlineGroup")
Tercio@23 1094 GroupContainer:SetTitle(name or "")
Tercio@23 1095 else
Tercio@23 1096 GroupContainer = gui:Create("SimpleGroup")
Tercio@23 1097 end
Tercio@23 1098
Tercio@23 1099 GroupContainer.width = "fill"
Tercio@23 1100 GroupContainer:SetLayout("flow")
Tercio@23 1101 container:AddChild(GroupContainer)
Tercio@23 1102 FeedOptions(appName,options,GroupContainer,rootframe,path,v,true)
Tercio@23 1103 end
Tercio@23 1104 else
Tercio@23 1105 --Control to feed
Tercio@23 1106 local control
Tercio@23 1107
Tercio@23 1108 local name = GetOptionsMemberValue("name", v, options, path, appName)
Tercio@23 1109
Tercio@23 1110 if v.type == "execute" then
Tercio@23 1111
Tercio@23 1112 local imageCoords = GetOptionsMemberValue("imageCoords",v, options, path, appName)
Tercio@23 1113 local image, width, height = GetOptionsMemberValue("image",v, options, path, appName)
Tercio@23 1114
Tercio@51 1115 if type(image) == "string" or type(image) == "number" then
Tercio@23 1116 control = gui:Create("Icon")
Tercio@23 1117 if not width then
Tercio@23 1118 width = GetOptionsMemberValue("imageWidth",v, options, path, appName)
Tercio@23 1119 end
Tercio@23 1120 if not height then
Tercio@23 1121 height = GetOptionsMemberValue("imageHeight",v, options, path, appName)
Tercio@23 1122 end
Tercio@23 1123 if type(imageCoords) == "table" then
Tercio@23 1124 control:SetImage(image, unpack(imageCoords))
Tercio@23 1125 else
Tercio@23 1126 control:SetImage(image)
Tercio@23 1127 end
Tercio@23 1128 if type(width) ~= "number" then
Tercio@23 1129 width = 32
Tercio@23 1130 end
Tercio@23 1131 if type(height) ~= "number" then
Tercio@23 1132 height = 32
Tercio@23 1133 end
Tercio@23 1134 control:SetImageSize(width, height)
Tercio@23 1135 control:SetLabel(name)
Tercio@23 1136 else
Tercio@23 1137 control = gui:Create("Button")
Tercio@23 1138 control:SetText(name)
Tercio@23 1139 end
Tercio@23 1140 control:SetCallback("OnClick",ActivateControl)
Tercio@23 1141
Tercio@23 1142 elseif v.type == "input" then
Tercio@23 1143 local controlType = v.dialogControl or v.control or (v.multiline and "MultiLineEditBox") or "EditBox"
Tercio@23 1144 control = gui:Create(controlType)
Tercio@23 1145 if not control then
Tercio@23 1146 geterrorhandler()(("Invalid Custom Control Type - %s"):format(tostring(controlType)))
Tercio@23 1147 control = gui:Create(v.multiline and "MultiLineEditBox" or "EditBox")
Tercio@23 1148 end
Tercio@23 1149
Tercio@23 1150 if v.multiline and control.SetNumLines then
Tercio@23 1151 control:SetNumLines(tonumber(v.multiline) or 4)
Tercio@23 1152 end
Tercio@23 1153 control:SetLabel(name)
Tercio@23 1154 control:SetCallback("OnEnterPressed",ActivateControl)
Tercio@23 1155 local text = GetOptionsMemberValue("get",v, options, path, appName)
Tercio@23 1156 if type(text) ~= "string" then
Tercio@23 1157 text = ""
Tercio@23 1158 end
Tercio@23 1159 control:SetText(text)
Tercio@23 1160
Tercio@23 1161 elseif v.type == "toggle" then
Tercio@23 1162 control = gui:Create("CheckBox")
Tercio@23 1163 control:SetLabel(name)
Tercio@23 1164 control:SetTriState(v.tristate)
Tercio@23 1165 local value = GetOptionsMemberValue("get",v, options, path, appName)
Tercio@23 1166 control:SetValue(value)
Tercio@23 1167 control:SetCallback("OnValueChanged",ActivateControl)
Tercio@23 1168
Tercio@23 1169 if v.descStyle == "inline" then
Tercio@23 1170 local desc = GetOptionsMemberValue("desc", v, options, path, appName)
Tercio@23 1171 control:SetDescription(desc)
Tercio@23 1172 end
Tercio@23 1173
Tercio@23 1174 local image = GetOptionsMemberValue("image", v, options, path, appName)
Tercio@23 1175 local imageCoords = GetOptionsMemberValue("imageCoords", v, options, path, appName)
Tercio@23 1176
Tercio@51 1177 if type(image) == "string" or type(image) == "number" then
Tercio@23 1178 if type(imageCoords) == "table" then
Tercio@23 1179 control:SetImage(image, unpack(imageCoords))
Tercio@23 1180 else
Tercio@23 1181 control:SetImage(image)
Tercio@23 1182 end
Tercio@23 1183 end
Tercio@23 1184 elseif v.type == "range" then
Tercio@23 1185 control = gui:Create("Slider")
Tercio@23 1186 control:SetLabel(name)
Tercio@23 1187 control:SetSliderValues(v.softMin or v.min or 0, v.softMax or v.max or 100, v.bigStep or v.step or 0)
Tercio@23 1188 control:SetIsPercent(v.isPercent)
Tercio@23 1189 local value = GetOptionsMemberValue("get",v, options, path, appName)
Tercio@23 1190 if type(value) ~= "number" then
Tercio@23 1191 value = 0
Tercio@23 1192 end
Tercio@23 1193 control:SetValue(value)
Tercio@23 1194 control:SetCallback("OnValueChanged",ActivateSlider)
Tercio@23 1195 control:SetCallback("OnMouseUp",ActivateSlider)
Tercio@23 1196
Tercio@23 1197 elseif v.type == "select" then
Tercio@23 1198 local values = GetOptionsMemberValue("values", v, options, path, appName)
Tercio@23 1199 if v.style == "radio" then
Tercio@23 1200 local disabled = CheckOptionDisabled(v, options, path, appName)
Tercio@23 1201 local width = GetOptionsMemberValue("width",v,options,path,appName)
Tercio@23 1202 control = gui:Create("InlineGroup")
Tercio@23 1203 control:SetLayout("Flow")
Tercio@23 1204 control:SetTitle(name)
Tercio@23 1205 control.width = "fill"
Tercio@23 1206
Tercio@23 1207 control:PauseLayout()
Tercio@23 1208 local optionValue = GetOptionsMemberValue("get",v, options, path, appName)
Tercio@23 1209 local t = {}
Tercio@23 1210 for value, text in pairs(values) do
Tercio@23 1211 t[#t+1]=value
Tercio@23 1212 end
Tercio@23 1213 tsort(t)
Tercio@23 1214 for k, value in ipairs(t) do
Tercio@23 1215 local text = values[value]
Tercio@23 1216 local radio = gui:Create("CheckBox")
Tercio@23 1217 radio:SetLabel(text)
Tercio@23 1218 radio:SetUserData("value", value)
Tercio@23 1219 radio:SetUserData("text", text)
Tercio@23 1220 radio:SetDisabled(disabled)
Tercio@23 1221 radio:SetType("radio")
Tercio@23 1222 radio:SetValue(optionValue == value)
Tercio@23 1223 radio:SetCallback("OnValueChanged", ActivateMultiControl)
Tercio@23 1224 InjectInfo(radio, options, v, path, rootframe, appName)
Tercio@23 1225 control:AddChild(radio)
Tercio@23 1226 if width == "double" then
Tercio@23 1227 radio:SetWidth(width_multiplier * 2)
Tercio@23 1228 elseif width == "half" then
Tercio@23 1229 radio:SetWidth(width_multiplier / 2)
Tercio@58 1230 elseif (type(width) == "number") then
Tercio@58 1231 radio:SetWidth(width_multiplier * width)
Tercio@23 1232 elseif width == "full" then
Tercio@23 1233 radio.width = "fill"
Tercio@23 1234 else
Tercio@23 1235 radio:SetWidth(width_multiplier)
Tercio@23 1236 end
Tercio@23 1237 end
Tercio@23 1238 control:ResumeLayout()
Tercio@23 1239 control:DoLayout()
Tercio@23 1240 else
Tercio@23 1241 local controlType = v.dialogControl or v.control or "Dropdown"
Tercio@23 1242 control = gui:Create(controlType)
Tercio@23 1243 if not control then
Tercio@23 1244 geterrorhandler()(("Invalid Custom Control Type - %s"):format(tostring(controlType)))
Tercio@23 1245 control = gui:Create("Dropdown")
Tercio@23 1246 end
Tercio@23 1247 local itemType = v.itemControl
Tercio@23 1248 if itemType and not gui:GetWidgetVersion(itemType) then
Tercio@23 1249 geterrorhandler()(("Invalid Custom Item Type - %s"):format(tostring(itemType)))
Tercio@23 1250 itemType = nil
Tercio@23 1251 end
Tercio@23 1252 control:SetLabel(name)
Tercio@23 1253 control:SetList(values, nil, itemType)
Tercio@23 1254 local value = GetOptionsMemberValue("get",v, options, path, appName)
Tercio@23 1255 if not values[value] then
Tercio@23 1256 value = nil
Tercio@23 1257 end
Tercio@23 1258 control:SetValue(value)
Tercio@23 1259 control:SetCallback("OnValueChanged", ActivateControl)
Tercio@23 1260 end
Tercio@23 1261
Tercio@23 1262 elseif v.type == "multiselect" then
Tercio@23 1263 local values = GetOptionsMemberValue("values", v, options, path, appName)
Tercio@23 1264 local disabled = CheckOptionDisabled(v, options, path, appName)
Tercio@23 1265
Tercio@23 1266 local controlType = v.dialogControl or v.control
Tercio@23 1267
Tercio@23 1268 local valuesort = new()
Tercio@23 1269 if values then
Tercio@23 1270 for value, text in pairs(values) do
Tercio@23 1271 tinsert(valuesort, value)
Tercio@23 1272 end
Tercio@23 1273 end
Tercio@23 1274 tsort(valuesort)
Tercio@23 1275
Tercio@23 1276 if controlType then
Tercio@23 1277 control = gui:Create(controlType)
Tercio@23 1278 if not control then
Tercio@23 1279 geterrorhandler()(("Invalid Custom Control Type - %s"):format(tostring(controlType)))
Tercio@23 1280 end
Tercio@23 1281 end
Tercio@23 1282 if control then
Tercio@23 1283 control:SetMultiselect(true)
Tercio@23 1284 control:SetLabel(name)
Tercio@23 1285 control:SetList(values)
Tercio@23 1286 control:SetDisabled(disabled)
Tercio@23 1287 control:SetCallback("OnValueChanged",ActivateControl)
Tercio@23 1288 control:SetCallback("OnClosed", MultiControlOnClosed)
Tercio@23 1289 local width = GetOptionsMemberValue("width",v,options,path,appName)
Tercio@23 1290 if width == "double" then
Tercio@23 1291 control:SetWidth(width_multiplier * 2)
Tercio@23 1292 elseif width == "half" then
Tercio@23 1293 control:SetWidth(width_multiplier / 2)
Tercio@58 1294 elseif (type(width) == "number") then
Tercio@58 1295 control:SetWidth(width_multiplier * width)
Tercio@23 1296 elseif width == "full" then
Tercio@23 1297 control.width = "fill"
Tercio@23 1298 else
Tercio@23 1299 control:SetWidth(width_multiplier)
Tercio@23 1300 end
Tercio@23 1301 --check:SetTriState(v.tristate)
Tercio@23 1302 for i = 1, #valuesort do
Tercio@23 1303 local key = valuesort[i]
Tercio@23 1304 local value = GetOptionsMemberValue("get",v, options, path, appName, key)
Tercio@23 1305 control:SetItemValue(key,value)
Tercio@23 1306 end
Tercio@23 1307 else
Tercio@23 1308 control = gui:Create("InlineGroup")
Tercio@23 1309 control:SetLayout("Flow")
Tercio@23 1310 control:SetTitle(name)
Tercio@23 1311 control.width = "fill"
Tercio@23 1312
Tercio@23 1313 control:PauseLayout()
Tercio@23 1314 local width = GetOptionsMemberValue("width",v,options,path,appName)
Tercio@23 1315 for i = 1, #valuesort do
Tercio@23 1316 local value = valuesort[i]
Tercio@23 1317 local text = values[value]
Tercio@23 1318 local check = gui:Create("CheckBox")
Tercio@23 1319 check:SetLabel(text)
Tercio@23 1320 check:SetUserData("value", value)
Tercio@23 1321 check:SetUserData("text", text)
Tercio@23 1322 check:SetDisabled(disabled)
Tercio@23 1323 check:SetTriState(v.tristate)
Tercio@23 1324 check:SetValue(GetOptionsMemberValue("get",v, options, path, appName, value))
Tercio@23 1325 check:SetCallback("OnValueChanged",ActivateMultiControl)
Tercio@23 1326 InjectInfo(check, options, v, path, rootframe, appName)
Tercio@23 1327 control:AddChild(check)
Tercio@23 1328 if width == "double" then
Tercio@23 1329 check:SetWidth(width_multiplier * 2)
Tercio@23 1330 elseif width == "half" then
Tercio@23 1331 check:SetWidth(width_multiplier / 2)
Tercio@58 1332 elseif (type(width) == "number") then
Tercio@58 1333 control:SetWidth(width_multiplier * width)
Tercio@23 1334 elseif width == "full" then
Tercio@23 1335 check.width = "fill"
Tercio@23 1336 else
Tercio@23 1337 check:SetWidth(width_multiplier)
Tercio@23 1338 end
Tercio@23 1339 end
Tercio@23 1340 control:ResumeLayout()
Tercio@23 1341 control:DoLayout()
Tercio@23 1342
Tercio@23 1343
Tercio@23 1344 end
Tercio@23 1345
Tercio@23 1346 del(valuesort)
Tercio@23 1347
Tercio@23 1348 elseif v.type == "color" then
Tercio@23 1349 control = gui:Create("ColorPicker")
Tercio@23 1350 control:SetLabel(name)
Tercio@23 1351 control:SetHasAlpha(GetOptionsMemberValue("hasAlpha",v, options, path, appName))
Tercio@23 1352 control:SetColor(GetOptionsMemberValue("get",v, options, path, appName))
Tercio@23 1353 control:SetCallback("OnValueChanged",ActivateControl)
Tercio@23 1354 control:SetCallback("OnValueConfirmed",ActivateControl)
Tercio@23 1355
Tercio@23 1356 elseif v.type == "keybinding" then
Tercio@23 1357 control = gui:Create("Keybinding")
Tercio@23 1358 control:SetLabel(name)
Tercio@23 1359 control:SetKey(GetOptionsMemberValue("get",v, options, path, appName))
Tercio@23 1360 control:SetCallback("OnKeyChanged",ActivateControl)
Tercio@23 1361
Tercio@23 1362 elseif v.type == "header" then
Tercio@23 1363 control = gui:Create("Heading")
Tercio@23 1364 control:SetText(name)
Tercio@23 1365 control.width = "fill"
Tercio@23 1366
Tercio@23 1367 elseif v.type == "description" then
Tercio@23 1368 control = gui:Create("Label")
Tercio@23 1369 control:SetText(name)
Tercio@23 1370
Tercio@23 1371 local fontSize = GetOptionsMemberValue("fontSize",v, options, path, appName)
Tercio@23 1372 if fontSize == "medium" then
Tercio@23 1373 control:SetFontObject(GameFontHighlight)
Tercio@23 1374 elseif fontSize == "large" then
Tercio@23 1375 control:SetFontObject(GameFontHighlightLarge)
Tercio@23 1376 else -- small or invalid
Tercio@23 1377 control:SetFontObject(GameFontHighlightSmall)
Tercio@23 1378 end
Tercio@23 1379
Tercio@23 1380 local imageCoords = GetOptionsMemberValue("imageCoords",v, options, path, appName)
Tercio@23 1381 local image, width, height = GetOptionsMemberValue("image",v, options, path, appName)
Tercio@23 1382
Tercio@51 1383 if type(image) == "string" or type(image) == "number" then
Tercio@23 1384 if not width then
Tercio@23 1385 width = GetOptionsMemberValue("imageWidth",v, options, path, appName)
Tercio@23 1386 end
Tercio@23 1387 if not height then
Tercio@23 1388 height = GetOptionsMemberValue("imageHeight",v, options, path, appName)
Tercio@23 1389 end
Tercio@23 1390 if type(imageCoords) == "table" then
Tercio@23 1391 control:SetImage(image, unpack(imageCoords))
Tercio@23 1392 else
Tercio@23 1393 control:SetImage(image)
Tercio@23 1394 end
Tercio@23 1395 if type(width) ~= "number" then
Tercio@23 1396 width = 32
Tercio@23 1397 end
Tercio@23 1398 if type(height) ~= "number" then
Tercio@23 1399 height = 32
Tercio@23 1400 end
Tercio@23 1401 control:SetImageSize(width, height)
Tercio@23 1402 end
Tercio@23 1403 local width = GetOptionsMemberValue("width",v,options,path,appName)
Tercio@23 1404 control.width = not width and "fill"
Tercio@23 1405 end
Tercio@23 1406
Tercio@23 1407 --Common Init
Tercio@23 1408 if control then
Tercio@23 1409 if control.width ~= "fill" then
Tercio@23 1410 local width = GetOptionsMemberValue("width",v,options,path,appName)
Tercio@23 1411 if width == "double" then
Tercio@23 1412 control:SetWidth(width_multiplier * 2)
Tercio@23 1413 elseif width == "half" then
Tercio@23 1414 control:SetWidth(width_multiplier / 2)
Tercio@58 1415 elseif (type(width) == "number") then
Tercio@58 1416 control:SetWidth(width_multiplier * width)
Tercio@23 1417 elseif width == "full" then
Tercio@23 1418 control.width = "fill"
Tercio@23 1419 else
Tercio@23 1420 control:SetWidth(width_multiplier)
Tercio@23 1421 end
Tercio@23 1422 end
Tercio@23 1423 if control.SetDisabled then
Tercio@23 1424 local disabled = CheckOptionDisabled(v, options, path, appName)
Tercio@23 1425 control:SetDisabled(disabled)
Tercio@23 1426 end
Tercio@23 1427
Tercio@23 1428 InjectInfo(control, options, v, path, rootframe, appName)
Tercio@23 1429 container:AddChild(control)
Tercio@23 1430 end
Tercio@23 1431
Tercio@23 1432 end
Tercio@23 1433 end
Tercio@23 1434 tremove(path)
Tercio@23 1435 end
Tercio@23 1436 container:ResumeLayout()
Tercio@23 1437 container:DoLayout()
Tercio@23 1438 del(keySort)
Tercio@23 1439 del(opts)
Tercio@23 1440 end
Tercio@23 1441
Tercio@23 1442 local function BuildPath(path, ...)
Tercio@23 1443 for i = 1, select("#",...) do
Tercio@23 1444 tinsert(path, (select(i,...)))
Tercio@23 1445 end
Tercio@23 1446 end
Tercio@23 1447
Tercio@23 1448
Tercio@23 1449 local function TreeOnButtonEnter(widget, event, uniquevalue, button)
Tercio@23 1450 local user = widget:GetUserDataTable()
Tercio@23 1451 if not user then return end
Tercio@23 1452 local options = user.options
Tercio@23 1453 local option = user.option
Tercio@23 1454 local path = user.path
Tercio@23 1455 local appName = user.appName
Tercio@23 1456
Tercio@23 1457 local feedpath = new()
Tercio@23 1458 for i = 1, #path do
Tercio@23 1459 feedpath[i] = path[i]
Tercio@23 1460 end
Tercio@23 1461
Tercio@23 1462 BuildPath(feedpath, ("\001"):split(uniquevalue))
Tercio@23 1463 local group = options
Tercio@23 1464 for i = 1, #feedpath do
Tercio@23 1465 if not group then return end
Tercio@23 1466 group = GetSubOption(group, feedpath[i])
Tercio@23 1467 end
Tercio@23 1468
Tercio@23 1469 local name = GetOptionsMemberValue("name", group, options, feedpath, appName)
Tercio@23 1470 local desc = GetOptionsMemberValue("desc", group, options, feedpath, appName)
Tercio@23 1471
Tercio@23 1472 GameTooltip:SetOwner(button, "ANCHOR_NONE")
Tercio@23 1473 if widget.type == "TabGroup" then
Tercio@23 1474 GameTooltip:SetPoint("BOTTOM",button,"TOP")
Tercio@23 1475 else
Tercio@23 1476 GameTooltip:SetPoint("LEFT",button,"RIGHT")
Tercio@23 1477 end
Tercio@23 1478
Tercio@23 1479 GameTooltip:SetText(name, 1, .82, 0, true)
Tercio@23 1480
Tercio@23 1481 if type(desc) == "string" then
Tercio@23 1482 GameTooltip:AddLine(desc, 1, 1, 1, true)
Tercio@23 1483 end
Tercio@23 1484
Tercio@23 1485 GameTooltip:Show()
Tercio@23 1486 end
Tercio@23 1487
Tercio@23 1488 local function TreeOnButtonLeave(widget, event, value, button)
Tercio@23 1489 GameTooltip:Hide()
Tercio@23 1490 end
Tercio@23 1491
Tercio@23 1492
Tercio@23 1493 local function GroupExists(appName, options, path, uniquevalue)
Tercio@23 1494 if not uniquevalue then return false end
Tercio@23 1495
Tercio@23 1496 local feedpath = new()
Tercio@23 1497 local temppath = new()
Tercio@23 1498 for i = 1, #path do
Tercio@23 1499 feedpath[i] = path[i]
Tercio@23 1500 end
Tercio@23 1501
Tercio@23 1502 BuildPath(feedpath, ("\001"):split(uniquevalue))
Tercio@23 1503
Tercio@23 1504 local group = options
Tercio@23 1505 for i = 1, #feedpath do
Tercio@23 1506 local v = feedpath[i]
Tercio@23 1507 temppath[i] = v
Tercio@23 1508 group = GetSubOption(group, v)
Tercio@23 1509
Tercio@23 1510 if not group or group.type ~= "group" or CheckOptionHidden(group, options, temppath, appName) then
Tercio@23 1511 del(feedpath)
Tercio@23 1512 del(temppath)
Tercio@23 1513 return false
Tercio@23 1514 end
Tercio@23 1515 end
Tercio@23 1516 del(feedpath)
Tercio@23 1517 del(temppath)
Tercio@23 1518 return true
Tercio@23 1519 end
Tercio@23 1520
Tercio@23 1521 local function GroupSelected(widget, event, uniquevalue)
Tercio@23 1522
Tercio@23 1523 local user = widget:GetUserDataTable()
Tercio@23 1524
Tercio@23 1525 local options = user.options
Tercio@23 1526 local option = user.option
Tercio@23 1527 local path = user.path
Tercio@23 1528 local rootframe = user.rootframe
Tercio@23 1529
Tercio@23 1530 local feedpath = new()
Tercio@23 1531 for i = 1, #path do
Tercio@23 1532 feedpath[i] = path[i]
Tercio@23 1533 end
Tercio@23 1534
Tercio@23 1535 BuildPath(feedpath, ("\001"):split(uniquevalue))
Tercio@23 1536 local group = options
Tercio@23 1537 for i = 1, #feedpath do
Tercio@23 1538 group = GetSubOption(group, feedpath[i])
Tercio@23 1539 end
Tercio@23 1540 widget:ReleaseChildren()
Tercio@23 1541 AceConfigDialog:FeedGroup(user.appName,options,widget,rootframe,feedpath)
Tercio@23 1542
Tercio@23 1543 del(feedpath)
Tercio@23 1544 end
Tercio@23 1545
Tercio@23 1546
Tercio@23 1547
Tercio@23 1548 --[[
Tercio@23 1549 -- INTERNAL --
Tercio@23 1550 This function will feed one group, and any inline child groups into the given container
Tercio@23 1551 Select Groups will only have the selection control (tree, tabs, dropdown) fed in
Tercio@23 1552 and have a group selected, this event will trigger the feeding of child groups
Tercio@23 1553
Tercio@23 1554 Rules:
Tercio@23 1555 If the group is Inline, FeedOptions
Tercio@23 1556 If the group has no child groups, FeedOptions
Tercio@23 1557
Tercio@23 1558 If the group is a tab or select group, FeedOptions then add the Group Control
Tercio@23 1559 If the group is a tree group FeedOptions then
Tercio@23 1560 its parent isnt a tree group: then add the tree control containing this and all child tree groups
Tercio@23 1561 if its parent is a tree group, its already a node on a tree
Tercio@23 1562 --]]
Tercio@23 1563
Tercio@23 1564 function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isRoot)
Tercio@23 1565 local group = options
Tercio@23 1566 --follow the path to get to the curent group
Tercio@23 1567 local inline
Tercio@23 1568 local grouptype, parenttype = options.childGroups, "none"
Tercio@23 1569
Tercio@23 1570
Tercio@23 1571 for i = 1, #path do
Tercio@23 1572 local v = path[i]
Tercio@23 1573 group = GetSubOption(group, v)
Tercio@23 1574 inline = inline or pickfirstset(v.dialogInline,v.guiInline,v.inline, false)
Tercio@23 1575 parenttype = grouptype
Tercio@23 1576 grouptype = group.childGroups
Tercio@23 1577 end
Tercio@23 1578
Tercio@23 1579 if not parenttype then
Tercio@23 1580 parenttype = "tree"
Tercio@23 1581 end
Tercio@23 1582
Tercio@23 1583 --check if the group has child groups
Tercio@23 1584 local hasChildGroups
Tercio@23 1585 for k, v in pairs(group.args) do
Tercio@23 1586 if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) and not CheckOptionHidden(v, options, path, appName) then
Tercio@23 1587 hasChildGroups = true
Tercio@23 1588 end
Tercio@23 1589 end
Tercio@23 1590 if group.plugins then
Tercio@23 1591 for plugin, t in pairs(group.plugins) do
Tercio@23 1592 for k, v in pairs(t) do
Tercio@23 1593 if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) and not CheckOptionHidden(v, options, path, appName) then
Tercio@23 1594 hasChildGroups = true
Tercio@23 1595 end
Tercio@23 1596 end
Tercio@23 1597 end
Tercio@23 1598 end
Tercio@23 1599
Tercio@23 1600 container:SetLayout("flow")
Tercio@23 1601 local scroll
Tercio@23 1602
Tercio@23 1603 --Add a scrollframe if we are not going to add a group control, this is the inverse of the conditions for that later on
Tercio@23 1604 if (not (hasChildGroups and not inline)) or (grouptype ~= "tab" and grouptype ~= "select" and (parenttype == "tree" and not isRoot)) then
Tercio@23 1605 if container.type ~= "InlineGroup" and container.type ~= "SimpleGroup" then
Tercio@23 1606 scroll = gui:Create("ScrollFrame")
Tercio@23 1607 scroll:SetLayout("flow")
Tercio@23 1608 scroll.width = "fill"
Tercio@23 1609 scroll.height = "fill"
Tercio@23 1610 container:SetLayout("fill")
Tercio@23 1611 container:AddChild(scroll)
Tercio@23 1612 container = scroll
Tercio@23 1613 end
Tercio@23 1614 end
Tercio@23 1615
Tercio@23 1616 FeedOptions(appName,options,container,rootframe,path,group,nil)
Tercio@23 1617
Tercio@23 1618 if scroll then
Tercio@23 1619 container:PerformLayout()
Tercio@23 1620 local status = self:GetStatusTable(appName, path)
Tercio@23 1621 if not status.scroll then
Tercio@23 1622 status.scroll = {}
Tercio@23 1623 end
Tercio@23 1624 scroll:SetStatusTable(status.scroll)
Tercio@23 1625 end
Tercio@23 1626
Tercio@23 1627 if hasChildGroups and not inline then
Tercio@23 1628 local name = GetOptionsMemberValue("name", group, options, path, appName)
Tercio@23 1629 if grouptype == "tab" then
Tercio@23 1630
Tercio@23 1631 local tab = gui:Create("TabGroup")
Tercio@23 1632 InjectInfo(tab, options, group, path, rootframe, appName)
Tercio@23 1633 tab:SetCallback("OnGroupSelected", GroupSelected)
Tercio@23 1634 tab:SetCallback("OnTabEnter", TreeOnButtonEnter)
Tercio@23 1635 tab:SetCallback("OnTabLeave", TreeOnButtonLeave)
Tercio@23 1636
Tercio@23 1637 local status = AceConfigDialog:GetStatusTable(appName, path)
Tercio@23 1638 if not status.groups then
Tercio@23 1639 status.groups = {}
Tercio@23 1640 end
Tercio@23 1641 tab:SetStatusTable(status.groups)
Tercio@23 1642 tab.width = "fill"
Tercio@23 1643 tab.height = "fill"
Tercio@23 1644
Tercio@23 1645 local tabs = BuildGroups(group, options, path, appName)
Tercio@23 1646 tab:SetTabs(tabs)
Tercio@23 1647 tab:SetUserData("tablist", tabs)
Tercio@23 1648
Tercio@23 1649 for i = 1, #tabs do
Tercio@23 1650 local entry = tabs[i]
Tercio@23 1651 if not entry.disabled then
Tercio@23 1652 tab:SelectTab((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or entry.value)
Tercio@23 1653 break
Tercio@23 1654 end
Tercio@23 1655 end
Tercio@23 1656
Tercio@23 1657 container:AddChild(tab)
Tercio@23 1658
Tercio@23 1659 elseif grouptype == "select" then
Tercio@23 1660
Tercio@23 1661 local select = gui:Create("DropdownGroup")
Tercio@23 1662 select:SetTitle(name)
Tercio@23 1663 InjectInfo(select, options, group, path, rootframe, appName)
Tercio@23 1664 select:SetCallback("OnGroupSelected", GroupSelected)
Tercio@23 1665 local status = AceConfigDialog:GetStatusTable(appName, path)
Tercio@23 1666 if not status.groups then
Tercio@23 1667 status.groups = {}
Tercio@23 1668 end
Tercio@23 1669 select:SetStatusTable(status.groups)
Tercio@23 1670 local grouplist, orderlist = BuildSelect(group, options, path, appName)
Tercio@23 1671 select:SetGroupList(grouplist, orderlist)
Tercio@23 1672 select:SetUserData("grouplist", grouplist)
Tercio@23 1673 select:SetUserData("orderlist", orderlist)
Tercio@23 1674
Tercio@23 1675 local firstgroup = orderlist[1]
Tercio@23 1676 if firstgroup then
Tercio@23 1677 select:SetGroup((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or firstgroup)
Tercio@23 1678 end
Tercio@23 1679
Tercio@23 1680 select.width = "fill"
Tercio@23 1681 select.height = "fill"
Tercio@23 1682
Tercio@23 1683 container:AddChild(select)
Tercio@23 1684
Tercio@23 1685 --assume tree group by default
Tercio@23 1686 --if parenttype is tree then this group is already a node on that tree
Tercio@23 1687 elseif (parenttype ~= "tree") or isRoot then
Tercio@23 1688 local tree = gui:Create("TreeGroup")
Tercio@23 1689 InjectInfo(tree, options, group, path, rootframe, appName)
Tercio@23 1690 tree:EnableButtonTooltips(false)
Tercio@23 1691
Tercio@23 1692 tree.width = "fill"
Tercio@23 1693 tree.height = "fill"
Tercio@23 1694
Tercio@23 1695 tree:SetCallback("OnGroupSelected", GroupSelected)
Tercio@23 1696 tree:SetCallback("OnButtonEnter", TreeOnButtonEnter)
Tercio@23 1697 tree:SetCallback("OnButtonLeave", TreeOnButtonLeave)
Tercio@23 1698
Tercio@23 1699 local status = AceConfigDialog:GetStatusTable(appName, path)
Tercio@23 1700 if not status.groups then
Tercio@23 1701 status.groups = {}
Tercio@23 1702 end
Tercio@23 1703 local treedefinition = BuildGroups(group, options, path, appName, true)
Tercio@23 1704 tree:SetStatusTable(status.groups)
Tercio@23 1705
Tercio@23 1706 tree:SetTree(treedefinition)
Tercio@23 1707 tree:SetUserData("tree",treedefinition)
Tercio@23 1708
Tercio@23 1709 for i = 1, #treedefinition do
Tercio@23 1710 local entry = treedefinition[i]
Tercio@23 1711 if not entry.disabled then
Tercio@23 1712 tree:SelectByValue((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or entry.value)
Tercio@23 1713 break
Tercio@23 1714 end
Tercio@23 1715 end
Tercio@23 1716
Tercio@23 1717 container:AddChild(tree)
Tercio@23 1718 end
Tercio@23 1719 end
Tercio@23 1720 end
Tercio@23 1721
Tercio@23 1722 local old_CloseSpecialWindows
Tercio@23 1723
Tercio@23 1724
Tercio@23 1725 local function RefreshOnUpdate(this)
Tercio@23 1726 for appName in pairs(this.closing) do
Tercio@23 1727 if AceConfigDialog.OpenFrames[appName] then
Tercio@23 1728 AceConfigDialog.OpenFrames[appName]:Hide()
Tercio@23 1729 end
Tercio@23 1730 if AceConfigDialog.BlizOptions and AceConfigDialog.BlizOptions[appName] then
Tercio@23 1731 for key, widget in pairs(AceConfigDialog.BlizOptions[appName]) do
Tercio@23 1732 if not widget:IsVisible() then
Tercio@23 1733 widget:ReleaseChildren()
Tercio@23 1734 end
Tercio@23 1735 end
Tercio@23 1736 end
Tercio@23 1737 this.closing[appName] = nil
Tercio@23 1738 end
Tercio@23 1739
Tercio@23 1740 if this.closeAll then
Tercio@23 1741 for k, v in pairs(AceConfigDialog.OpenFrames) do
Tercio@23 1742 if not this.closeAllOverride[k] then
Tercio@23 1743 v:Hide()
Tercio@23 1744 end
Tercio@23 1745 end
Tercio@23 1746 this.closeAll = nil
Tercio@23 1747 wipe(this.closeAllOverride)
Tercio@23 1748 end
Tercio@23 1749
Tercio@23 1750 for appName in pairs(this.apps) do
Tercio@23 1751 if AceConfigDialog.OpenFrames[appName] then
Tercio@23 1752 local user = AceConfigDialog.OpenFrames[appName]:GetUserDataTable()
Tercio@23 1753 AceConfigDialog:Open(appName, unpack(user.basepath or emptyTbl))
Tercio@23 1754 end
Tercio@23 1755 if AceConfigDialog.BlizOptions and AceConfigDialog.BlizOptions[appName] then
Tercio@23 1756 for key, widget in pairs(AceConfigDialog.BlizOptions[appName]) do
Tercio@23 1757 local user = widget:GetUserDataTable()
Tercio@23 1758 if widget:IsVisible() then
Tercio@23 1759 AceConfigDialog:Open(widget:GetUserData("appName"), widget, unpack(user.basepath or emptyTbl))
Tercio@23 1760 end
Tercio@23 1761 end
Tercio@23 1762 end
Tercio@23 1763 this.apps[appName] = nil
Tercio@23 1764 end
Tercio@23 1765 this:SetScript("OnUpdate", nil)
Tercio@23 1766 end
Tercio@23 1767
Tercio@23 1768 -- Upgrade the OnUpdate script as well, if needed.
Tercio@23 1769 if AceConfigDialog.frame:GetScript("OnUpdate") then
Tercio@23 1770 AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate)
Tercio@23 1771 end
Tercio@23 1772
Tercio@23 1773 --- Close all open options windows
Tercio@23 1774 function AceConfigDialog:CloseAll()
Tercio@23 1775 AceConfigDialog.frame.closeAll = true
Tercio@23 1776 AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate)
Tercio@23 1777 if next(self.OpenFrames) then
Tercio@23 1778 return true
Tercio@23 1779 end
Tercio@23 1780 end
Tercio@23 1781
Tercio@23 1782 --- Close a specific options window.
Tercio@23 1783 -- @param appName The application name as given to `:RegisterOptionsTable()`
Tercio@23 1784 function AceConfigDialog:Close(appName)
Tercio@23 1785 if self.OpenFrames[appName] then
Tercio@23 1786 AceConfigDialog.frame.closing[appName] = true
Tercio@23 1787 AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate)
Tercio@23 1788 return true
Tercio@23 1789 end
Tercio@23 1790 end
Tercio@23 1791
Tercio@23 1792 -- Internal -- Called by AceConfigRegistry
Tercio@23 1793 function AceConfigDialog:ConfigTableChanged(event, appName)
Tercio@23 1794 AceConfigDialog.frame.apps[appName] = true
Tercio@23 1795 AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate)
Tercio@23 1796 end
Tercio@23 1797
Tercio@23 1798 reg.RegisterCallback(AceConfigDialog, "ConfigTableChange", "ConfigTableChanged")
Tercio@23 1799
Tercio@23 1800 --- Sets the default size of the options window for a specific application.
Tercio@23 1801 -- @param appName The application name as given to `:RegisterOptionsTable()`
Tercio@23 1802 -- @param width The default width
Tercio@23 1803 -- @param height The default height
Tercio@23 1804 function AceConfigDialog:SetDefaultSize(appName, width, height)
Tercio@23 1805 local status = AceConfigDialog:GetStatusTable(appName)
Tercio@23 1806 if type(width) == "number" and type(height) == "number" then
Tercio@23 1807 status.width = width
Tercio@23 1808 status.height = height
Tercio@23 1809 end
Tercio@23 1810 end
Tercio@23 1811
Tercio@23 1812 --- Open an option window at the specified path (if any).
Tercio@23 1813 -- This function can optionally feed the group into a pre-created container
Tercio@23 1814 -- instead of creating a new container frame.
Tercio@23 1815 -- @paramsig appName [, container][, ...]
Tercio@23 1816 -- @param appName The application name as given to `:RegisterOptionsTable()`
Tercio@23 1817 -- @param container An optional container frame to feed the options into
Tercio@23 1818 -- @param ... The path to open after creating the options window (see `:SelectGroup` for details)
Tercio@23 1819 function AceConfigDialog:Open(appName, container, ...)
Tercio@23 1820 if not old_CloseSpecialWindows then
Tercio@23 1821 old_CloseSpecialWindows = CloseSpecialWindows
Tercio@23 1822 CloseSpecialWindows = function()
Tercio@23 1823 local found = old_CloseSpecialWindows()
Tercio@23 1824 return self:CloseAll() or found
Tercio@23 1825 end
Tercio@23 1826 end
Tercio@23 1827 local app = reg:GetOptionsTable(appName)
Tercio@23 1828 if not app then
Tercio@23 1829 error(("%s isn't registed with AceConfigRegistry, unable to open config"):format(appName), 2)
Tercio@23 1830 end
Tercio@23 1831 local options = app("dialog", MAJOR)
Tercio@23 1832
Tercio@23 1833 local f
Tercio@23 1834
Tercio@23 1835 local path = new()
Tercio@23 1836 local name = GetOptionsMemberValue("name", options, options, path, appName)
Tercio@23 1837
Tercio@23 1838 --If an optional path is specified add it to the path table before feeding the options
Tercio@23 1839 --as container is optional as well it may contain the first element of the path
Tercio@23 1840 if type(container) == "string" then
Tercio@23 1841 tinsert(path, container)
Tercio@23 1842 container = nil
Tercio@23 1843 end
Tercio@23 1844 for n = 1, select("#",...) do
Tercio@23 1845 tinsert(path, (select(n, ...)))
Tercio@23 1846 end
Tercio@23 1847
Tercio@23 1848 local option = options
Tercio@23 1849 if type(container) == "table" and container.type == "BlizOptionsGroup" and #path > 0 then
Tercio@23 1850 for i = 1, #path do
Tercio@23 1851 option = options.args[path[i]]
Tercio@23 1852 end
Tercio@23 1853 name = format("%s - %s", name, GetOptionsMemberValue("name", option, options, path, appName))
Tercio@23 1854 end
Tercio@23 1855
Tercio@23 1856 --if a container is given feed into that
Tercio@23 1857 if container then
Tercio@23 1858 f = container
Tercio@23 1859 f:ReleaseChildren()
Tercio@23 1860 f:SetUserData("appName", appName)
Tercio@23 1861 f:SetUserData("iscustom", true)
Tercio@23 1862 if #path > 0 then
Tercio@23 1863 f:SetUserData("basepath", copy(path))
Tercio@23 1864 end
Tercio@23 1865 local status = AceConfigDialog:GetStatusTable(appName)
Tercio@23 1866 if not status.width then
Tercio@23 1867 status.width = 700
Tercio@23 1868 end
Tercio@23 1869 if not status.height then
Tercio@23 1870 status.height = 500
Tercio@23 1871 end
Tercio@23 1872 if f.SetStatusTable then
Tercio@23 1873 f:SetStatusTable(status)
Tercio@23 1874 end
Tercio@23 1875 if f.SetTitle then
Tercio@23 1876 f:SetTitle(name or "")
Tercio@23 1877 end
Tercio@23 1878 else
Tercio@23 1879 if not self.OpenFrames[appName] then
Tercio@23 1880 f = gui:Create("Frame")
Tercio@23 1881 self.OpenFrames[appName] = f
Tercio@23 1882 else
Tercio@23 1883 f = self.OpenFrames[appName]
Tercio@23 1884 end
Tercio@23 1885 f:ReleaseChildren()
Tercio@23 1886 f:SetCallback("OnClose", FrameOnClose)
Tercio@23 1887 f:SetUserData("appName", appName)
Tercio@23 1888 if #path > 0 then
Tercio@23 1889 f:SetUserData("basepath", copy(path))
Tercio@23 1890 end
Tercio@23 1891 f:SetTitle(name or "")
Tercio@23 1892 local status = AceConfigDialog:GetStatusTable(appName)
Tercio@23 1893 f:SetStatusTable(status)
Tercio@23 1894 end
Tercio@23 1895
Tercio@23 1896 self:FeedGroup(appName,options,f,f,path,true)
Tercio@23 1897 if f.Show then
Tercio@23 1898 f:Show()
Tercio@23 1899 end
Tercio@23 1900 del(path)
Tercio@23 1901
Tercio@23 1902 if AceConfigDialog.frame.closeAll then
Tercio@23 1903 -- close all is set, but thats not good, since we're just opening here, so force it
Tercio@23 1904 AceConfigDialog.frame.closeAllOverride[appName] = true
Tercio@23 1905 end
Tercio@23 1906 end
Tercio@23 1907
Tercio@23 1908 -- convert pre-39 BlizOptions structure to the new format
Tercio@23 1909 if oldminor and oldminor < 39 and AceConfigDialog.BlizOptions then
Tercio@23 1910 local old = AceConfigDialog.BlizOptions
Tercio@23 1911 local new = {}
Tercio@23 1912 for key, widget in pairs(old) do
Tercio@23 1913 local appName = widget:GetUserData("appName")
Tercio@23 1914 if not new[appName] then new[appName] = {} end
Tercio@23 1915 new[appName][key] = widget
Tercio@23 1916 end
Tercio@23 1917 AceConfigDialog.BlizOptions = new
Tercio@23 1918 else
Tercio@23 1919 AceConfigDialog.BlizOptions = AceConfigDialog.BlizOptions or {}
Tercio@23 1920 end
Tercio@23 1921
Tercio@23 1922 local function FeedToBlizPanel(widget, event)
Tercio@23 1923 local path = widget:GetUserData("path")
Tercio@23 1924 AceConfigDialog:Open(widget:GetUserData("appName"), widget, unpack(path or emptyTbl))
Tercio@23 1925 end
Tercio@23 1926
Tercio@23 1927 local function ClearBlizPanel(widget, event)
Tercio@23 1928 local appName = widget:GetUserData("appName")
Tercio@23 1929 AceConfigDialog.frame.closing[appName] = true
Tercio@23 1930 AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate)
Tercio@23 1931 end
Tercio@23 1932
Tercio@23 1933 --- Add an option table into the Blizzard Interface Options panel.
Tercio@23 1934 -- You can optionally supply a descriptive name to use and a parent frame to use,
Tercio@23 1935 -- as well as a path in the options table.\\
Tercio@23 1936 -- If no name is specified, the appName will be used instead.
Tercio@23 1937 --
Tercio@23 1938 -- If you specify a proper `parent` (by name), the interface options will generate a
Tercio@23 1939 -- tree layout. Note that only one level of children is supported, so the parent always
Tercio@23 1940 -- has to be a head-level note.
Tercio@23 1941 --
Tercio@23 1942 -- This function returns a reference to the container frame registered with the Interface
Tercio@23 1943 -- Options. You can use this reference to open the options with the API function
Tercio@23 1944 -- `InterfaceOptionsFrame_OpenToCategory`.
Tercio@23 1945 -- @param appName The application name as given to `:RegisterOptionsTable()`
Tercio@23 1946 -- @param name A descriptive name to display in the options tree (defaults to appName)
Tercio@23 1947 -- @param parent The parent to use in the interface options tree.
Tercio@23 1948 -- @param ... The path in the options table to feed into the interface options panel.
Tercio@23 1949 -- @return The reference to the frame registered into the Interface Options.
Tercio@23 1950 function AceConfigDialog:AddToBlizOptions(appName, name, parent, ...)
Tercio@23 1951 local BlizOptions = AceConfigDialog.BlizOptions
Tercio@23 1952
Tercio@23 1953 local key = appName
Tercio@23 1954 for n = 1, select("#", ...) do
Tercio@23 1955 key = key.."\001"..select(n, ...)
Tercio@23 1956 end
Tercio@23 1957
Tercio@23 1958 if not BlizOptions[appName] then
Tercio@23 1959 BlizOptions[appName] = {}
Tercio@23 1960 end
Tercio@23 1961
Tercio@23 1962 if not BlizOptions[appName][key] then
Tercio@23 1963 local group = gui:Create("BlizOptionsGroup")
Tercio@23 1964 BlizOptions[appName][key] = group
Tercio@23 1965 group:SetName(name or appName, parent)
Tercio@23 1966
Tercio@23 1967 group:SetTitle(name or appName)
Tercio@23 1968 group:SetUserData("appName", appName)
Tercio@23 1969 if select("#", ...) > 0 then
Tercio@23 1970 local path = {}
Tercio@23 1971 for n = 1, select("#",...) do
Tercio@23 1972 tinsert(path, (select(n, ...)))
Tercio@23 1973 end
Tercio@23 1974 group:SetUserData("path", path)
Tercio@23 1975 end
Tercio@23 1976 group:SetCallback("OnShow", FeedToBlizPanel)
Tercio@23 1977 group:SetCallback("OnHide", ClearBlizPanel)
Tercio@23 1978 InterfaceOptions_AddCategory(group.frame)
Tercio@23 1979 return group.frame
Tercio@23 1980 else
Tercio@23 1981 error(("%s has already been added to the Blizzard Options Window with the given path"):format(appName), 2)
Tercio@23 1982 end
Tercio@23 1983 end