/trunk/TipTop/libs/AceConfig-3.0/AceConfigDialog-3.0
--- AceConfigDialog-3.0 generates AceGUI-3.0 based windows based on option tables. |
-- @class file |
-- @name AceConfigDialog-3.0 |
-- @release $Id: AceConfigDialog-3.0.lua 1169 2018-02-27 16:18:28Z nevcairiel $ |
-- @release $Id: AceConfigDialog-3.0.lua 1232 2020-04-14 22:21:22Z nevcairiel $ |
local LibStub = LibStub |
local gui = LibStub("AceGUI-3.0") |
local reg = LibStub("AceConfigRegistry-3.0") |
local MAJOR, MINOR = "AceConfigDialog-3.0", 66 |
local MAJOR, MINOR = "AceConfigDialog-3.0", 79 |
local AceConfigDialog, oldminor = LibStub:NewLibrary(MAJOR, MINOR) |
if not AceConfigDialog then return end |
AceConfigDialog.OpenFrames = AceConfigDialog.OpenFrames or {} |
AceConfigDialog.Status = AceConfigDialog.Status or {} |
AceConfigDialog.frame = AceConfigDialog.frame or CreateFrame("Frame") |
AceConfigDialog.tooltip = AceConfigDialog.tooltip or CreateFrame("GameTooltip", "AceConfigDialogTooltip", UIParent, "GameTooltipTemplate") |
AceConfigDialog.frame.apps = AceConfigDialog.frame.apps or {} |
AceConfigDialog.frame.closing = AceConfigDialog.frame.closing or {} |
AceConfigDialog.frame.closeAllOverride = AceConfigDialog.frame.closeAllOverride or {} |
-- Lua APIs |
local tconcat, tinsert, tsort, tremove, tsort = table.concat, table.insert, table.sort, table.remove, table.sort |
local tinsert, tsort, tremove = table.insert, table.sort, table.remove |
local strmatch, format = string.match, string.format |
local assert, loadstring, error = assert, loadstring, error |
local error = error |
local pairs, next, select, type, unpack, wipe, ipairs = pairs, next, select, type, unpack, wipe, ipairs |
local rawset, tostring, tonumber = rawset, tostring, tonumber |
local tostring, tonumber = tostring, tonumber |
local math_min, math_max, math_floor = math.min, math.max, math.floor |
-- Global vars/functions that we don't upvalue since they might get hooked, or upgraded |
-- List them here for Mikk's FindGlobals script |
-- GLOBALS: NORMAL_FONT_COLOR, GameTooltip, StaticPopupDialogs, ACCEPT, CANCEL, StaticPopup_Show |
-- GLOBALS: NORMAL_FONT_COLOR, ACCEPT, CANCEL |
-- GLOBALS: PlaySound, GameFontHighlight, GameFontHighlightSmall, GameFontHighlightLarge |
-- GLOBALS: CloseSpecialWindows, InterfaceOptions_AddCategory, geterrorhandler |
return geterrorhandler()(err) |
end |
local function CreateDispatcher(argCount) |
local code = [[ |
local xpcall, eh = ... |
local method, ARGS |
local function call() return method(ARGS) end |
local function dispatch(func, ...) |
method = func |
if not method then return end |
ARGS = ... |
return xpcall(call, eh) |
end |
return dispatch |
]] |
local ARGS = {} |
for i = 1, argCount do ARGS[i] = "arg"..i end |
code = code:gsub("ARGS", tconcat(ARGS, ", ")) |
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler) |
end |
local Dispatchers = setmetatable({}, {__index=function(self, argCount) |
local dispatcher = CreateDispatcher(argCount) |
rawset(self, argCount, dispatcher) |
return dispatcher |
end}) |
Dispatchers[0] = function(func) |
return xpcall(func, errorhandler) |
end |
local function safecall(func, ...) |
return Dispatchers[select("#", ...)](func, ...) |
if func then |
return xpcall(func, errorhandler, ...) |
end |
end |
local width_multiplier = 170 |
--[[ |
Group Types |
Tree - All Descendant Groups will all become nodes on the tree, direct child options will appear above the tree |
- Descendant Groups with inline=true and thier children will not become nodes |
- Descendant Groups with inline=true and thier children will not become nodes |
Tab - Direct Child Groups will become tabs, direct child options will appear above the tab control |
- Grandchild groups will default to inline unless specified otherwise |
- Grandchild groups will default to inline unless specified otherwise |
Select- Same as Tab but with entries in a dropdown rather than tabs |
Inline Groups |
- Will not become nodes of a select group, they will be effectivly part of thier parent group seperated by a border |
- If declared on a direct child of a root node of a select group, they will appear above the group container control |
- When a group is displayed inline, all descendants will also be inline members of the group |
- Will not become nodes of a select group, they will be effectivly part of thier parent group seperated by a border |
- If declared on a direct child of a root node of a select group, they will appear above the group container control |
- When a group is displayed inline, all descendants will also be inline members of the group |
]] |
local function GetOptionsMemberValue(membername, option, options, path, appName, ...) |
--get definition for the member |
local inherits = isInherited[membername] |
--get the member of the option, traversing the tree if it can be inherited |
local member |
if inherits then |
local group = options |
if group[membername] ~= nil then |
else |
member = option[membername] |
end |
--check if we need to call a functon, or if we have a literal value |
if ( not allIsLiteral[membername] ) and ( type(member) == "function" or ((not stringIsLiteral[membername]) and type(member) == "string") ) then |
--We have a function to call |
local handler |
local group = options |
handler = group.handler or handler |
for i = 1, #path do |
group = GetSubOption(group, path[i]) |
info[i] = path[i] |
handler = group.handler or handler |
end |
info.options = options |
info.appName = appName |
info[0] = appName |
info.type = option.type |
info.uiType = "dialog" |
info.uiName = MAJOR |
local a, b, c ,d |
local a, b, c ,d |
--using 4 returns for the get of a color type, increase if a type needs more |
if type(member) == "function" then |
--Call the function |
return a,b,c,d |
else |
--The value isnt a function to call, return it |
return member |
end |
return member |
end |
end |
--[[calls an options function that could be inherited, method name or function ref |
return NameA:upper() < NameB:upper() |
end |
if OrderA < 0 then |
if OrderB > 0 then |
if OrderB >= 0 then |
return false |
end |
else |
local function BuildSortedOptionsTable(group, keySort, opts, options, path, appName) |
tempOrders = new() |
tempNames = new() |
if group.plugins then |
for plugin, t in pairs(group.plugins) do |
for k, v in pairs(t) do |
end |
end |
end |
for k, v in pairs(group.args) do |
if not opts[k] then |
tinsert(keySort, k) |
end |
local function CleanUserData(widget, event) |
local user = widget:GetUserDataTable() |
if user.path then |
-- - Gets a status table for the given appname and options path. |
-- @param appName The application name as given to `:RegisterOptionsTable()` |
-- @param path The path to the options (a table with all group keys) |
-- @return |
-- @return |
function AceConfigDialog:GetStatusTable(appName, path) |
local status = self.Status |
function AceConfigDialog:SelectGroup(appName, ...) |
local path = new() |
local app = reg:GetOptionsTable(appName) |
if not app then |
error(("%s isn't registed with AceConfigRegistry, unable to open config"):format(appName), 2) |
status.groups = {} |
end |
status = status.groups |
local treevalue |
local treestatus |
local treevalue |
local treestatus |
for n = 1, select("#",...) do |
local key = select(n, ...) |
--the selected group will be overwritten if a child is the final target but still needs to be open |
treestatus.selected = treevalue |
treestatus.groups[treevalue] = true |
end |
--move to the next group in the path |
group = GetSubOption(group, key) |
if not group then |
if not group then |
break |
end |
tinsert(path, key) |
end |
status = status.groups |
end |
del(path) |
reg:NotifyChange(appName) |
end |
end |
local function OptionOnMouseOver(widget, event) |
--show a tooltip/set the status bar to the desc text |
local options = user.options |
local path = user.path |
local appName = user.appName |
local tooltip = AceConfigDialog.tooltip |
GameTooltip:SetOwner(widget.frame, "ANCHOR_TOPRIGHT") |
tooltip:SetOwner(widget.frame, "ANCHOR_TOPRIGHT") |
local name = GetOptionsMemberValue("name", opt, options, path, appName) |
local desc = GetOptionsMemberValue("desc", opt, options, path, appName) |
local usage = GetOptionsMemberValue("usage", opt, options, path, appName) |
local descStyle = opt.descStyle |
if descStyle and descStyle ~= "tooltip" then return end |
GameTooltip:SetText(name, 1, .82, 0, true) |
tooltip:SetText(name, 1, .82, 0, true) |
if opt.type == "multiselect" then |
GameTooltip:AddLine(user.text, 0.5, 0.5, 0.8, true) |
end |
tooltip:AddLine(user.text, 0.5, 0.5, 0.8, true) |
end |
if type(desc) == "string" then |
GameTooltip:AddLine(desc, 1, 1, 1, true) |
tooltip:AddLine(desc, 1, 1, 1, true) |
end |
if type(usage) == "string" then |
GameTooltip:AddLine("Usage: "..usage, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, true) |
tooltip:AddLine("Usage: "..usage, NORMAL_FONT_COLOR.r, NORMAL_FONT_COLOR.g, NORMAL_FONT_COLOR.b, true) |
end |
GameTooltip:Show() |
tooltip:Show() |
end |
local function OptionOnMouseLeave(widget, event) |
GameTooltip:Hide() |
AceConfigDialog.tooltip:Hide() |
end |
local function GetFuncName(option) |
return "set" |
end |
end |
do |
local frame = AceConfigDialog.popup |
if not frame then |
frame = CreateFrame("Frame", nil, UIParent) |
AceConfigDialog.popup = frame |
frame:Hide() |
frame:SetPoint("CENTER", UIParent, "CENTER") |
frame:SetSize(320, 72) |
frame:SetFrameStrata("TOOLTIP") |
frame:SetScript("OnKeyDown", function(self, key) |
if key == "ESCAPE" then |
self:SetPropagateKeyboardInput(false) |
if self.cancel:IsShown() then |
self.cancel:Click() |
else -- Showing a validation error |
self:Hide() |
end |
else |
self:SetPropagateKeyboardInput(true) |
end |
end) |
if WOW_PROJECT_ID == WOW_PROJECT_CLASSIC then |
frame:SetBackdrop({ |
bgFile = [[Interface\DialogFrame\UI-DialogBox-Background-Dark]], |
edgeFile = [[Interface\DialogFrame\UI-DialogBox-Border]], |
tile = true, |
tileSize = 32, |
edgeSize = 32, |
insets = { left = 11, right = 11, top = 11, bottom = 11 }, |
}) |
else |
local border = CreateFrame("Frame", nil, frame, "DialogBorderDarkTemplate") |
border:SetAllPoints(frame) |
end |
local text = frame:CreateFontString(nil, "ARTWORK", "GameFontHighlight") |
text:SetSize(290, 0) |
text:SetPoint("TOP", 0, -16) |
frame.text = text |
local function newButton(text) |
local button = CreateFrame("Button", nil, frame) |
button:SetSize(128, 21) |
button:SetNormalFontObject(GameFontNormal) |
button:SetHighlightFontObject(GameFontHighlight) |
button:SetNormalTexture(130763) -- "Interface\\Buttons\\UI-DialogBox-Button-Up" |
button:GetNormalTexture():SetTexCoord(0.0, 1.0, 0.0, 0.71875) |
button:SetPushedTexture(130761) -- "Interface\\Buttons\\UI-DialogBox-Button-Down" |
button:GetPushedTexture():SetTexCoord(0.0, 1.0, 0.0, 0.71875) |
button:SetHighlightTexture(130762) -- "Interface\\Buttons\\UI-DialogBox-Button-Highlight" |
button:GetHighlightTexture():SetTexCoord(0.0, 1.0, 0.0, 0.71875) |
button:SetText(text) |
return button |
end |
local accept = newButton(ACCEPT) |
accept:SetPoint("BOTTOMRIGHT", frame, "BOTTOM", -6, 16) |
frame.accept = accept |
local cancel = newButton(CANCEL) |
cancel:SetPoint("LEFT", accept, "RIGHT", 13, 0) |
frame.cancel = cancel |
end |
end |
local function confirmPopup(appName, rootframe, basepath, info, message, func, ...) |
if not StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"] then |
StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"] = {} |
end |
local t = StaticPopupDialogs["ACECONFIGDIALOG30_CONFIRM_DIALOG"] |
for k in pairs(t) do |
t[k] = nil |
end |
t.text = message |
t.button1 = ACCEPT |
t.button2 = CANCEL |
t.preferredIndex = STATICPOPUP_NUMDIALOGS |
local dialog, oldstrata |
t.OnAccept = function() |
safecall(func, unpack(t)) |
if dialog and oldstrata then |
dialog:SetFrameStrata(oldstrata) |
end |
local frame = AceConfigDialog.popup |
frame:Show() |
frame.text:SetText(message) |
-- From StaticPopup.lua |
-- local height = 32 + text:GetHeight() + 2; |
-- height = height + 6 + accept:GetHeight() |
-- We add 32 + 2 + 6 + 21 (button height) == 61 |
local height = 61 + frame.text:GetHeight() |
frame:SetHeight(height) |
frame.accept:ClearAllPoints() |
frame.accept:SetPoint("BOTTOMRIGHT", frame, "BOTTOM", -6, 16) |
frame.cancel:Show() |
local t = {...} |
local tCount = select("#", ...) |
frame.accept:SetScript("OnClick", function(self) |
safecall(func, unpack(t, 1, tCount)) -- Manually set count as unpack() stops on nil (bug with #table) |
AceConfigDialog:Open(appName, rootframe, unpack(basepath or emptyTbl)) |
frame:Hide() |
self:SetScript("OnClick", nil) |
frame.cancel:SetScript("OnClick", nil) |
del(info) |
end |
t.OnCancel = function() |
if dialog and oldstrata then |
dialog:SetFrameStrata(oldstrata) |
end |
end) |
frame.cancel:SetScript("OnClick", function(self) |
AceConfigDialog:Open(appName, rootframe, unpack(basepath or emptyTbl)) |
frame:Hide() |
self:SetScript("OnClick", nil) |
frame.accept:SetScript("OnClick", nil) |
del(info) |
end |
for i = 1, select("#", ...) do |
t[i] = select(i, ...) or false |
end |
t.timeout = 0 |
t.whileDead = 1 |
t.hideOnEscape = 1 |
dialog = StaticPopup_Show("ACECONFIGDIALOG30_CONFIRM_DIALOG") |
if dialog then |
oldstrata = dialog:GetFrameStrata() |
dialog:SetFrameStrata("TOOLTIP") |
end |
end) |
end |
local function validationErrorPopup(message) |
if not StaticPopupDialogs["ACECONFIGDIALOG30_VALIDATION_ERROR_DIALOG"] then |
StaticPopupDialogs["ACECONFIGDIALOG30_VALIDATION_ERROR_DIALOG"] = {} |
end |
local t = StaticPopupDialogs["ACECONFIGDIALOG30_VALIDATION_ERROR_DIALOG"] |
t.text = message |
t.button1 = OKAY |
t.preferredIndex = STATICPOPUP_NUMDIALOGS |
local dialog, oldstrata |
t.OnAccept = function() |
if dialog and oldstrata then |
dialog:SetFrameStrata(oldstrata) |
end |
end |
t.timeout = 0 |
t.whileDead = 1 |
t.hideOnEscape = 1 |
local frame = AceConfigDialog.popup |
frame:Show() |
frame.text:SetText(message) |
-- From StaticPopup.lua |
-- local height = 32 + text:GetHeight() + 2; |
-- height = height + 6 + accept:GetHeight() |
-- We add 32 + 2 + 6 + 21 (button height) == 61 |
local height = 61 + frame.text:GetHeight() |
frame:SetHeight(height) |
dialog = StaticPopup_Show("ACECONFIGDIALOG30_VALIDATION_ERROR_DIALOG") |
if dialog then |
oldstrata = dialog:GetFrameStrata() |
dialog:SetFrameStrata("TOOLTIP") |
end |
frame.accept:ClearAllPoints() |
frame.accept:SetPoint("BOTTOM", frame, "BOTTOM", 0, 16) |
frame.cancel:Hide() |
frame.accept:SetScript("OnClick", function() |
frame:Hide() |
end) |
end |
local function ActivateControl(widget, event, ...) |
end |
end |
end |
local success |
if validated and option.type ~= "execute" then |
if type(validate) == "string" then |
if not success then validated = false end |
end |
end |
local rootframe = user.rootframe |
if not validated or type(validated) == "string" then |
if not validated then |
del(info) |
return true |
else |
local confirmText = option.confirmText |
--call confirm func/method |
if type(confirm) == "string" then |
confirmText = confirmText.." - "..desc |
end |
end |
local iscustom = user.rootframe:GetUserData("iscustom") |
local rootframe |
if iscustom then |
rootframe = user.rootframe |
end |
--full refresh of the frame, some controls dont cause this on all events |
if option.type == "color" then |
if event == "OnValueConfirmed" then |
if iscustom then |
AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath)) |
else |
local function MultiControlOnClosed(widget, event, ...) |
local user = widget:GetUserDataTable() |
if user.valuechanged then |
if user.valuechanged and not widget:IsReleasing() then |
local iscustom = user.rootframe:GetUserData("iscustom") |
local basepath = user.rootframe:GetUserData("basepath") or emptyTbl |
if iscustom then |
control:SetCallback("OnEnter", OptionOnMouseOver) |
end |
local function CreateControl(userControlType, fallbackControlType) |
local control |
if userControlType then |
control = gui:Create(userControlType) |
if not control then |
geterrorhandler()(("Invalid Custom Control Type - %s"):format(tostring(userControlType))) |
end |
end |
if not control then |
control = gui:Create(fallbackControlType) |
end |
return control |
end |
local function sortTblAsStrings(x,y) |
return tostring(x) < tostring(y) -- Support numbers as keys |
end |
--[[ |
options - root of the options table being fed |
container - widget that controls will be placed in |
else |
GroupContainer = gui:Create("SimpleGroup") |
end |
GroupContainer.width = "fill" |
GroupContainer:SetLayout("flow") |
container:AddChild(GroupContainer) |
else |
--Control to feed |
local control |
local name = GetOptionsMemberValue("name", v, options, path, appName) |
if v.type == "execute" then |
local imageCoords = GetOptionsMemberValue("imageCoords",v, options, path, appName) |
local image, width, height = GetOptionsMemberValue("image",v, options, path, appName) |
if type(image) == "string" or type(image) == "number" then |
control = gui:Create("Icon") |
local iconControl = type(image) == "string" or type(image) == "number" |
control = CreateControl(v.dialogControl or v.control, iconControl and "Icon" or "Button") |
if iconControl then |
if not width then |
width = GetOptionsMemberValue("imageWidth",v, options, path, appName) |
end |
control:SetImageSize(width, height) |
control:SetLabel(name) |
else |
control = gui:Create("Button") |
control:SetText(name) |
end |
control:SetCallback("OnClick",ActivateControl) |
elseif v.type == "input" then |
local controlType = v.dialogControl or v.control or (v.multiline and "MultiLineEditBox") or "EditBox" |
control = gui:Create(controlType) |
if not control then |
geterrorhandler()(("Invalid Custom Control Type - %s"):format(tostring(controlType))) |
control = gui:Create(v.multiline and "MultiLineEditBox" or "EditBox") |
end |
control = CreateControl(v.dialogControl or v.control, v.multiline and "MultiLineEditBox" or "EditBox") |
if v.multiline and control.SetNumLines then |
control:SetNumLines(tonumber(v.multiline) or 4) |
end |
control:SetText(text) |
elseif v.type == "toggle" then |
control = gui:Create("CheckBox") |
control = CreateControl(v.dialogControl or v.control, "CheckBox") |
control:SetLabel(name) |
control:SetTriState(v.tristate) |
local value = GetOptionsMemberValue("get",v, options, path, appName) |
control:SetValue(value) |
control:SetCallback("OnValueChanged",ActivateControl) |
if v.descStyle == "inline" then |
local desc = GetOptionsMemberValue("desc", v, options, path, appName) |
control:SetDescription(desc) |
end |
local image = GetOptionsMemberValue("image", v, options, path, appName) |
local imageCoords = GetOptionsMemberValue("imageCoords", v, options, path, appName) |
if type(image) == "string" or type(image) == "number" then |
if type(imageCoords) == "table" then |
control:SetImage(image, unpack(imageCoords)) |
end |
end |
elseif v.type == "range" then |
control = gui:Create("Slider") |
control = CreateControl(v.dialogControl or v.control, "Slider") |
control:SetLabel(name) |
control:SetSliderValues(v.softMin or v.min or 0, v.softMax or v.max or 100, v.bigStep or v.step or 0) |
control:SetIsPercent(v.isPercent) |
elseif v.type == "select" then |
local values = GetOptionsMemberValue("values", v, options, path, appName) |
local sorting = GetOptionsMemberValue("sorting", v, options, path, appName) |
if v.style == "radio" then |
local disabled = CheckOptionDisabled(v, options, path, appName) |
local width = GetOptionsMemberValue("width",v,options,path,appName) |
control:PauseLayout() |
local optionValue = GetOptionsMemberValue("get",v, options, path, appName) |
local t = {} |
for value, text in pairs(values) do |
t[#t+1]=value |
if not sorting then |
sorting = {} |
for value, text in pairs(values) do |
sorting[#sorting+1]=value |
end |
tsort(sorting, sortTblAsStrings) |
end |
tsort(t) |
for k, value in ipairs(t) do |
for k, value in ipairs(sorting) do |
local text = values[value] |
local radio = gui:Create("CheckBox") |
radio:SetLabel(text) |
control:ResumeLayout() |
control:DoLayout() |
else |
local controlType = v.dialogControl or v.control or "Dropdown" |
control = gui:Create(controlType) |
if not control then |
geterrorhandler()(("Invalid Custom Control Type - %s"):format(tostring(controlType))) |
control = gui:Create("Dropdown") |
end |
control = CreateControl(v.dialogControl or v.control, "Dropdown") |
local itemType = v.itemControl |
if itemType and not gui:GetWidgetVersion(itemType) then |
geterrorhandler()(("Invalid Custom Item Type - %s"):format(tostring(itemType))) |
itemType = nil |
end |
control:SetLabel(name) |
control:SetList(values, nil, itemType) |
control:SetList(values, sorting, itemType) |
local value = GetOptionsMemberValue("get",v, options, path, appName) |
if not values[value] then |
value = nil |
elseif v.type == "multiselect" then |
local values = GetOptionsMemberValue("values", v, options, path, appName) |
local disabled = CheckOptionDisabled(v, options, path, appName) |
local controlType = v.dialogControl or v.control |
local valuesort = new() |
if values then |
for value, text in pairs(values) do |
end |
end |
tsort(valuesort) |
local controlType = v.dialogControl or v.control |
if controlType then |
control = gui:Create(controlType) |
if not control then |
control:ResumeLayout() |
control:DoLayout() |
end |
del(valuesort) |
elseif v.type == "color" then |
control = gui:Create("ColorPicker") |
control = CreateControl(v.dialogControl or v.control, "ColorPicker") |
control:SetLabel(name) |
control:SetHasAlpha(GetOptionsMemberValue("hasAlpha",v, options, path, appName)) |
control:SetColor(GetOptionsMemberValue("get",v, options, path, appName)) |
control:SetCallback("OnValueConfirmed",ActivateControl) |
elseif v.type == "keybinding" then |
control = gui:Create("Keybinding") |
control = CreateControl(v.dialogControl or v.control, "Keybinding") |
control:SetLabel(name) |
control:SetKey(GetOptionsMemberValue("get",v, options, path, appName)) |
control:SetCallback("OnKeyChanged",ActivateControl) |
elseif v.type == "header" then |
control = gui:Create("Heading") |
control = CreateControl(v.dialogControl or v.control, "Heading") |
control:SetText(name) |
control.width = "fill" |
elseif v.type == "description" then |
control = gui:Create("Label") |
control = CreateControl(v.dialogControl or v.control, "Label") |
control:SetText(name) |
local fontSize = GetOptionsMemberValue("fontSize",v, options, path, appName) |
if fontSize == "medium" then |
control:SetFontObject(GameFontHighlight) |
else -- small or invalid |
control:SetFontObject(GameFontHighlightSmall) |
end |
local imageCoords = GetOptionsMemberValue("imageCoords",v, options, path, appName) |
local image, width, height = GetOptionsMemberValue("image",v, options, path, appName) |
if type(image) == "string" or type(image) == "number" then |
if not width then |
width = GetOptionsMemberValue("imageWidth",v, options, path, appName) |
InjectInfo(control, options, v, path, rootframe, appName) |
container:AddChild(control) |
end |
end |
end |
tremove(path) |
local option = user.option |
local path = user.path |
local appName = user.appName |
local tooltip = AceConfigDialog.tooltip |
local feedpath = new() |
for i = 1, #path do |
feedpath[i] = path[i] |
local name = GetOptionsMemberValue("name", group, options, feedpath, appName) |
local desc = GetOptionsMemberValue("desc", group, options, feedpath, appName) |
GameTooltip:SetOwner(button, "ANCHOR_NONE") |
tooltip:SetOwner(button, "ANCHOR_NONE") |
tooltip:ClearAllPoints() |
if widget.type == "TabGroup" then |
GameTooltip:SetPoint("BOTTOM",button,"TOP") |
tooltip:SetPoint("BOTTOM",button,"TOP") |
else |
GameTooltip:SetPoint("LEFT",button,"RIGHT") |
tooltip:SetPoint("LEFT",button,"RIGHT") |
end |
GameTooltip:SetText(name, 1, .82, 0, true) |
tooltip:SetText(name, 1, .82, 0, true) |
if type(desc) == "string" then |
GameTooltip:AddLine(desc, 1, 1, 1, true) |
tooltip:AddLine(desc, 1, 1, 1, true) |
end |
GameTooltip:Show() |
tooltip:Show() |
end |
local function TreeOnButtonLeave(widget, event, value, button) |
GameTooltip:Hide() |
AceConfigDialog.tooltip:Hide() |
end |
local function GroupExists(appName, options, path, uniquevalue) |
if not uniquevalue then return false end |
local feedpath = new() |
local temppath = new() |
for i = 1, #path do |
feedpath[i] = path[i] |
end |
BuildPath(feedpath, ("\001"):split(uniquevalue)) |
local group = options |
for i = 1, #feedpath do |
local v = feedpath[i] |
temppath[i] = v |
group = GetSubOption(group, v) |
if not group or group.type ~= "group" or CheckOptionHidden(group, options, temppath, appName) then |
if not group or group.type ~= "group" or CheckOptionHidden(group, options, temppath, appName) then |
del(feedpath) |
del(temppath) |
return false |
return false |
end |
end |
del(feedpath) |
end |
BuildPath(feedpath, ("\001"):split(uniquevalue)) |
local group = options |
for i = 1, #feedpath do |
group = GetSubOption(group, feedpath[i]) |
end |
widget:ReleaseChildren() |
AceConfigDialog:FeedGroup(user.appName,options,widget,rootframe,feedpath) |
tab:SetCallback("OnGroupSelected", GroupSelected) |
tab:SetCallback("OnTabEnter", TreeOnButtonEnter) |
tab:SetCallback("OnTabLeave", TreeOnButtonLeave) |
local status = AceConfigDialog:GetStatusTable(appName, path) |
if not status.groups then |
status.groups = {} |
break |
end |
end |
container:AddChild(tab) |
elseif grouptype == "select" then |
if firstgroup then |
select:SetGroup((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or firstgroup) |
end |
select.width = "fill" |
select.height = "fill" |
local tree = gui:Create("TreeGroup") |
InjectInfo(tree, options, group, path, rootframe, appName) |
tree:EnableButtonTooltips(false) |
tree.width = "fill" |
tree.height = "fill" |
tree:SetCallback("OnGroupSelected", GroupSelected) |
tree:SetCallback("OnButtonEnter", TreeOnButtonEnter) |
tree:SetCallback("OnButtonLeave", TreeOnButtonLeave) |
local status = AceConfigDialog:GetStatusTable(appName, path) |
if not status.groups then |
status.groups = {} |
end |
this.closing[appName] = nil |
end |
if this.closeAll then |
for k, v in pairs(AceConfigDialog.OpenFrames) do |
if not this.closeAllOverride[k] then |
this.closeAll = nil |
wipe(this.closeAllOverride) |
end |
for appName in pairs(this.apps) do |
if AceConfigDialog.OpenFrames[appName] then |
local user = AceConfigDialog.OpenFrames[appName]:GetUserDataTable() |
local options = app("dialog", MAJOR) |
local f |
local path = new() |
local name = GetOptionsMemberValue("name", options, options, path, appName) |
--If an optional path is specified add it to the path table before feeding the options |
--as container is optional as well it may contain the first element of the path |
if type(container) == "string" then |
for n = 1, select("#",...) do |
tinsert(path, (select(n, ...))) |
end |
local option = options |
if type(container) == "table" and container.type == "BlizOptionsGroup" and #path > 0 then |
for i = 1, #path do |
end |
name = format("%s - %s", name, GetOptionsMemberValue("name", option, options, path, appName)) |
end |
--if a container is given feed into that |
if container then |
f = container |
-- @param name A descriptive name to display in the options tree (defaults to appName) |
-- @param parent The parent to use in the interface options tree. |
-- @param ... The path in the options table to feed into the interface options panel. |
-- @return The reference to the frame registered into the Interface Options. |
-- @return The reference to the frame registered into the Interface Options. |
function AceConfigDialog:AddToBlizOptions(appName, name, parent, ...) |
local BlizOptions = AceConfigDialog.BlizOptions |
local key = appName |
for n = 1, select("#", ...) do |
key = key.."\001"..select(n, ...) |
end |
if not BlizOptions[appName] then |
BlizOptions[appName] = {} |
end |
if not BlizOptions[appName][key] then |
local group = gui:Create("BlizOptionsGroup") |
BlizOptions[appName][key] = group |