annotate Libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua @ 0:c6ff7ba0e8f6

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