/trunk/MyThreat/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 796 2009-04-07 15:48:54Z nevcairiel $ |
-- @release $Id: AceConfigDialog-3.0.lua 895 2009-12-06 16:28:55Z nevcairiel $ |
local LibStub = LibStub |
local MAJOR, MINOR = "AceConfigDialog-3.0", 34 |
local AceConfigDialog = LibStub:NewLibrary(MAJOR, MINOR) |
local MAJOR, MINOR = "AceConfigDialog-3.0", 41 |
local AceConfigDialog, oldminor = LibStub:NewLibrary(MAJOR, MINOR) |
if not AceConfigDialog then return end |
local gui = LibStub("AceGUI-3.0") |
local reg = LibStub("AceConfigRegistry-3.0") |
local select = select |
local pairs = pairs |
local type = type |
local assert = assert |
local tinsert = tinsert |
local tremove = tremove |
local error = error |
local table = table |
local unpack = unpack |
local string = string |
local next = next |
local math = math |
local _ |
-- Lua APIs |
local tconcat, tinsert, tsort, tremove = table.concat, table.insert, table.sort, table.remove |
local strmatch, format = string.match, string.format |
local assert, loadstring, error = assert, loadstring, error |
local pairs, next, select, type, unpack = pairs, next, select, type, unpack |
local rawset, tostring = rawset, tostring |
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: PlaySound, GameFontHighlight, GameFontHighlightSmall, GameFontHighlightLarge |
-- GLOBALS: CloseSpecialWindows, InterfaceOptions_AddCategory, geterrorhandler |
local emptyTbl = {} |
--[[ |
xpcall safecall implementation |
]] |
local ARGS = {} |
for i = 1, argCount do ARGS[i] = "arg"..i end |
code = code:gsub("ARGS", table.concat(ARGS, ", ")) |
code = code:gsub("ARGS", tconcat(ARGS, ", ")) |
return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler) |
end |
--Is Never a function or method |
local allIsLiteral = { |
type = true, |
descStyle = true, |
imageWidth = true, |
imageHeight = true, |
} |
if handler and handler[member] then |
a,b,c,d = handler[member](handler, info, ...) |
else |
error(string.format("Method %s doesn't exist in handler for type %s", member, membername)) |
error(format("Method %s doesn't exist in handler for type %s", member, membername)) |
end |
end |
del(info) |
end |
end |
table.sort(keySort, compareOptions) |
tsort(keySort, compareOptions) |
del(tempOrders) |
del(tempNames) |
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, 1) |
if opt.type == 'multiselect' then |
if dialog and oldstrata then |
dialog:SetFrameStrata(oldstrata) |
end |
AceConfigDialog:Open(appName, rootframe, basepath and unpack(basepath)) |
AceConfigDialog:Open(appName, rootframe, unpack(basepath or emptyTbl)) |
del(info) |
end |
t.OnCancel = function() |
if dialog and oldstrata then |
dialog:SetFrameStrata(oldstrata) |
end |
AceConfigDialog:Open(appName, rootframe, basepath and unpack(basepath)) |
AceConfigDialog:Open(appName, rootframe, unpack(basepath or emptyTbl)) |
del(info) |
end |
for i = 1, select('#', ...) do |
success, validated = safecall(handler[validate], handler, info, ...) |
if not success then validated = false end |
else |
error(string.format("Method %s doesn't exist in handler for type execute", validate)) |
error(format("Method %s doesn't exist in handler for type execute", validate)) |
end |
elseif type(validate) == "function" then |
success, validated = safecall(validate, info, ...) |
--validate function returned a message to display |
if rootframe.SetStatusText then |
rootframe:SetStatusText(validated) |
else |
-- TODO: do something else. |
end |
PlaySound("igPlayerInviteDecline") |
del(info) |
rootframe:SetStatusText(name..": Invalid Value") |
end |
end |
else |
-- TODO: do something else |
end |
PlaySound("igPlayerInviteDecline") |
del(info) |
confirm = false |
end |
else |
error(string.format("Method %s doesn't exist in handler for type confirm", confirm)) |
error(format("Method %s doesn't exist in handler for type confirm", confirm)) |
end |
elseif type(confirm) == "function" then |
success, confirm = safecall(confirm, info, ...) |
if handler and handler[func] then |
confirmPopup(user.appName, rootframe, basepath, info, confirmText, handler[func], handler, info, ...) |
else |
error(string.format("Method %s doesn't exist in handler for type func", func)) |
error(format("Method %s doesn't exist in handler for type func", func)) |
end |
elseif type(func) == "function" then |
confirmPopup(user.appName, rootframe, basepath, info, confirmText, func, info, ...) |
if handler and handler[func] then |
safecall(handler[func],handler, info, ...) |
else |
error(string.format("Method %s doesn't exist in handler for type func", func)) |
error(format("Method %s doesn't exist in handler for type func", func)) |
end |
elseif type(func) == "function" then |
safecall(func,info, ...) |
local iscustom = user.rootframe:GetUserData('iscustom') |
local basepath = user.rootframe:GetUserData('basepath') |
local basepath = user.rootframe:GetUserData('basepath') or emptyTbl |
--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, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath)) |
else |
AceConfigDialog:Open(user.appName, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, unpack(basepath)) |
end |
end |
elseif option.type == "range" then |
if event == "OnMouseUp" then |
if iscustom then |
AceConfigDialog:Open(user.appName, user.rootframe, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath)) |
else |
AceConfigDialog:Open(user.appName, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, unpack(basepath)) |
end |
end |
--multiselects don't cause a refresh on 'OnValueChanged' only 'OnClosed' |
user.valuechanged = true |
else |
if iscustom then |
AceConfigDialog:Open(user.appName, user.rootframe, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath)) |
else |
AceConfigDialog:Open(user.appName, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, unpack(basepath)) |
end |
end |
local option = widget:GetUserData('option') |
local min, max, step = option.min or 0, option.max or 100, option.step |
if step then |
value = math.floor((value - min) / step + 0.5) * step + min |
value = math_floor((value - min) / step + 0.5) * step + min |
else |
value = math.max(math.min(value,max),min) |
value = math_max(math_min(value,max),min) |
end |
ActivateControl(widget,event,value) |
end |
ActivateControl(widget, event, widget:GetUserData('value'), ...) |
local user = widget:GetUserDataTable() |
local iscustom = user.rootframe:GetUserData('iscustom') |
local basepath = user.rootframe:GetUserData('basepath') |
local basepath = user.rootframe:GetUserData('basepath') or emptyTbl |
if iscustom then |
AceConfigDialog:Open(user.appName, user.rootframe, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath)) |
else |
AceConfigDialog:Open(user.appName, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, unpack(basepath)) |
end |
end |
local user = widget:GetUserDataTable() |
if user.valuechanged then |
local iscustom = user.rootframe:GetUserData('iscustom') |
local basepath = user.rootframe:GetUserData('basepath') |
local basepath = user.rootframe:GetUserData('basepath') or emptyTbl |
if iscustom then |
AceConfigDialog:Open(user.appName, user.rootframe, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath)) |
else |
AceConfigDialog:Open(user.appName, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, unpack(basepath)) |
end |
end |
end |
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' then |
if type(imageCoords) == 'table' then |
control:SetImage(image, unpack(imageCoords)) |
else |
control:SetImage(image) |
end |
end |
elseif v.type == "range" then |
control = gui:Create("Slider") |
control:SetLabel(name) |
tinsert(valuesort, value) |
end |
end |
table.sort(valuesort) |
tsort(valuesort) |
if controlType then |
control = gui:Create(controlType) |
if not control then |
feedpath[i] = path[i] |
end |
BuildPath(feedpath, string.split("\001", uniquevalue)) |
BuildPath(feedpath, ("\001"):split(uniquevalue)) |
local group = options |
for i = 1, #feedpath do |
if not group then return end |
GameTooltip:SetOwner(button, "ANCHOR_NONE") |
if widget.type == "TabGroup" then |
GameTooltip:SetPoint("BOTTOM",button,"TOP") |
GameTooltip:SetPoint("BOTTOM",button,"TOP") |
else |
GameTooltip:SetPoint("LEFT",button,"RIGHT") |
GameTooltip:SetPoint("LEFT",button,"RIGHT") |
end |
GameTooltip:SetText(name, 1, .82, 0, 1) |
feedpath[i] = path[i] |
end |
BuildPath(feedpath, string.split("\001", uniquevalue)) |
BuildPath(feedpath, ("\001"):split(uniquevalue)) |
local group = options |
for i = 1, #feedpath do |
feedpath[i] = path[i] |
end |
BuildPath(feedpath, string.split("\001", uniquevalue)) |
BuildPath(feedpath, ("\001"):split(uniquevalue)) |
local group = options |
for i = 1, #feedpath do |
group = GetSubOption(group, feedpath[i]) |
--Add a scrollframe if we are not going to add a group control, this is the inverse of the conditions for that later on |
if (not (hasChildGroups and not inline)) or (grouptype ~= "tab" and grouptype ~= "select" and (parenttype == "tree" and not isRoot)) then |
if container.type ~= "InlineGroup" then |
if container.type ~= "InlineGroup" and container.type ~= "SimpleGroup" then |
scroll = gui:Create("ScrollFrame") |
scroll:SetLayout("flow") |
scroll.width = "fill" |
end |
if hasChildGroups and not inline then |
local name = GetOptionsMemberValue("name", group, options, path, appName) |
if grouptype == "tab" then |
local tab = gui:Create("TabGroup") |
elseif grouptype == "select" then |
local select = gui:Create("DropdownGroup") |
select:SetTitle(name) |
InjectInfo(select, options, group, path, rootframe, appName) |
select:SetCallback("OnGroupSelected", GroupSelected) |
local status = AceConfigDialog:GetStatusTable(appName, path) |
end |
if firstgroup then |
select:SetGroup( (GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or firstgroup) |
select:SetGroup((GroupExists(appName, options, path,status.groups.selected) and status.groups.selected) or firstgroup) |
end |
select.width = "fill" |
AceConfigDialog.OpenFrames[appName]:Hide() |
end |
if AceConfigDialog.BlizOptions and AceConfigDialog.BlizOptions[appName] then |
local widget = AceConfigDialog.BlizOptions[appName] |
if not widget:IsVisible() then |
widget:ReleaseChildren() |
for key, widget in pairs(AceConfigDialog.BlizOptions[appName]) do |
if not widget:IsVisible() then |
widget:ReleaseChildren() |
end |
end |
end |
this.closing[appName] = nil |
for appName in pairs(this.apps) do |
if AceConfigDialog.OpenFrames[appName] then |
local user = AceConfigDialog.OpenFrames[appName]:GetUserDataTable() |
AceConfigDialog:Open(appName, user.basepath and unpack(user.basepath)) |
AceConfigDialog:Open(appName, unpack(user.basepath or emptyTbl)) |
end |
if AceConfigDialog.BlizOptions and AceConfigDialog.BlizOptions[appName] then |
local widget = AceConfigDialog.BlizOptions[appName] |
local user = widget:GetUserDataTable() |
if widget:IsVisible() then |
AceConfigDialog:Open(widget:GetUserData('appName'), widget, user.basepath and unpack(user.basepath)) |
for key, widget in pairs(AceConfigDialog.BlizOptions[appName]) do |
local user = widget:GetUserDataTable() |
if widget:IsVisible() then |
AceConfigDialog:Open(widget:GetUserData('appName'), widget, unpack(user.basepath or emptyTbl)) |
end |
end |
end |
this.apps[appName] = nil |
if f.SetStatusTable then |
f:SetStatusTable(status) |
end |
if f.SetTitle then |
f:SetTitle(name or "") |
end |
else |
if not self.OpenFrames[appName] then |
f = gui:Create("Frame") |
del(path) |
end |
AceConfigDialog.BlizOptions = AceConfigDialog.BlizOptions or {} |
-- convert pre-39 BlizOptions structure to the new format |
if oldminor and oldminor < 39 and AceConfigDialog.BlizOptions then |
local old = AceConfigDialog.BlizOptions |
local new = {} |
for key, widget in pairs(old) do |
local appName = widget:GetUserData('appName') |
if not new[appName] then new[appName] = {} end |
new[appName][key] = widget |
end |
AceConfigDialog.BlizOptions = new |
else |
AceConfigDialog.BlizOptions = AceConfigDialog.BlizOptions or {} |
end |
local function FeedToBlizPanel(widget, event) |
local path = widget:GetUserData('path') |
AceConfigDialog:Open(widget:GetUserData('appName'), widget, path and unpack(path)) |
AceConfigDialog:Open(widget:GetUserData('appName'), widget, unpack(path or emptyTbl)) |
end |
local function ClearBlizPanel(widget, event) |
key = key..'\001'..select(n, ...) |
end |
if not BlizOptions[key] then |
if not BlizOptions[appName] then |
BlizOptions[appName] = {} |
end |
if not BlizOptions[appName][key] then |
local group = gui:Create("BlizOptionsGroup") |
BlizOptions[key] = group |
BlizOptions[appName][key] = group |
group:SetName(name or appName, parent) |
group:SetTitle(name or appName) |