diff --git a/data/spells.lua b/data/spells.lua index 64109dd..f4093a0 100644 --- a/data/spells.lua +++ b/data/spells.lua @@ -13,38 +13,40 @@ -- values: silence,gapcloser,defensive,potion,nuke,anticc,cc,stun,disarm,cdreset,shield,uncategorized --ispetspell -> if its a pet spell true, else false ---TODO recklessness value! +--TODO shield slam r1-5 Rect.spells = { --Trinkets - [42292] = {120, nil, 120, 120, 120, 0, "", "anticc", false}, --PvP Trinket + --This (Doesn't work, because there is no combatlog event) + [42292] = {120, nil, 120, 120, 120, 0, "", "anticc", false}, --PvP Trinket + + [44055] = {180, nil, 180, 180, 180, 0, "", "defensive", false}, --Battlemaster Trinket + --Other Stuff + --TODO Rocket boots extreme [54861] = {180, nil, 180, 180, 180, 0, "", "gapcloser", false}, --Rocket Boots (Enchant) + --Racials (War Stomp no combatlog entry) - [59752] = {120, nil, 120, 120, 120, 0, "", "anticc", false}, --Every Man For Himself + [20600] = {180, nil, 120, 120, 120, 0, "", "anticc", false}, --Perception [7744] = {120, nil, 120, 120, 120, 0, "", "defensive", false}, --Will of the Forsaken [25046] = {120, nil, 120, 120, 120, 0, "", "silence", false}, --Arcane Torrent (Energy Version) [28730] = {120, nil, 120, 120, 120, 0, "", "silence", false}, --Arcane Torrent (Mana version) [50613] = {120, nil, 120, 120, 120, 0, "", "silence", false}, --Arcane Torrent (Runic Power version) [28730] = {120, nil, 120, 120, 120, 0, "", "silence", false}, --Arcane Torrent (Heroes Warrior) [65116] = {120, nil, 120, 120, 120, 0, "", "defensive", false}, --Stoneform - [58984] = {120, nil, 120, 120, 120, 0, "", "defensive", false}, --Shadowmeld [20589] = {105, nil, 105, 105, 105, 0, "", "defensive", false}, --Escape Artist [28880] = {180, nil, 180, 180, 180, 0, "", "defensive", false}, --Gift of the Naaru --Potions [6615] = {60, nil, 60, 60, 60, 0, "", "potion", false}, --Free Action Potion --Warrior - --Total: 20 + --Total: 15 --Arms - [46924] = {90, nil, 90, 90, 90, 3, "Warrior", "nuke", false}, --BladeStrom [100] = {15, nil, 20, 15, 15, 0, "Warrior", "gapcloser", false}, --Charge rank 1 [6178] = {15, nil, 20, 15, 15, 0, "Warrior", "gapcloser", false}, --Charge rank 2 [11578] = {15, nil, 20, 15, 15, 0, "Warrior", "gapcloser", false}, --Charge rank 3 - [57755] = {60, nil, 60, 60, 60, 0, "Warrior", "uncategorized", false}, --Heroic Throw - [20230] = {240, nil, 300, 300, 240, 0, "Warrior", "nuke", false}, --Retaliation - [64382] = {300, nil, 300, 300, 300, 0, "Warrior", "uncategorized", false}, --Shattering Throw - [12328] = {30, nil, 30, 30, 30, 3, "Warrior", "uncategorized", false}, --Sweeping Strikes + [20230] = {1800, nil, 1800, 1800, 1800, 0, "Warrior", "nuke", false}, --Retaliation + [12292] = {180, nil, 180, 180, 180, 3, "Warrior", "nuke", false}, --Death Wish --Detection [12294] = {0, nil, 0, 0, 0, 3, "Warrior", "", false}, --Mortal Strike r1 [21551] = {0, nil, 0, 0, 0, 3, "Warrior", "", false}, --Mortal Strike r2 @@ -52,36 +54,31 @@ Rect.spells = { [21553] = {0, nil, 0, 0, 0, 3, "Warrior", "", false}, --Mortal Strike r4 [25248] = {0, nil, 0, 0, 0, 3, "Warrior", "", false}, --Mortal Strike r5 [30330] = {0, nil, 0, 0, 0, 3, "Warrior", "", false}, --Mortal Strike r6 - [47485] = {0, nil, 0, 0, 0, 3, "Warrior", "", false}, --Mortal Strike r7 - [47486] = {0, nil, 0, 0, 0, 3, "Warrior", "", false}, --Mortal Strike r8 --Fury - [18499] = {20.1, nil, 30, 20.1, 30, 0, "Warrior", "anticc", false}, --Berserker Rage - [12292] = {121, nil, 121, 121, 121, 4, "Warrior", "nuke", false}, --Death Wish - [55694] = {180, nil, 180, 180, 180, 0, "Warrior", "defensive", false}, --Enraged Regeneration - [60970] = {45, {20252}, 45, 45, 45, 4, "Warrior", "gapcloser", false}, --Heroic Fury - [20252] = {20, nil, 30, 20, 30, 0, "Warrior", "gapcloser", false}, --Intercept - [5246] = {120, nil, 120, 120, 120, 0, "Warrior", "cc", false}, --Intimidating Shout + [18499] = {30, nil, 30, 30, 30, 0, "Warrior", "anticc", false}, --Berserker Rage + [20252] = {30, nil, 20, 30, 30, 0, "Warrior", "gapcloser", false}, --Intercept + [5246] = {180, nil, 180, 180, 180, 0, "Warrior", "cc", false}, --Intimidating Shout [6552] = {10, nil, 10, 10, 10, 0, "Warrior", "silence", false}, --Pummel - [1719] = {161, nil, 300, 210, 240, 0, "Warrior", "nuke", false}, --Recklessness + [1719] = {1800, nil, 1800, 1800, 1800, 0, "Warrior", "nuke", false}, --Recklessness + [12328] = {30, nil, 30, 30, 30, 4, "Warrior", "uncategorized", false}, --Sweeping Strikes --Detection [23881] = {0, nil, 0, 0, 0, 4, "Warrior", "uncategorized", false}, --Bloodthirst --Protection - [12809] = {30, nil, 30, 30, 30, 5, "Warrior", "stun", false}, --Concussion Blow - [676] = {40, nil, 60, 60, 60, 0, "Warrior", "disarm", false}, --Disarm + [12809] = {45, nil, 45, 45, 45, 5, "Warrior", "stun", false}, --Concussion Blow + [676] = {60, nil, 60, 60, 60, 0, "Warrior", "disarm", false}, --Disarm [3411] = {30, nil, 30, 30, 30, 0, "Warrior", "gapcloser", false}, --Intervene - [12975] = {180, nil, 180, 180, 180, 0, "Warrior", "defensive", false}, --Last Stand - [72] = {12, nil, 12, 12, 12, 0, "Warrior", "silence", false}, --Shield Bash - [871] = {240, nil, 300, 300, 240, 0, "Warrior", "defensive", false}, --Shield Wall - [46968] = {20, nil, 20, 20, 20, 5, "Warrior", "stun", false}, --Shockwave + [12975] = {480, nil, 480, 480, 480, 0, "Warrior", "defensive", false}, --Last Stand + [871] = {1800, nil, 1800, 1800, 1800, 0, "Warrior", "defensive", false}, --Shield Wall [23920] = {10, nil, 10, 10, 10, 0, "Warrior", "silence", false}, --Spell Reflection + [72] = {12, nil, 12, 12, 12, 0, "Warrior", "silence", false}, --Shield Bash --Detection [20243] = {0, nil, 0, 0, 0, 5, "Warrior", "", false}, --Devastate r1 [30016] = {0, nil, 0, 0, 0, 5, "Warrior", "", false}, --Devastate r2 [30022] = {0, nil, 0, 0, 0, 5, "Warrior", "", false}, --Devastate r3 - [47497] = {0, nil, 0, 0, 0, 5, "Warrior", "", false}, --Devastate r4 - [47498] = {0, nil, 0, 0, 0, 5, "Warrior", "", false}, --Devastate r5 - [50720] = {0, nil, 0, 0, 0, 5, "Warrior", "", false}, --Vigilance + + [30022] = {0, nil, 0, 0, 0, 5, "Warrior", "", false}, --Shield Slam r6 + --Paladin --Total: 16 --Holy @@ -249,6 +246,8 @@ Rect.spells = { --Priest --Total: 14 + --Racials + [25441] = {180, nil, 180, 180, 180, 0, "Priest", "silence", false}, --Feedback --Discipline [6346] = {180, nil, 180, 180, 180, 0, "Priest", "anticc", false}, --Fear Ward [14751] = {144, nil, 144, 180, 180, 0, "Priest", "uncategorized", false}, --Inner Focus @@ -311,58 +310,6 @@ Rect.spells = { [48159] = {0, nil, 0, 0, 0, 5, "Priest", "", false}, --Vampiric Touch r4 [48160] = {0, nil, 0, 0, 0, 5, "Priest", "", false}, --Vampiric Touch r5 - --Death Knight - --Pet - [47481] = {60, nil, 60, 60, 60, 0, "DeathKnight", "stun", true}, --Gnaw - --Total: 18 - --Blood - [49028] = {90, nil, 90, 90, 90, 3, "DeathKnight", "nuke", false}, --Dancing Rune Weapon - [48743] = {120, nil, 120, 120, 120, 0, "DeathKnight", "defensive", false}, --Death Pact - [49016] = {180, nil, 180, 180, 180, 3, "DeathKnight", "nuke", false}, --Hysteria - [49005] = {180, nil, 180, 180, 180, 3, "DeathKnight", "defensive", false}, --Mark of Blood - [48982] = {30, nil, 30, 60, 60, 0, "DeathKnight", "defensive", false}, --Rune Tap - [47476] = {120, nil, 120, 120, 120, 0, "DeathKnight", "silence", false}, --Strangulate - [55233] = {60, nil, 60, 60, 60, 3, "DeathKnight", "defensive", false}, --Vampiric Blood - --Detection - [55050] = {0, nil, 0, 0, 0, 3, "DeathKnight", "", false}, --Heart Strike r1 - [55258] = {0, nil, 0, 0, 0, 3, "DeathKnight", "", false}, --Heart Strike r2 - [55259] = {0, nil, 0, 0, 0, 3, "DeathKnight", "", false}, --Heart Strike r3 - [55260] = {0, nil, 0, 0, 0, 3, "DeathKnight", "", false}, --Heart Strike r4 - [55261] = {0, nil, 0, 0, 0, 3, "DeathKnight", "", false}, --Heart Strike r5 - [55262] = {0, nil, 0, 0, 0, 3, "DeathKnight", "", false}, --Heart Strike r6 - --Frost - [49796] = {120, nil, 120, 120, 120, 4, "DeathKnight", "defensive", false}, --Unbreakable Armor - [47568] = {300, nil, 300, 300, 300, 0, "DeathKnight", "nuke", false}, --Empower Rune Weapon - [49203] = {60, nil, 60, 60, 60, 4, "DeathKnight", "cc", false}, --Hungering Cold - [48792] = {120, nil, 120, 120, 120, 0, "DeathKnight", "anticc", false}, --Icebound Fortitude - [49039] = {120, nil, 120, 120, 120, 0, "DeathKnight", "anticc", false}, --Lichborne - [47528] = {10, nil, 10, 10, 10, 0, "DeathKnight", "silence", false}, --Mind Freeze - [51271] = {60, nil, 60, 60, 60, 4, "DeathKnight", "defensive", false}, --Unbreakable Armor - --Detection - [49143] = {0, nil, 0, 0, 0, 4, "DeathKnight", "", false}, --Frost Strike r1 - [51416] = {0, nil, 0, 0, 0, 4, "DeathKnight", "", false}, --Frost Strike r2 - [51271] = {0, nil, 0, 0, 0, 4, "DeathKnight", "", false}, --Frost Strike r3 - [51418] = {0, nil, 0, 0, 0, 4, "DeathKnight", "", false}, --Frost Strike r4 - [51419] = {0, nil, 0, 0, 0, 4, "DeathKnight", "", false}, --Frost Strike r5 - [55268] = {0, nil, 0, 0, 0, 4, "DeathKnight", "", false}, --Frost Strike r6 - [49184] = {0, nil, 0, 0, 0, 4, "DeathKnight", "", false}, --Howling Blast r1 - [51409] = {0, nil, 0, 0, 0, 4, "DeathKnight", "", false}, --Howling Blast r2 - [51410] = {0, nil, 0, 0, 0, 4, "DeathKnight", "", false}, --Howling Blast r3 - [51411] = {0, nil, 0, 0, 0, 4, "DeathKnight", "", false}, --Howling Blast r4 - --Unholy - [48707] = {45, nil, 45, 45, 45, 0, "DeathKnight", "defensive", false}, --Anti-Magic Shell - [51052] = {120, nil, 120, 120, 120, 5, "DeathKnight", "defensive", false}, --Anti-Magic Zone - [42650] = {360, nil, 600, 600, 360, 0, "DeathKnight", "nuke", false}, --Army of the Dead - [49222] = {60, nil, 60, 60, 60, 5, "DeathKnight", "defensive", false}, --Bone Shield - [49576] = {25, nil, 35, 35, 25, 0, "DeathKnight", "gapcloser", false}, --Death Grip - [49206] = {180, nil, 180, 180, 180, 5, "DeathKnight", "nuke", false}, --Summon Gargoyle - --Detection - [55090] = {0, nil, 0, 0, 0, 5, "DeathKnight", "", false}, --Scourge Strike r1 - [55265] = {0, nil, 0, 0, 0, 5, "DeathKnight", "", false}, --Scourge Strike r2 - [55270] = {0, nil, 0, 0, 0, 5, "DeathKnight", "", false}, --Scourge Strike r3 - [55271] = {0, nil, 0, 0, 0, 5, "DeathKnight", "", false}, --Scourge Strike r4 - [63560] = {0, nil, 0, 0, 0, 5, "DeathKnight", "", false}, --Ghoul Frenzy - --Shaman --Total: 17 --Elemental diff --git a/lib/AceConfig-3.0/AceConfig-3.0.lua b/lib/AceConfig-3.0/AceConfig-3.0.lua index 059c08d..156e793 100644 --- a/lib/AceConfig-3.0/AceConfig-3.0.lua +++ b/lib/AceConfig-3.0/AceConfig-3.0.lua @@ -1,47 +1,33 @@ ---- AceConfig-3.0 wrapper library. --- Provides an API to register an options table with the config registry, --- as well as associate it with a slash command. --- @class file --- @name AceConfig-3.0 --- @release $Id: AceConfig-3.0.lua 877 2009-11-02 15:56:50Z nevcairiel $ - +--[[ $Id: AceConfig-3.0.lua 60131 2008-02-03 13:03:56Z nevcairiel $ ]] --[[ AceConfig-3.0 Very light wrapper library that combines all the AceConfig subcomponents into one more easily used whole. +Also automatically adds "config", "enable" and "disable" commands to options table as appropriate. + ]] local MAJOR, MINOR = "AceConfig-3.0", 2 -local AceConfig = LibStub:NewLibrary(MAJOR, MINOR) +local lib = LibStub:NewLibrary(MAJOR, MINOR) + +if not lib then return end -if not AceConfig then return end local cfgreg = LibStub("AceConfigRegistry-3.0") local cfgcmd = LibStub("AceConfigCmd-3.0") local cfgdlg = LibStub("AceConfigDialog-3.0") --TODO: local cfgdrp = LibStub("AceConfigDropdown-3.0") --- Lua APIs -local pcall, error, type, pairs = pcall, error, type, pairs --- ------------------------------------------------------------------- +--------------------------------------------------------------------- -- :RegisterOptionsTable(appName, options, slashcmd, persist) -- -- - appName - (string) application name -- - options - table or function ref, see AceConfigRegistry -- - slashcmd - slash command (string) or table with commands, or nil to NOT create a slash command ---- Register a option table with the AceConfig registry. --- You can supply a slash command (or a table of slash commands) to register with AceConfigCmd directly. --- @paramsig appName, options [, slashcmd] --- @param appName The application name for the config table. --- @param options The option table (or a function to generate one on demand) --- @param slashcmd A slash command to register for the option table, or a table of slash commands. --- @usage --- local AceConfig = LibStub("AceConfig-3.0") --- AceConfig:RegisterOptionsTable("MyAddon", myOptions, {"/myslash", "/my"}) -function AceConfig:RegisterOptionsTable(appName, options, slashcmd) +function lib:RegisterOptionsTable(appName, options, slashcmd) local ok,msg = pcall(cfgreg.RegisterOptionsTable, self, appName, options) if not ok then error(msg, 2) end diff --git a/lib/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.lua b/lib/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.lua index e764a99..d52742e 100644 --- a/lib/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.lua +++ b/lib/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.lua @@ -1,7 +1,3 @@ ---- AceConfigCmd-3.0 handles access to an options table through the "command line" interface via the ChatFrames. --- @class file --- @name AceConfigCmd-3.0 --- @release $Id: AceConfigCmd-3.0.lua 904 2009-12-13 11:56:37Z nevcairiel $ --[[ AceConfigCmd-3.0 @@ -12,35 +8,23 @@ REQUIRES: AceConsole-3.0 for command registration (loaded on demand) ]] +-- TODO: handle disabled / hidden +-- TODO: implement handlers for all types -- TODO: plugin args -local MAJOR, MINOR = "AceConfigCmd-3.0", 12 -local AceConfigCmd = LibStub:NewLibrary(MAJOR, MINOR) +local MAJOR, MINOR = "AceConfigCmd-3.0", 6 +local lib = LibStub:NewLibrary(MAJOR, MINOR) -if not AceConfigCmd then return end +if not lib then return end -AceConfigCmd.commands = AceConfigCmd.commands or {} -local commands = AceConfigCmd.commands +lib.commands = lib.commands or {} +local commands = lib.commands local cfgreg = LibStub("AceConfigRegistry-3.0") local AceConsole -- LoD local AceConsoleName = "AceConsole-3.0" --- Lua APIs -local strsub, strsplit, strlower, strmatch, strtrim = string.sub, string.split, string.lower, string.match, string.trim -local format, tonumber, tostring = string.format, tonumber, tostring -local tsort, tinsert = table.sort, table.insert -local select, pairs, next, type = select, pairs, next, type -local error, assert = error, assert - --- WoW APIs -local _G = _G - --- Global vars/functions that we don't upvalue since they might get hooked, or upgraded --- List them here for Mikk's FindGlobals script --- GLOBALS: LibStub, SELECTED_CHAT_FRAME, DEFAULT_CHAT_FRAME - local L = setmetatable({}, { -- TODO: replace with proper locale __index = function(self,k) return k end @@ -52,14 +36,6 @@ local function print(msg) (SELECTED_CHAT_FRAME or DEFAULT_CHAT_FRAME):AddMessage(msg) end --- constants used by getparam() calls below - -local handlertypes = {["table"]=true} -local handlermsg = "expected a table" - -local functypes = {["function"]=true, ["string"]=true} -local funcmsg = "expected function or member name" - -- pickfirstset() - picks the first non-nil value and returns it @@ -189,20 +165,7 @@ local function iterateargs(tab) end end -local function checkhidden(info, inputpos, tab) - if tab.cmdHidden~=nil then - return tab.cmdHidden - end - local hidden = tab.hidden - if type(hidden) == "function" or type(hidden) == "string" then - info.hidden = hidden - hidden = callmethod(info, inputpos, tab, 'hidden') - info.hidden = nil - end - return hidden -end - -local function showhelp(info, inputpos, tab, depth, noHead) +local function showhelp(info, inputpos, tab, noHead) if not noHead then print("|cff33ff99"..info.appName.."|r: Arguments to |cffffff78/"..info[0].."|r "..strsub(info.input,1,inputpos-1)..":") end @@ -212,12 +175,12 @@ local function showhelp(info, inputpos, tab, depth, noHead) for k,v in iterateargs(tab) do if not refTbl[k] then -- a plugin overriding something in .args - tinsert(sortTbl, k) + table.insert(sortTbl, k) refTbl[k] = v end end - tsort(sortTbl, function(one, two) + table.sort(sortTbl, function(one, two) local o1 = refTbl[one].order or 100 local o2 = refTbl[two].order or 100 if type(o1) == "function" or type(o1) == "string" then @@ -241,28 +204,22 @@ local function showhelp(info, inputpos, tab, depth, noHead) return o1optiontable -- - depth - starts at 0 -- - retfalse - return false rather than produce error if a match is not found (used by inlined groups) @@ -357,9 +322,9 @@ local function handle(info, inputpos, tab, depth, retfalse) if tab.plugins and type(tab.plugins)~="table" then err(info,inputpos) end -- grab next arg from input - local _,nextpos,arg = (info.input):find(" *([^ ]+) *", inputpos) + local _,nextpos,arg = string.find(info.input, " *([^ ]+) *", inputpos) if not arg then - showhelp(info, inputpos, tab, depth) + showhelp(info, inputpos, tab) return end nextpos=nextpos+1 @@ -378,7 +343,7 @@ local function handle(info, inputpos, tab, depth, retfalse) return -- done, name was found in inline group end -- matching name and not a inline group - elseif strlower(arg)==strlower(k:gsub(" ", "_")) then + elseif strlower(arg)==strlower(k) then info[depth+1] = k return handle(info,nextpos,v,depth+1) end @@ -488,6 +453,10 @@ local function handle(info, inputpos, tab, depth, retfalse) elseif tab.type=="select" then ------------ select ------------------------------------ local str = strtrim(strlower(str)) + if str == "" then + --TODO: Show current selection and possible values + return + end local values = tab.values if type(values) == "function" or type(values) == "string" then @@ -495,21 +464,6 @@ local function handle(info, inputpos, tab, depth, retfalse) values = callmethod(info, inputpos, tab, "values") info.values = nil end - - if str == "" then - local b = callmethod(info, inputpos, tab, "get") - local fmt = "|cffffff78- [%s]|r %s" - local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r" - print(L["Options for |cffffff78"..info[#info].."|r:"]) - for k, v in pairs(values) do - if b == k then - print(fmt_sel:format(k, v)) - else - print(fmt:format(k, v)) - end - end - return - end local ok for k,v in pairs(values) do @@ -529,35 +483,25 @@ local function handle(info, inputpos, tab, depth, retfalse) elseif tab.type=="multiselect" then ------------ multiselect ------------------------------------------- local str = strtrim(strlower(str)) + if str == "" then + --TODO: Show current values + return + end local values = tab.values if type(values) == "function" or type(values) == "string" then info.values = values values = callmethod(info, inputpos, tab, "values") info.values = nil - end - - if str == "" then - local fmt = "|cffffff78- [%s]|r %s" - local fmt_sel = "|cffffff78- [%s]|r %s |cffff0000*|r" - print(L["Options for |cffffff78"..info[#info].."|r (multiple possible):"]) - for k, v in pairs(values) do - if callmethod(info, inputpos, tab, "get", k) then - print(fmt_sel:format(k, v)) - else - print(fmt:format(k, v)) - end - end - return - end + end --build a table of the selections, checking that they exist --parse for =on =off =default in the process --table will be key = true for options that should toggle, key = [on|off|default] for options to be set local sels = {} - for v in str:gmatch("[^ ]+") do + for v in string.gmatch(str, "[^ ]+") do --parse option=on etc - local opt, val = v:match('(.+)=(.+)') + local opt, val = string.match(v,'(.+)=(.+)') --get option if toggling if not opt then opt = v @@ -720,27 +664,17 @@ local function handle(info, inputpos, tab, depth, retfalse) end end ---- Handle the chat command. --- This is usually called from a chat command handler to parse the command input as operations on an aceoptions table.\\ --- AceConfigCmd uses this function internally when a slash command is registered with `:CreateChatCommand` --- @param slashcmd The slash command WITHOUT leading slash (only used for error output) --- @param appName The application name as given to `:RegisterOptionsTable()` --- @param input The commandline input (as given by the WoW handler, i.e. without the command itself) --- @usage --- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceConsole-3.0") --- -- Use AceConsole-3.0 to register a Chat Command --- MyAddon:RegisterChatCommand("mychat", "ChatCommand") + +----------------------------------------------------------------------- +-- HandleCommand(slashcmd, appName, input) +-- +-- Call this from a chat command handler to parse the command input as operations on an aceoptions table -- --- -- Show the GUI if no input is supplied, otherwise handle the chat input. --- function MyAddon:ChatCommand(input) --- -- Assuming "MyOptions" is the appName of a valid options table --- if not input or input:trim() == "" then --- LibStub("AceConfigDialog-3.0"):Open("MyOptions") --- else --- LibStub("AceConfigCmd-3.0").HandleCommand(MyAddon, "mychat", "MyOptions", input) --- end --- end -function AceConfigCmd:HandleCommand(slashcmd, appName, input) +-- slashcmd (string) - the slash command WITHOUT leading slash (only used for error output) +-- appName (string) - the application name as given to AceConfigRegistry:RegisterOptionsTable() +-- input (string) -- the commandline input (as given by the WoW handler, i.e. without the command itself) + +function lib:HandleCommand(slashcmd, appName, input) local optgetter = cfgreg:GetOptionsTable(appName) if not optgetter then @@ -762,26 +696,34 @@ function AceConfigCmd:HandleCommand(slashcmd, appName, input) handle(info, 1, options, 0) -- (info, inputpos, table, depth) end ---- Utility function to create a slash command handler. + + +----------------------------------------------------------------------- +-- CreateChatCommand(slashcmd, appName) +-- +-- Utility function to create a slash command handler. -- Also registers tab completion with AceTab --- @param slashcmd The slash command WITHOUT leading slash (only used for error output) --- @param appName The application name as given to `:RegisterOptionsTable()` -function AceConfigCmd:CreateChatCommand(slashcmd, appName) +-- +-- slashcmd (string) - the slash command WITHOUT leading slash (only used for error output) +-- appName (string) - the application name as given to AceConfigRegistry:RegisterOptionsTable() + +function lib:CreateChatCommand(slashcmd, appName) if not AceConsole then AceConsole = LibStub(AceConsoleName) end if AceConsole.RegisterChatCommand(self, slashcmd, function(input) - AceConfigCmd.HandleCommand(self, slashcmd, appName, input) -- upgradable + lib.HandleCommand(self, slashcmd, appName, input) -- upgradable end, true) then -- succesfully registered so lets get the command -> app table in commands[slashcmd] = appName end end ---- Utility function that returns the options table that belongs to a slashcommand. --- Designed to be used for the AceTab interface. --- @param slashcmd The slash command WITHOUT leading slash (only used for error output) --- @return The options table associated with the slash command (or nil if the slash command was not registered) -function AceConfigCmd:GetChatCommandOptions(slashcmd) +-- GetChatCommandOptions(slashcmd) +-- +-- Utility function that returns the options table that belongs to a slashcommand +-- mainly used by AceTab + +function lib:GetChatCommandOptions(slashcmd) return commands[slashcmd] end diff --git a/lib/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua b/lib/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua index b57ac89..626e062 100644 --- a/lib/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua +++ b/lib/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua @@ -1,40 +1,36 @@ ---- 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 958 2010-07-03 10:22:29Z nevcairiel $ +--[[ +AceConfigDialog-3.0 +]] local LibStub = LibStub -local MAJOR, MINOR = "AceConfigDialog-3.0", 49 -local AceConfigDialog, oldminor = LibStub:NewLibrary(MAJOR, MINOR) +local MAJOR, MINOR = "AceConfigDialog-3.0", 25 +local lib = LibStub:NewLibrary(MAJOR, MINOR) -if not AceConfigDialog then return end +if not lib then return end -AceConfigDialog.OpenFrames = AceConfigDialog.OpenFrames or {} -AceConfigDialog.Status = AceConfigDialog.Status or {} -AceConfigDialog.frame = AceConfigDialog.frame or CreateFrame("Frame") +lib.OpenFrames = lib.OpenFrames or {} +lib.Status = lib.Status or {} +lib.frame = lib.frame or CreateFrame("Frame") -AceConfigDialog.frame.apps = AceConfigDialog.frame.apps or {} -AceConfigDialog.frame.closing = AceConfigDialog.frame.closing or {} -AceConfigDialog.frame.closeAllOverride = AceConfigDialog.frame.closeAllOverride or {} +lib.frame.apps = lib.frame.apps or {} +lib.frame.closing = lib.frame.closing or {} local gui = LibStub("AceGUI-3.0") local reg = LibStub("AceConfigRegistry-3.0") --- 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, wipe = pairs, next, select, type, unpack, wipe -local rawset, tostring, tonumber = rawset, 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: PlaySound, GameFontHighlight, GameFontHighlightSmall, GameFontHighlightLarge --- GLOBALS: CloseSpecialWindows, InterfaceOptions_AddCategory, geterrorhandler - -local emptyTbl = {} +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 _ --[[ xpcall safecall implementation @@ -63,7 +59,7 @@ local function CreateDispatcher(argCount) local ARGS = {} for i = 1, argCount do ARGS[i] = "arg"..i end - code = code:gsub("ARGS", tconcat(ARGS, ", ")) + code = code:gsub("ARGS", table.concat(ARGS, ", ")) return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler) end @@ -77,7 +73,7 @@ Dispatchers[0] = function(func) end local function safecall(func, ...) - return Dispatchers[select("#", ...)](func, ...) + return Dispatchers[select('#', ...)](func, ...) end local width_multiplier = 170 @@ -104,7 +100,7 @@ Group Types local new, del, copy --newcount, delcount,createdcount,cached = 0,0,0 do - local pool = setmetatable({},{__mode="k"}) + local pool = setmetatable({},{__mode='k'}) function new() --newcount = newcount + 1 local t = next(pool) @@ -182,13 +178,11 @@ local stringIsLiteral = { usage = true, width = true, image = true, - fontSize = true, } --Is Never a function or method local allIsLiteral = { type = true, - descStyle = true, imageWidth = true, imageHeight = true, } @@ -241,7 +235,7 @@ local function GetOptionsMemberValue(membername, option, options, path, appName, info.handler = handler info.option = option info.type = option.type - info.uiType = "dialog" + info.uiType = 'dialog' info.uiName = MAJOR local a, b, c ,d @@ -254,7 +248,7 @@ local function GetOptionsMemberValue(membername, option, options, path, appName, if handler and handler[member] then a,b,c,d = handler[member](handler, info, ...) else - error(format("Method %s doesn't exist in handler for type %s", member, membername)) + error(string.format("Method %s doesn't exist in handler for type %s", member, membername)) end end del(info) @@ -375,7 +369,7 @@ local function BuildSortedOptionsTable(group, keySort, opts, options, path, appN end end - tsort(keySort, compareOptions) + table.sort(keySort, compareOptions) del(tempOrders) del(tempNames) @@ -427,11 +421,10 @@ local function CleanUserData(widget, event) end end --- - 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 -function AceConfigDialog:GetStatusTable(appName, path) +--[[ + Gets a status table for the given appname and options path +]] +function lib:GetStatusTable(appName, path) local status = self.Status if not status[appName] then @@ -457,11 +450,10 @@ function AceConfigDialog:GetStatusTable(appName, path) return status.status end ---- Selects the specified path in the options window. --- The path specified has to match the keys of the groups in the table. --- @param appName The application name as given to `:RegisterOptionsTable()` --- @param ... The path to the key that should be selected -function AceConfigDialog:SelectGroup(appName, ...) +--[[ + Sets the given path to be selected +]] +function lib:SelectGroup(appName, ...) local path = new() @@ -479,7 +471,7 @@ function AceConfigDialog:SelectGroup(appName, ...) local treevalue local treestatus - for n = 1, select("#",...) do + for n = 1, select('#',...) do local key = select(n, ...) if group.childGroups == "tab" or group.childGroups == "select" then @@ -537,13 +529,10 @@ local function OptionOnMouseOver(widget, event) 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 opt.type == 'multiselect' then GameTooltip:AddLine(user.text,0.5, 0.5, 0.8, 1) end if type(desc) == "string" then @@ -562,10 +551,10 @@ end local function GetFuncName(option) local type = option.type - if type == "execute" then - return "func" + if type == 'execute' then + return 'func' else - return "set" + return 'set' end end local function confirmPopup(appName, rootframe, basepath, info, message, func, ...) @@ -585,17 +574,16 @@ local function confirmPopup(appName, rootframe, basepath, info, message, func, . if dialog and oldstrata then dialog:SetFrameStrata(oldstrata) end - AceConfigDialog:Open(appName, rootframe, unpack(basepath or emptyTbl)) + lib:Open(appName, rootframe, basepath and unpack(basepath)) del(info) end t.OnCancel = function() if dialog and oldstrata then dialog:SetFrameStrata(oldstrata) end - AceConfigDialog:Open(appName, rootframe, unpack(basepath or emptyTbl)) del(info) end - for i = 1, select("#", ...) do + for i = 1, select('#', ...) do t[i] = select(i, ...) or false end t.timeout = 0 @@ -654,7 +642,7 @@ local function ActivateControl(widget, event, ...) info.handler = handler info.option = option info.type = option.type - info.uiType = "dialog" + info.uiType = 'dialog' info.uiName = MAJOR local name @@ -685,7 +673,7 @@ local function ActivateControl(widget, event, ...) success, validated = safecall(handler[validate], handler, info, ...) if not success then validated = false end else - error(format("Method %s doesn't exist in handler for type execute", validate)) + error(string.format("Method %s doesn't exist in handler for type execute", validate)) end elseif type(validate) == "function" then success, validated = safecall(validate, info, ...) @@ -698,8 +686,6 @@ local function ActivateControl(widget, event, ...) --validate function returned a message to display if rootframe.SetStatusText then rootframe:SetStatusText(validated) - else - -- TODO: do something else. end PlaySound("igPlayerInviteDecline") del(info) @@ -716,8 +702,6 @@ local function ActivateControl(widget, event, ...) rootframe:SetStatusText(name..": Invalid Value") end end - else - -- TODO: do something else end PlaySound("igPlayerInviteDecline") del(info) @@ -736,7 +720,7 @@ local function ActivateControl(widget, event, ...) confirm = false end else - error(format("Method %s doesn't exist in handler for type confirm", confirm)) + error(string.format("Method %s doesn't exist in handler for type confirm", confirm)) end elseif type(confirm) == "function" then success, confirm = safecall(confirm, info, ...) @@ -765,18 +749,18 @@ local function ActivateControl(widget, event, ...) end end - local iscustom = user.rootframe:GetUserData("iscustom") + local iscustom = user.rootframe:GetUserData('iscustom') local rootframe if iscustom then rootframe = user.rootframe end - local basepath = user.rootframe:GetUserData("basepath") + local basepath = user.rootframe:GetUserData('basepath') if type(func) == "string" then if handler and handler[func] then confirmPopup(user.appName, rootframe, basepath, info, confirmText, handler[func], handler, info, ...) else - error(format("Method %s doesn't exist in handler for type func", func)) + error(string.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, ...) @@ -791,7 +775,7 @@ local function ActivateControl(widget, event, ...) if handler and handler[func] then safecall(handler[func],handler, info, ...) else - error(format("Method %s doesn't exist in handler for type func", func)) + error(string.format("Method %s doesn't exist in handler for type func", func)) end elseif type(func) == "function" then safecall(func,info, ...) @@ -799,24 +783,24 @@ local function ActivateControl(widget, event, ...) - local iscustom = user.rootframe:GetUserData("iscustom") - local basepath = user.rootframe:GetUserData("basepath") or emptyTbl + local iscustom = user.rootframe:GetUserData('iscustom') + local basepath = user.rootframe:GetUserData('basepath') --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)) + lib:Open(user.appName, user.rootframe, basepath and unpack(basepath)) else - AceConfigDialog:Open(user.appName, unpack(basepath)) + lib:Open(user.appName, basepath and unpack(basepath)) end end elseif option.type == "range" then if event == "OnMouseUp" then if iscustom then - AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath)) + lib:Open(user.appName, user.rootframe, basepath and unpack(basepath)) else - AceConfigDialog:Open(user.appName, unpack(basepath)) + lib:Open(user.appName, basepath and unpack(basepath)) end end --multiselects don't cause a refresh on 'OnValueChanged' only 'OnClosed' @@ -824,9 +808,9 @@ local function ActivateControl(widget, event, ...) user.valuechanged = true else if iscustom then - AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath)) + lib:Open(user.appName, user.rootframe, basepath and unpack(basepath)) else - AceConfigDialog:Open(user.appName, unpack(basepath)) + lib:Open(user.appName, basepath and unpack(basepath)) end end @@ -835,16 +819,12 @@ local function ActivateControl(widget, event, ...) end local function ActivateSlider(widget, event, value) - local option = widget:GetUserData("option") - 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 - if min then - if step then - value = math_floor((value - min) / step + 0.5) * step + min - end - value = math_max(value, min) - end - if max then - value = math_min(value, max) + 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 + else + value = math.max(math.min(value,max),min) end ActivateControl(widget,event,value) end @@ -852,33 +832,33 @@ end --called from a checkbox that is part of an internally created multiselect group --this type is safe to refresh on activation of one control local function ActivateMultiControl(widget, event, ...) - ActivateControl(widget, event, widget:GetUserData("value"), ...) + ActivateControl(widget, event, widget:GetUserData('value'), ...) local user = widget:GetUserDataTable() - local iscustom = user.rootframe:GetUserData("iscustom") - local basepath = user.rootframe:GetUserData("basepath") or emptyTbl + local iscustom = user.rootframe:GetUserData('iscustom') + local basepath = user.rootframe:GetUserData('basepath') if iscustom then - AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath)) + lib:Open(user.appName, user.rootframe, basepath and unpack(basepath)) else - AceConfigDialog:Open(user.appName, unpack(basepath)) + lib:Open(user.appName, basepath and unpack(basepath)) end end local function MultiControlOnClosed(widget, event, ...) local user = widget:GetUserDataTable() if user.valuechanged then - local iscustom = user.rootframe:GetUserData("iscustom") - local basepath = user.rootframe:GetUserData("basepath") or emptyTbl + local iscustom = user.rootframe:GetUserData('iscustom') + local basepath = user.rootframe:GetUserData('basepath') if iscustom then - AceConfigDialog:Open(user.appName, user.rootframe, unpack(basepath)) + lib:Open(user.appName, user.rootframe, basepath and unpack(basepath)) else - AceConfigDialog:Open(user.appName, unpack(basepath)) + lib:Open(user.appName, basepath and unpack(basepath)) end end end local function FrameOnClose(widget, event) - local appName = widget:GetUserData("appName") - AceConfigDialog.OpenFrames[appName] = nil + local appName = widget:GetUserData('appName') + lib.OpenFrames[appName] = nil gui:Release(widget) end @@ -975,8 +955,6 @@ local function BuildSubGroups(group, tree, options, path, appName) local entry = new() entry.value = k entry.text = GetOptionsMemberValue("name", v, options, path, appName) - entry.icon = GetOptionsMemberValue("icon", v, options, path, appName) - entry.iconCoords = GetOptionsMemberValue("iconCoords", v, options, path, appName) entry.disabled = CheckOptionDisabled(v, options, path, appName) if not tree.children then tree.children = new() end tinsert(tree.children,entry) @@ -1010,7 +988,6 @@ local function BuildGroups(group, options, path, appName, recurse) local entry = new() entry.value = k entry.text = GetOptionsMemberValue("name", v, options, path, appName) - entry.icon = GetOptionsMemberValue("icon", v, options, path, appName) entry.disabled = CheckOptionDisabled(v, options, path, appName) tinsert(tree,entry) if recurse and (v.childGroups or "tree") == "tree" then @@ -1084,47 +1061,23 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin 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" then - control = gui:Create("Icon") - if not width then - width = GetOptionsMemberValue("imageWidth",v, options, path, appName) - end - if not height then - height = GetOptionsMemberValue("imageHeight",v, options, path, appName) - end - if type(imageCoords) == "table" then - control:SetImage(image, unpack(imageCoords)) - else - control:SetImage(image) - end - if type(width) ~= "number" then - width = 32 - end - if type(height) ~= "number" then - height = 32 - end - control:SetImageSize(width, height) - control:SetLabel(name) - else - control = gui:Create("Button") - control:SetText(name) - end + control = gui:Create("Button") + control:SetText(name) 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") + error(("Invalid Custom Control Type - %s"):format(tostring(controlType))) end - if v.multiline and control.SetNumLines then - control:SetNumLines(tonumber(v.multiline) or 4) + if v.multiline then + local lines = 4 + if type(v.multiline) == "number" then + lines = v.multiline + end + control:SetHeight(60 + (14*lines)) end control:SetLabel(name) control:SetCallback("OnEnterPressed",ActivateControl) @@ -1141,26 +1094,11 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin 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) - control:SetSliderValues(v.softMin or v.min or 0, v.softMax or v.max or 100, v.bigStep or v.step or 0) + control:SetSliderValues(v.min or 0,v.max or 100, v.bigStep or v.step or 0) control:SetIsPercent(v.isPercent) local value = GetOptionsMemberValue("get",v, options, path, appName) if type(value) ~= "number" then @@ -1175,8 +1113,7 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin 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") + error(("Invalid Custom Control Type - %s"):format(tostring(controlType))) end control:SetLabel(name) control:SetList(values) @@ -1199,15 +1136,13 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin tinsert(valuesort, value) end end - tsort(valuesort) - + table.sort(valuesort) + if controlType then control = gui:Create(controlType) if not control then - geterrorhandler()(("Invalid Custom Control Type - %s"):format(tostring(controlType))) + error(("Invalid Custom Control Type - %s"):format(tostring(controlType))) end - end - if control then control:SetMultiselect(true) control:SetLabel(name) control:SetList(values) @@ -1243,8 +1178,8 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin local text = values[value] local check = gui:Create("CheckBox") check:SetLabel(text) - check:SetUserData("value", value) - check:SetUserData("text", text) + check:SetUserData('value', value) + check:SetUserData('text', text) check:SetDisabled(disabled) check:SetTriState(v.tristate) check:SetValue(GetOptionsMemberValue("get",v, options, path, appName, value)) @@ -1291,27 +1226,17 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin elseif v.type == "description" then control = gui:Create("Label") control:SetText(name) - - local fontSize = GetOptionsMemberValue("fontSize",v, options, path, appName) - if fontSize == "medium" then - control:SetFontObject(GameFontHighlight) - elseif fontSize == "large" then - control:SetFontObject(GameFontHighlightLarge) - 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" then + if type(image) == 'string' then if not width then width = GetOptionsMemberValue("imageWidth",v, options, path, appName) end if not height then height = GetOptionsMemberValue("imageHeight",v, options, path, appName) end - if type(imageCoords) == "table" then + if type(imageCoords) == 'table' then control:SetImage(image, unpack(imageCoords)) else control:SetImage(image) @@ -1362,7 +1287,7 @@ local function FeedOptions(appName, options,container,rootframe,path,group,inlin end local function BuildPath(path, ...) - for i = 1, select("#",...) do + for i = 1, select('#',...) do tinsert(path, (select(i,...))) end end @@ -1381,7 +1306,7 @@ local function TreeOnButtonEnter(widget, event, uniquevalue, button) feedpath[i] = path[i] end - BuildPath(feedpath, ("\001"):split(uniquevalue)) + BuildPath(feedpath, string.split("\001", uniquevalue)) local group = options for i = 1, #feedpath do if not group then return end @@ -1393,9 +1318,9 @@ local function TreeOnButtonEnter(widget, event, uniquevalue, button) 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) @@ -1421,7 +1346,7 @@ local function GroupExists(appName, options, path, uniquevalue) feedpath[i] = path[i] end - BuildPath(feedpath, ("\001"):split(uniquevalue)) + BuildPath(feedpath, string.split("\001", uniquevalue)) local group = options for i = 1, #feedpath do @@ -1454,13 +1379,13 @@ local function GroupSelected(widget, event, uniquevalue) feedpath[i] = path[i] end - BuildPath(feedpath, ("\001"):split(uniquevalue)) + BuildPath(feedpath, string.split("\001", 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) + lib:FeedGroup(user.appName,options,widget,rootframe,feedpath) del(feedpath) end @@ -1468,7 +1393,6 @@ end --[[ --- INTERNAL -- This function will feed one group, and any inline child groups into the given container Select Groups will only have the selection control (tree, tabs, dropdown) fed in and have a group selected, this event will trigger the feeding of child groups @@ -1483,20 +1407,24 @@ Rules: if its parent is a tree group, its already a node on a tree --]] -function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isRoot) +function lib:FeedGroup(appName,options,container,rootframe,path, isRoot) local group = options --follow the path to get to the curent group local inline local grouptype, parenttype = options.childGroups, "none" + --temp path table to pass to callbacks as we traverse the tree + local temppath = new() for i = 1, #path do local v = path[i] + temppath[i] = v group = GetSubOption(group, v) inline = inline or pickfirstset(v.dialogInline,v.guiInline,v.inline, false) parenttype = grouptype grouptype = group.childGroups end + del(temppath) if not parenttype then parenttype = "tree" @@ -1505,14 +1433,14 @@ function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isR --check if the group has child groups local hasChildGroups for k, v in pairs(group.args) do - if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) and not CheckOptionHidden(v, options, path, appName) then + if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) then hasChildGroups = true end end if group.plugins then for plugin, t in pairs(group.plugins) do for k, v in pairs(t) do - if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) and not CheckOptionHidden(v, options, path, appName) then + if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) then hasChildGroups = true end end @@ -1524,7 +1452,7 @@ function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isR --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" and container.type ~= "SimpleGroup" then + if container.type ~= "InlineGroup" then scroll = gui:Create("ScrollFrame") scroll:SetLayout("flow") scroll.width = "fill" @@ -1547,7 +1475,7 @@ function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isR end if hasChildGroups and not inline then - local name = GetOptionsMemberValue("name", group, options, path, appName) + if grouptype == "tab" then local tab = gui:Create("TabGroup") @@ -1556,7 +1484,7 @@ function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isR tab:SetCallback("OnTabEnter", TreeOnButtonEnter) tab:SetCallback("OnTabLeave", TreeOnButtonLeave) - local status = AceConfigDialog:GetStatusTable(appName, path) + local status = lib:GetStatusTable(appName, path) if not status.groups then status.groups = {} end @@ -1581,10 +1509,9 @@ function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isR 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) + local status = lib:GetStatusTable(appName, path) if not status.groups then status.groups = {} end @@ -1600,7 +1527,7 @@ function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isR 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" @@ -1622,7 +1549,7 @@ function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isR tree:SetCallback("OnButtonEnter", TreeOnButtonEnter) tree:SetCallback("OnButtonLeave", TreeOnButtonLeave) - local status = AceConfigDialog:GetStatusTable(appName, path) + local status = lib:GetStatusTable(appName, path) if not status.groups then status.groups = {} end @@ -1650,40 +1577,29 @@ local old_CloseSpecialWindows local function RefreshOnUpdate(this) for appName in pairs(this.closing) do - if AceConfigDialog.OpenFrames[appName] then - AceConfigDialog.OpenFrames[appName]:Hide() - end - if AceConfigDialog.BlizOptions and AceConfigDialog.BlizOptions[appName] then - for key, widget in pairs(AceConfigDialog.BlizOptions[appName]) do - if not widget:IsVisible() then - widget:ReleaseChildren() - end - end + if lib.OpenFrames[appName] then + lib.OpenFrames[appName]:Hide() end this.closing[appName] = nil end if this.closeAll then - for k, v in pairs(AceConfigDialog.OpenFrames) do - if not this.closeAllOverride[k] then - v:Hide() - end + for k, v in pairs(lib.OpenFrames) do + v:Hide() end 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() - AceConfigDialog:Open(appName, unpack(user.basepath or emptyTbl)) + if lib.OpenFrames[appName] then + local user = lib.OpenFrames[appName]:GetUserDataTable() + lib:Open(appName, user.basepath and unpack(user.basepath)) end - if AceConfigDialog.BlizOptions and AceConfigDialog.BlizOptions[appName] then - 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 + if lib.BlizOptions and lib.BlizOptions[appName] then + local widget = lib.BlizOptions[appName] + local user = widget:GetUserDataTable() + if widget:IsVisible() then + lib:Open(widget:GetUserData('appName'), widget, user.basepath and unpack(user.basepath)) end end this.apps[appName] = nil @@ -1691,58 +1607,39 @@ local function RefreshOnUpdate(this) this:SetScript("OnUpdate", nil) end --- Upgrade the OnUpdate script as well, if needed. -if AceConfigDialog.frame:GetScript("OnUpdate") then - AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate) -end - ---- Close all open options windows -function AceConfigDialog:CloseAll() - AceConfigDialog.frame.closeAll = true - AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate) +function lib:CloseAll() + lib.frame.closeAll = true + lib.frame:SetScript("OnUpdate", RefreshOnUpdate) if next(self.OpenFrames) then return true end end ---- Close a specific options window. --- @param appName The application name as given to `:RegisterOptionsTable()` -function AceConfigDialog:Close(appName) +function lib:Close(appName) if self.OpenFrames[appName] then - AceConfigDialog.frame.closing[appName] = true - AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate) + lib.frame.closing[appName] = true + lib.frame:SetScript("OnUpdate", RefreshOnUpdate) return true end end --- Internal -- Called by AceConfigRegistry -function AceConfigDialog:ConfigTableChanged(event, appName) - AceConfigDialog.frame.apps[appName] = true - AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate) +function lib:ConfigTableChanged(event, appName) + lib.frame.apps[appName] = true + lib.frame:SetScript("OnUpdate", RefreshOnUpdate) end -reg.RegisterCallback(AceConfigDialog, "ConfigTableChange", "ConfigTableChanged") +reg.RegisterCallback(lib, "ConfigTableChange", "ConfigTableChanged") ---- Sets the default size of the options window for a specific application. --- @param appName The application name as given to `:RegisterOptionsTable()` --- @param width The default width --- @param height The default height -function AceConfigDialog:SetDefaultSize(appName, width, height) - local status = AceConfigDialog:GetStatusTable(appName) +function lib:SetDefaultSize(appName, width, height) + local status = lib:GetStatusTable(appName) if type(width) == "number" and type(height) == "number" then status.width = width status.height = height end end ---- Open an option window at the specified path (if any). --- This function can optionally feed the group into a pre-created container --- instead of creating a new container frame. --- @paramsig appName [, container][, ...] --- @param appName The application name as given to `:RegisterOptionsTable()` --- @param container An optional container frame to feed the options into --- @param ... The path to open after creating the options window (see `:SelectGroup` for details) -function AceConfigDialog:Open(appName, container, ...) +-- :Open(appName, [container], [path ...]) +function lib:Open(appName, container, ...) if not old_CloseSpecialWindows then old_CloseSpecialWindows = CloseSpecialWindows CloseSpecialWindows = function() @@ -1767,7 +1664,7 @@ function AceConfigDialog:Open(appName, container, ...) tinsert(path, container) container = nil end - for n = 1, select("#",...) do + for n = 1, select('#',...) do tinsert(path, (select(n, ...))) end @@ -1775,12 +1672,12 @@ function AceConfigDialog:Open(appName, container, ...) if container then f = container f:ReleaseChildren() - f:SetUserData("appName", appName) - f:SetUserData("iscustom", true) + f:SetUserData('appName', appName) + f:SetUserData('iscustom', true) if #path > 0 then - f:SetUserData("basepath", copy(path)) + f:SetUserData('basepath', copy(path)) end - local status = AceConfigDialog:GetStatusTable(appName) + local status = lib:GetStatusTable(appName) if not status.width then status.width = 700 end @@ -1790,9 +1687,6 @@ function AceConfigDialog:Open(appName, container, ...) 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") @@ -1802,12 +1696,12 @@ function AceConfigDialog:Open(appName, container, ...) end f:ReleaseChildren() f:SetCallback("OnClose", FrameOnClose) - f:SetUserData("appName", appName) + f:SetUserData('appName', appName) if #path > 0 then - f:SetUserData("basepath", copy(path)) + f:SetUserData('basepath', copy(path)) end f:SetTitle(name or "") - local status = AceConfigDialog:GetStatusTable(appName) + local status = lib:GetStatusTable(appName) f:SetStatusTable(status) end @@ -1816,80 +1710,40 @@ function AceConfigDialog:Open(appName, container, ...) f:Show() end del(path) - - if AceConfigDialog.frame.closeAll then - -- close all is set, but thats not good, since we're just opening here, so force it - AceConfigDialog.frame.closeAllOverride[appName] = true - end end --- 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 +lib.BlizOptions = lib.BlizOptions or {} local function FeedToBlizPanel(widget, event) - local path = widget:GetUserData("path") - AceConfigDialog:Open(widget:GetUserData("appName"), widget, unpack(path or emptyTbl)) + local path = widget:GetUserData('path') + lib:Open(widget:GetUserData('appName'), widget, path and unpack(path)) end local function ClearBlizPanel(widget, event) - local appName = widget:GetUserData("appName") - AceConfigDialog.frame.closing[appName] = true - AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate) + widget:ReleaseChildren() end ---- Add an option table into the Blizzard Interface Options panel. --- You can optionally supply a descriptive name to use and a parent frame to use, --- as well as a path in the options table.\\ --- If no name is specified, the appName will be used instead. --- --- If you specify a proper `parent` (by name), the interface options will generate a --- tree layout. Note that only one level of children is supported, so the parent always --- has to be a head-level note. --- --- This function returns a reference to the container frame registered with the Interface --- Options. You can use this reference to open the options with the API function --- `InterfaceOptionsFrame_OpenToCategory`. --- @param appName The application name as given to `:RegisterOptionsTable()` --- @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. -function AceConfigDialog:AddToBlizOptions(appName, name, parent, ...) - local BlizOptions = AceConfigDialog.BlizOptions +function lib:AddToBlizOptions(appName, name, parent, ...) + local BlizOptions = lib.BlizOptions local key = appName - for n = 1, select("#", ...) do - key = key.."\001"..select(n, ...) + 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 + if not BlizOptions[key] then local group = gui:Create("BlizOptionsGroup") - BlizOptions[appName][key] = group + BlizOptions[key] = group group:SetName(name or appName, parent) group:SetTitle(name or appName) - group:SetUserData("appName", appName) - if select("#", ...) > 0 then + group:SetUserData('appName', appName) + if select('#', ...) > 0 then local path = {} - for n = 1, select("#",...) do + for n = 1, select('#',...) do tinsert(path, (select(n, ...))) end - group:SetUserData("path", path) + group:SetUserData('path', path) end group:SetCallback("OnShow", FeedToBlizPanel) group:SetCallback("OnHide", ClearBlizPanel) diff --git a/lib/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua b/lib/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua index d98c020..3d41dc9 100644 --- a/lib/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua +++ b/lib/AceConfig-3.0/AceConfigRegistry-3.0/AceConfigRegistry-3.0.lua @@ -1,38 +1,34 @@ ---- AceConfigRegistry-3.0 handles central registration of options tables in use by addons and modules.\\ --- Options tables can be registered as raw tables, OR as function refs that return a table.\\ --- Such functions receive three arguments: "uiType", "uiName", "appName". \\ --- * Valid **uiTypes**: "cmd", "dropdown", "dialog". This is verified by the library at call time. \\ --- * The **uiName** field is expected to contain the full name of the calling addon, including version, e.g. "FooBar-1.0". This is verified by the library at call time.\\ --- * The **appName** field is the options table name as given at registration time \\ --- --- :IterateOptionsTables() (and :GetOptionsTable() if only given one argument) return a function reference that the requesting config handling addon must call with valid "uiType", "uiName". --- @class file --- @name AceConfigRegistry-3.0 --- @release $Id: AceConfigRegistry-3.0.lua 921 2010-05-09 15:49:14Z nevcairiel $ -local MAJOR, MINOR = "AceConfigRegistry-3.0", 12 -local AceConfigRegistry = LibStub:NewLibrary(MAJOR, MINOR) +--[[ +AceConfigRegistry-3.0: -if not AceConfigRegistry then return end +Handle central registration of options tables in use by addons and modules. Do nothing else. -AceConfigRegistry.tables = AceConfigRegistry.tables or {} +Options tables can be registered as raw tables, or as function refs that return a table. +These functions receive two arguments: "uiType" and "uiName". +- Valid "uiTypes": "cmd", "dropdown", "dialog". This is verified by the library at call time. +- The "uiName" field is expected to contain the full name of the calling addon, including version, e.g. "FooBar-1.0". This is verified by the library at call time. + +:IterateOptionsTables() and :GetOptionsTable() always return a function reference that the requesting config handling addon must call with the above arguments. +]] + +local MAJOR, MINOR = "AceConfigRegistry-3.0", 6 +local lib = LibStub:NewLibrary(MAJOR, MINOR) + +if not lib then return end + +lib.tables = lib.tables or {} local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0") -if not AceConfigRegistry.callbacks then - AceConfigRegistry.callbacks = CallbackHandler:New(AceConfigRegistry) +if not lib.callbacks then + lib.callbacks = CallbackHandler:New(lib) end --- Lua APIs -local tinsert, tconcat = table.insert, table.concat -local strfind, strmatch = string.find, string.match -local type, tostring, select, pairs = type, tostring, select, pairs -local error, assert = error, assert - ----------------------------------------------------------------------- -- Validating options table consistency: -AceConfigRegistry.validated = { +lib.validated = { -- list of options table names ran through :ValidateOptionsTable automatically. -- CLEARED ON PURPOSE, since newer versions may have newer validators cmd = {}, @@ -47,7 +43,7 @@ local function err(msg, errlvl, ...) for i=select("#",...),1,-1 do tinsert(t, (select(i, ...))) end - error(MAJOR..":ValidateOptionsTable(): "..tconcat(t,".")..msg, errlvl+2) + error(MAJOR..":ValidateOptionsTable(): "..table.concat(t,".")..msg, errlvl+2) end @@ -71,7 +67,6 @@ local basekeys={ type=isstring, name=isstringfunc, desc=optstringfunc, - descStyle=optstring, order=optmethodnumber, validate=optmethodfalse, confirm=optmethodbool, @@ -99,7 +94,6 @@ local typedkeys={ imageCoords=optmethodtable, imageHeight=optnumber, imageWidth=optnumber, - fontSize=optstringfunc, }, group={ args=istable, @@ -112,10 +106,11 @@ local typedkeys={ childGroups=optstring, }, execute={ - image=optstringfunc, - imageCoords=optmethodtable, - imageHeight=optnumber, - imageWidth=optnumber, +-- func={ +-- ["function"]=true, +-- ["string"]=true, +-- _="methodname or funcref" +-- }, }, input={ pattern=optstring, @@ -127,16 +122,12 @@ local typedkeys={ }, toggle={ tristate=optbool, - image=optstringfunc, - imageCoords=optmethodtable, }, tristate={ }, range={ min=optnumber, - softMin=optnumber, max=optnumber, - softMax=optnumber, step=optnumber, bigStep=optnumber, isPercent=optbool, @@ -173,8 +164,8 @@ local function validateKey(k,errlvl,...) if type(k)~="string" then err("["..tostring(k).."] - key is not a string", errlvl,...) end - if strfind(k, "[%c\127]") then - err("["..tostring(k).."] - key name contained control characters", errlvl,...) + if strfind(k, "[%c \127]") then + err("["..tostring(k).."] - key name contained spaces (or control characters)", errlvl,...) end end @@ -243,13 +234,16 @@ local function validate(options,errlvl,...) end end - ---- Validates basic structure and integrity of an options table \\ +--------------------------------------------------------------------- +-- :ValidateOptionsTable(options,name,errlvl) +-- - options - the table +-- - name - (string) name of table, used in error reports +-- - errlvl - (optional number) error level offset, default 0 +-- +-- Validates basic structure and integrity of an options table -- Does NOT verify that get/set etc actually exist, since they can be defined at any depth --- @param options The table to be validated --- @param name The name of the table to be validated (shown in any error message) --- @param errlvl (optional number) error level offset, default 0 (=errors point to the function calling :ValidateOptionsTable) -function AceConfigRegistry:ValidateOptionsTable(options,name,errlvl) + +function lib:ValidateOptionsTable(options,name,errlvl) errlvl=(errlvl or 0)+1 name = name or "Optionstable" if not options.name then @@ -258,16 +252,19 @@ function AceConfigRegistry:ValidateOptionsTable(options,name,errlvl) validate(options,errlvl,name) end ---- Fires a "ConfigTableChange" callback for those listening in on it, allowing config GUIs to refresh. --- You should call this function if your options table changed from any outside event, like a game event --- or a timer. --- @param appName The application name as given to `:RegisterOptionsTable()` -function AceConfigRegistry:NotifyChange(appName) - if not AceConfigRegistry.tables[appName] then return end - AceConfigRegistry.callbacks:Fire("ConfigTableChange", appName) +------------------------------ +-- :NotifyChange(appName) +-- - appName - string identifying the addon +-- +-- Fires a ConfigTableChange callback for those listening in on it, allowing config GUIs to refresh +------------------------------ + +function lib:NotifyChange(appName) + if not lib.tables[appName] then return end + lib.callbacks:Fire("ConfigTableChange", appName) end --- ------------------------------------------------------------------- +--------------------------------------------------------------------- -- Registering and retreiving options tables: @@ -283,32 +280,34 @@ local function validateGetterArgs(uiType, uiName, errlvl) end end ---- Register an options table with the config registry. --- @param appName The application name as given to `:RegisterOptionsTable()` --- @param options The options table, OR a function reference that generates it on demand. \\ --- See the top of the page for info on arguments passed to such functions. -function AceConfigRegistry:RegisterOptionsTable(appName, options) + +--------------------------------------------------------------------- +-- :RegisterOptionsTable(appName, options) +-- - appName - string identifying the addon +-- - options - table or function reference + +function lib:RegisterOptionsTable(appName, options) if type(options)=="table" then if options.type~="group" then -- quick sanity checker error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - missing type='group' member in root group", 2) end - AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl) + lib.tables[appName] = function(uiType, uiName, errlvl) errlvl=(errlvl or 0)+1 validateGetterArgs(uiType, uiName, errlvl) - if not AceConfigRegistry.validated[uiType][appName] then - AceConfigRegistry:ValidateOptionsTable(options, appName, errlvl) -- upgradable - AceConfigRegistry.validated[uiType][appName] = true + if not lib.validated[uiType][appName] then + lib:ValidateOptionsTable(options, appName, errlvl) -- upgradable + lib.validated[uiType][appName] = true end return options end elseif type(options)=="function" then - AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl) + lib.tables[appName] = function(uiType, uiName, errlvl) errlvl=(errlvl or 0)+1 validateGetterArgs(uiType, uiName, errlvl) - local tab = assert(options(uiType, uiName, appName)) - if not AceConfigRegistry.validated[uiType][appName] then - AceConfigRegistry:ValidateOptionsTable(tab, appName, errlvl) -- upgradable - AceConfigRegistry.validated[uiType][appName] = true + local tab = assert(options(uiType, uiName)) + if not lib.validated[uiType][appName] then + lib:ValidateOptionsTable(tab, appName, errlvl) -- upgradable + lib.validated[uiType][appName] = true end return tab end @@ -317,23 +316,30 @@ function AceConfigRegistry:RegisterOptionsTable(appName, options) end end ---- Returns an iterator of ["appName"]=funcref pairs -function AceConfigRegistry:IterateOptionsTables() - return pairs(AceConfigRegistry.tables) + +--------------------------------------------------------------------- +-- :IterateOptionsTables() +-- +-- Returns an iterator of ["appName"]=funcref pairs + +function lib:IterateOptionsTables() + return pairs(lib.tables) end - - ---- Query the registry for a specific options table. +--------------------------------------------------------------------- +-- :GetOptionsTable(appName) +-- - appName - which addon to retreive the options table of +-- Optional: +-- - uiType - "cmd", "dropdown", "dialog" +-- - uiName - e.g. "MyLib-1.0" +-- -- If only appName is given, a function is returned which you --- can call with (uiType,uiName) to get the table.\\ +-- can call with (uiType,uiName) to get the table. -- If uiType&uiName are given, the table is returned. --- @param appName The application name as given to `:RegisterOptionsTable()` --- @param uiType The type of UI to get the table for, one of "cmd", "dropdown", "dialog" --- @param uiName The name of the library/addon querying for the table, e.g. "MyLib-1.0" -function AceConfigRegistry:GetOptionsTable(appName, uiType, uiName) - local f = AceConfigRegistry.tables[appName] + +function lib:GetOptionsTable(appName, uiType, uiName) + local f = lib.tables[appName] if not f then return nil end diff --git a/lib/AceGUI-3.0/AceGUI-3.0.lua b/lib/AceGUI-3.0/AceGUI-3.0.lua index 53295bb..89a4e16 100644 --- a/lib/AceGUI-3.0/AceGUI-3.0.lua +++ b/lib/AceGUI-3.0/AceGUI-3.0.lua @@ -1,49 +1,9 @@ ---- **AceGUI-3.0** provides access to numerous widgets which can be used to create GUIs. --- AceGUI is used by AceConfigDialog to create the option GUIs, but you can use it by itself --- to create any custom GUI. There are more extensive examples in the test suite in the Ace3 --- stand-alone distribution. --- --- **Note**: When using AceGUI-3.0 directly, please do not modify the frames of the widgets directly, --- as any "unknown" change to the widgets will cause addons that get your widget out of the widget pool --- to misbehave. If you think some part of a widget should be modifiable, please open a ticket, and we"ll --- implement a proper API to modify it. --- @usage --- local AceGUI = LibStub("AceGUI-3.0") --- -- Create a container frame --- local f = AceGUI:Create("Frame") --- f:SetCallback("OnClose",function(widget) AceGUI:Release(widget) end) --- f:SetTitle("AceGUI-3.0 Example") --- f:SetStatusText("Status Bar") --- f:SetLayout("Flow") --- -- Create a button --- local btn = AceGUI:Create("Button") --- btn:SetWidth(170) --- btn:SetText("Button !") --- btn:SetCallback("OnClick", function() print("Click!") end) --- -- Add the button to the container --- f:AddChild(btn) --- @class file --- @name AceGUI-3.0 --- @release $Id: AceGUI-3.0.lua 924 2010-05-13 15:12:20Z nevcairiel $ -local ACEGUI_MAJOR, ACEGUI_MINOR = "AceGUI-3.0", 33 +--[[ $Id: AceGUI-3.0.lua 81438 2008-09-06 13:44:36Z nevcairiel $ ]] +local ACEGUI_MAJOR, ACEGUI_MINOR = "AceGUI-3.0", 16 local AceGUI, oldminor = LibStub:NewLibrary(ACEGUI_MAJOR, ACEGUI_MINOR) if not AceGUI then return end -- No upgrade needed --- Lua APIs -local tconcat, tremove, tinsert = table.concat, table.remove, table.insert -local select, pairs, next, type = select, pairs, next, type -local error, assert, loadstring = error, assert, loadstring -local setmetatable, rawget, rawset = setmetatable, rawget, rawset -local math_max = math.max - --- WoW APIs -local UIParent = UIParent - --- Global vars/functions that we don't upvalue since they might get hooked, or upgraded --- List them here for Mikk's FindGlobals script --- GLOBALS: geterrorhandler, LibStub - --local con = LibStub("AceConsole-3.0",true) AceGUI.WidgetRegistry = AceGUI.WidgetRegistry or {} @@ -57,6 +17,17 @@ local WidgetRegistry = AceGUI.WidgetRegistry local LayoutRegistry = AceGUI.LayoutRegistry local WidgetVersions = AceGUI.WidgetVersions +local pcall = pcall +local select = select +local pairs = pairs +local ipairs = ipairs +local type = type +local assert = assert +local tinsert = tinsert +local tremove = tremove +local CreateFrame = CreateFrame +local UIParent = UIParent + --[[ xpcall safecall implementation ]] @@ -84,7 +55,7 @@ local function CreateDispatcher(argCount) local ARGS = {} for i = 1, argCount do ARGS[i] = "arg"..i end - code = code:gsub("ARGS", tconcat(ARGS, ", ")) + code = code:gsub("ARGS", table.concat(ARGS, ", ")) return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler) end @@ -98,62 +69,43 @@ Dispatchers[0] = function(func) end local function safecall(func, ...) - return Dispatchers[select("#", ...)](func, ...) + return Dispatchers[select('#', ...)](func, ...) end -- Recycling functions -local newWidget, delWidget +local new, del do - -- Version Upgrade in Minor 29 - -- Internal Storage of the objects changed, from an array table - -- to a hash table, and additionally we introduced versioning on - -- the widgets which would discard all widgets from a pre-29 version - -- anyway, so we just clear the storage now, and don't try to - -- convert the storage tables to the new format. - -- This should generally not cause *many* widgets to end up in trash, - -- since once dialogs are opened, all addons should be loaded already - -- and AceGUI should be on the latest version available on the users - -- setup. - -- -- nevcairiel - Nov 2nd, 2009 - if oldminor and oldminor < 29 and AceGUI.objPools then - AceGUI.objPools = nil - end - AceGUI.objPools = AceGUI.objPools or {} local objPools = AceGUI.objPools --Returns a new instance, if none are available either returns a new table or calls the given contructor - function newWidget(type) - if not WidgetRegistry[type] then - error("Attempt to instantiate unknown widget type", 2) + function new(type,constructor,...) + if not type then + type = "table" end - if not objPools[type] then objPools[type] = {} end - - local newObj = next(objPools[type]) + local newObj = tremove(objPools[type]) if not newObj then - newObj = WidgetRegistry[type]() - newObj.AceGUIWidgetVersion = WidgetVersions[type] - else - objPools[type][newObj] = nil - -- if the widget is older then the latest, don't even try to reuse it - -- just forget about it, and grab a new one. - if not newObj.AceGUIWidgetVersion or newObj.AceGUIWidgetVersion < WidgetVersions[type] then - return newWidget(type) - end + newObj = constructor and constructor(...) or {} end return newObj end -- Releases an instance to the Pool - function delWidget(obj,type) + function del(obj,type) + if not type then + type = "table" + end if not objPools[type] then objPools[type] = {} end - if objPools[type][obj] then - error("Attempt to Release Widget that is already released", 2) + for i,v in ipairs(objPools[type]) do + if v == obj then + error("Attempt to Release Widget that is already released") + return + end end - objPools[type][obj] = true + tinsert(objPools[type],obj) end end @@ -164,25 +116,21 @@ end -- Gets a widget Object ---- Create a new Widget of the given type. --- This function will instantiate a new widget (or use one from the widget pool), and call the --- OnAcquire function on it, before returning. --- @param type The type of the widget. --- @return The newly created widget. function AceGUI:Create(type) - if WidgetRegistry[type] then - local widget = newWidget(type) + local reg = WidgetRegistry + if reg[type] then + local widget = new(type,reg[type]) - if rawget(widget, "Acquire") then + if rawget(widget,'Acquire') then widget.OnAcquire = widget.Acquire widget.Acquire = nil - elseif rawget(widget, "Aquire") then + elseif rawget(widget,'Aquire') then widget.OnAcquire = widget.Aquire widget.Aquire = nil end - if rawget(widget, "Release") then - widget.OnRelease = rawget(widget, "Release") + if rawget(widget,'Release') then + widget.OnRelease = rawget(widget,'Release') widget.Release = nil end @@ -190,28 +138,22 @@ function AceGUI:Create(type) widget:OnAcquire() else error(("Widget type %s doesn't supply an OnAcquire Function"):format(type)) - end - -- Set the default Layout ("List") - safecall(widget.SetLayout, widget, "List") + end safecall(widget.ResumeLayout, widget) return widget end end ---- Releases a widget Object. --- This function calls OnRelease on the widget and places it back in the widget pool. --- Any data on the widget is being erased, and the widget will be hidden.\\ --- If this widget is a Container-Widget, all of its Child-Widgets will be releases as well. --- @param widget The widget to release +-- Releases a widget Object function AceGUI:Release(widget) - safecall(widget.PauseLayout, widget) + safecall( widget.PauseLayout, widget ) widget:Fire("OnRelease") - safecall(widget.ReleaseChildren, widget) + safecall( widget.ReleaseChildren, widget ) if widget.OnRelease then widget:OnRelease() --- else --- error(("Widget type %s doesn't supply an OnRelease Function"):format(widget.type)) + else + error(("Widget type %s doesn't supply an OnRelease Function"):format(type)) end for k in pairs(widget.userdata) do widget.userdata[k] = nil @@ -219,31 +161,26 @@ function AceGUI:Release(widget) for k in pairs(widget.events) do widget.events[k] = nil end - widget.width = nil - widget.relWidth = nil - widget.height = nil - widget.relHeight = nil - widget.noAutoHeight = nil + widget.width = nil + --widget.frame:SetParent(nil) widget.frame:ClearAllPoints() widget.frame:Hide() - widget.frame:SetParent(UIParent) - widget.frame.width = nil - widget.frame.height = nil + widget.frame:SetParent(nil) if widget.content then widget.content.width = nil widget.content.height = nil end - delWidget(widget, widget.type) + del(widget,widget.type) end ----------- -- Focus -- ----------- - ---- Called when a widget has taken focus. +----- +-- Called when a widget has taken focus -- e.g. Dropdowns opening, Editboxes gaining kb focus --- @param widget The widget that should be focused +----- function AceGUI:SetFocus(widget) if self.FocusedWidget and self.FocusedWidget ~= widget then safecall(self.FocusedWidget.ClearFocus, self.FocusedWidget) @@ -251,9 +188,10 @@ function AceGUI:SetFocus(widget) self.FocusedWidget = widget end - ---- Called when something has happened that could cause widgets with focus to drop it +----- +-- Called when something has happened that could cause widgets with focus to drop it -- e.g. titlebar of a frame being clicked +----- function AceGUI:ClearFocus() if self.FocusedWidget then safecall(self.FocusedWidget.ClearFocus, self.FocusedWidget) @@ -267,6 +205,7 @@ end --[[ Widgets must provide the following functions OnAcquire() - Called when the object is acquired, should set everything to a default hidden state + OnRelease() - Called when the object is Released, should remove any anchors and hide the Widget And the following members frame - the frame or derivitive object that will be treated as the widget for size and anchoring purposes @@ -280,12 +219,11 @@ end content - frame or derivitive that children will be anchored to The Widget can supply the following Optional Members - :OnRelease() - Called when the object is Released, should remove any additional anchors and clear any data :OnWidthSet(width) - Called when the width of the widget is changed :OnHeightSet(height) - Called when the height of the widget is changed Widgets should not use the OnSizeChanged events of thier frame or content members, use these methods instead AceGUI already sets a handler to the event - :LayoutFinished(width, height) - called after a layout has finished, the width and height will be the width and height of the + :OnLayoutFinished(width, height) - called after a layout has finished, the width and height will be the width and height of the area used for controls. These can be nil if the layout used the existing size to layout the controls. ]] @@ -294,6 +232,17 @@ end -- Widget Base Template -- -------------------------- do + local function fixlevels(parent,...) + local i = 1 + local child = select(i, ...) + while child do + child:SetFrameLevel(parent:GetFrameLevel()+1) + fixlevels(child, child:GetChildren()) + i = i + 1 + child = select(i, ...) + end + end + local WidgetBase = AceGUI.WidgetBase WidgetBase.SetParent = function(self, parent) @@ -301,6 +250,7 @@ do frame:SetParent(nil) frame:SetParent(parent.content) self.parent = parent + fixlevels(parent.frame,parent.frame:GetChildren()) end WidgetBase.SetCallback = function(self, name, func) @@ -326,14 +276,6 @@ do end end - WidgetBase.SetRelativeWidth = function(self, width) - if width <= 0 or width > 1 then - error(":SetRelativeWidth(width): Invalid relative width.", 2) - end - self.relWidth = width - self.width = "relative" - end - WidgetBase.SetHeight = function(self, height) self.frame:SetHeight(height) self.frame.height = height @@ -341,14 +283,6 @@ do self:OnHeightSet(height) end end - - --[[ WidgetBase.SetRelativeHeight = function(self, height) - if height <= 0 or height > 1 then - error(":SetRelativeHeight(height): Invalid relative height.", 2) - end - self.relHeight = height - self.height = "relative" - end ]] WidgetBase.IsVisible = function(self) return self.frame:IsVisible() @@ -433,7 +367,7 @@ do if self.LayoutPaused then return end - safecall(self.LayoutFunc, self.content, self.children) + safecall(self.LayoutFunc,self.content, self.children) end --call this function to layout, makes sure layed out objects get a frame to get sizes etc @@ -444,37 +378,16 @@ do -- end end - WidgetContainerBase.AddChild = function(self, child, beforeWidget) - if beforeWidget then - local siblingIndex = 1 - for _, widget in pairs(self.children) do - if widget == beforeWidget then - break - end - siblingIndex = siblingIndex + 1 - end - tinsert(self.children, siblingIndex, child) - else - tinsert(self.children, child) - end + WidgetContainerBase.AddChild = function(self, child) + tinsert(self.children,child) child:SetParent(self) child.frame:Show() self:DoLayout() end - WidgetContainerBase.AddChildren = function(self, ...) - for i = 1, select("#", ...) do - local child = select(i, ...) - tinsert(self.children, child) - child:SetParent(self) - child.frame:Show() - end - self:DoLayout() - end - WidgetContainerBase.ReleaseChildren = function(self) local children = self.children - for i = 1,#children do + for i in ipairs(children) do AceGUI:Release(children[i]) children[i] = nil end @@ -484,14 +397,6 @@ do self.LayoutFunc = AceGUI:GetLayout(Layout) end - WidgetContainerBase.SetAutoAdjustHeight = function(self, adjust) - if adjust then - self.noAutoHeight = nil - else - self.noAutoHeight = true - end - end - local function FrameResize(this) local self = this.obj if this:GetWidth() and this:GetHeight() then @@ -512,12 +417,9 @@ do end end - setmetatable(WidgetContainerBase, {__index=WidgetBase}) + setmetatable(WidgetContainerBase,{__index=WidgetBase}) --One of these function should be called on each Widget Instance as part of its creation process - - --- Register a widget-class as a container for newly created widgets. - -- @param widget The widget class function AceGUI:RegisterAsContainer(widget) widget.children = {} widget.userdata = {} @@ -525,23 +427,19 @@ do widget.base = WidgetContainerBase widget.content.obj = widget widget.frame.obj = widget - widget.content:SetScript("OnSizeChanged", ContentResize) - widget.frame:SetScript("OnSizeChanged", FrameResize) - setmetatable(widget, {__index = WidgetContainerBase}) + widget.content:SetScript("OnSizeChanged",ContentResize) + widget.frame:SetScript("OnSizeChanged",FrameResize) + setmetatable(widget,{__index=WidgetContainerBase}) widget:SetLayout("List") - return widget end - --- Register a widget-class as a widget. - -- @param widget The widget class function AceGUI:RegisterAsWidget(widget) widget.userdata = {} widget.events = {} widget.base = WidgetBase widget.frame.obj = widget - widget.frame:SetScript("OnSizeChanged", FrameResize) - setmetatable(widget, {__index = WidgetBase}) - return widget + widget.frame:SetScript("OnSizeChanged",FrameResize) + setmetatable(widget,{__index=WidgetBase}) end end @@ -551,11 +449,7 @@ end ------------------ -- Widget API -- ------------------ - ---- Registers a widget Constructor, this function returns a new instance of the Widget --- @param Name The name of the widget --- @param Constructor The widget constructor function --- @param Version The version of the widget +-- Registers a widget Constructor, this function returns a new instance of the Widget function AceGUI:RegisterWidgetType(Name, Constructor, Version) assert(type(Constructor) == "function") assert(type(Version) == "number") @@ -567,9 +461,7 @@ function AceGUI:RegisterWidgetType(Name, Constructor, Version) WidgetRegistry[Name] = Constructor end ---- Registers a Layout Function --- @param Name The name of the layout --- @param LayoutFunc Reference to the layout function +-- Registers a Layout Function function AceGUI:RegisterLayout(Name, LayoutFunc) assert(type(LayoutFunc) == "function") if type(Name) == "string" then @@ -578,8 +470,6 @@ function AceGUI:RegisterLayout(Name, LayoutFunc) LayoutRegistry[Name] = LayoutFunc end ---- Get a Layout Function from the registry --- @param Name The name of the layout function AceGUI:GetLayout(Name) if type(Name) == "string" then Name = Name:upper() @@ -589,10 +479,6 @@ end AceGUI.counts = AceGUI.counts or {} ---- A type-based counter to count the number of widgets created. --- This is used by widgets that require a named frame, e.g. when a Blizzard --- Template requires it. --- @param type The widget type function AceGUI:GetNextWidgetNum(type) if not self.counts[type] then self.counts[type] = 0 @@ -601,18 +487,49 @@ function AceGUI:GetNextWidgetNum(type) return self.counts[type] end ---- Return the number of created widgets for this type. --- In contrast to GetNextWidgetNum, the number is not incremented. --- @param type The widget type -function AceGUI:GetWidgetCount(type) - return self.counts[type] or 0 +--[[ Widget Template + +-------------------------- +-- Widget Name -- +-------------------------- +do + local Type = "Type" + + local function OnAcquire(self) + + end + + local function OnRelease(self) + self.frame:ClearAllPoints() + self.frame:Hide() + end + + + local function Constructor() + local frame = CreateFrame("Frame",nil,UIParent) + local self = {} + self.type = Type + + self.OnRelease = OnRelease + self.OnAcquire = OnAcquire + + self.frame = frame + frame.obj = self + + --Container Support + --local content = CreateFrame("Frame",nil,frame) + --self.content = content + + --AceGUI:RegisterAsContainer(self) + AceGUI:RegisterAsWidget(self) + return self + end + + AceGUI:RegisterWidgetType(Type,Constructor) end ---- Return the version of the currently registered widget type. --- @param type The widget type -function AceGUI:GetWidgetVersion(type) - return WidgetVersions[type] -end + +]] ------------- -- Layouts -- @@ -622,35 +539,33 @@ end A Layout is a func that takes 2 parameters content - the frame that widgets will be placed inside children - a table containing the widgets to layout + ]] -- Very simple Layout, Children are stacked on top of each other down the left side AceGUI:RegisterLayout("List", - function(content, children) - local height = 0 - local width = content.width or content:GetWidth() or 0 - for i = 1, #children do - local child = children[i] + function(content, children) + + local height = 0 + local width = content.width or content:GetWidth() or 0 + for i, child in ipairs(children) do + local frame = child.frame frame:ClearAllPoints() frame:Show() if i == 1 then - frame:SetPoint("TOPLEFT", content) + frame:SetPoint("TOPLEFT",content,"TOPLEFT",0,0) else - frame:SetPoint("TOPLEFT", children[i-1].frame, "BOTTOMLEFT") + frame:SetPoint("TOPLEFT",children[i-1].frame,"BOTTOMLEFT",0,0) end if child.width == "fill" then child:SetWidth(width) - frame:SetPoint("RIGHT", content) - - if child.DoLayout then - child:DoLayout() + frame:SetPoint("RIGHT",content,"RIGHT") + if child.OnWidthSet then + child:OnWidthSet(content.width or content:GetWidth()) end - elseif child.width == "relative" then - child:SetWidth(width * child.relWidth) - if child.DoLayout then child:DoLayout() end @@ -658,66 +573,58 @@ AceGUI:RegisterLayout("List", height = height + (frame.height or frame:GetHeight() or 0) end - safecall(content.obj.LayoutFinished, content.obj, nil, height) - end) - + safecall( content.obj.LayoutFinished, content.obj, nil, height ) + end + ) + -- A single control fills the whole content area AceGUI:RegisterLayout("Fill", - function(content, children) + function(content, children) if children[1] then children[1]:SetWidth(content:GetWidth() or 0) children[1]:SetHeight(content:GetHeight() or 0) children[1].frame:SetAllPoints(content) children[1].frame:Show() - safecall(content.obj.LayoutFinished, content.obj, nil, children[1].frame:GetHeight()) + safecall( content.obj.LayoutFinished, content.obj, nil, children[1].frame:GetHeight() ) end - end) - + end + ) + AceGUI:RegisterLayout("Flow", - function(content, children) - --used height so far - local height = 0 - --width used in the current row - local usedwidth = 0 - --height of the current row - local rowheight = 0 - local rowoffset = 0 - local lastrowoffset - - local width = content.width or content:GetWidth() or 0 - - --control at the start of the row - local rowstart + function(content, children) + --used height so far + local height = 0 + --width used in the current row + local usedwidth = 0 + --height of the current row + local rowheight = 0 + local rowoffset = 0 + local lastrowoffset + + local width = content.width or content:GetWidth() or 0 + + --control at the start of the row + local rowstart local rowstartoffset - local lastrowstart - local isfullheight - - local frameoffset - local lastframeoffset - local oversize - for i = 1, #children do - local child = children[i] + local lastrowstart + local isfullheight + + local frameoffset + local lastframeoffset + local oversize + for i, child in ipairs(children) do oversize = nil local frame = child.frame local frameheight = frame.height or frame:GetHeight() or 0 local framewidth = frame.width or frame:GetWidth() or 0 lastframeoffset = frameoffset - -- HACK: Why did we set a frameoffset of (frameheight / 2) ? - -- That was moving all widgets half the widgets size down, is that intended? - -- Actually, it seems to be neccessary for many cases, we'll leave it in for now. - -- If widgets seem to anchor weirdly with this, provide a valid alignoffset for them. - -- TODO: Investigate moar! frameoffset = child.alignoffset or (frameheight / 2) - if child.width == "relative" then - framewidth = width * child.relWidth - end - frame:Show() frame:ClearAllPoints() if i == 1 then -- anchor the first control to the top left - frame:SetPoint("TOPLEFT", content) + --frame:SetPoint("TOPLEFT",content,"TOPLEFT",0,0) rowheight = frameheight rowoffset = frameoffset rowstart = frame @@ -730,20 +637,15 @@ AceGUI:RegisterLayout("Flow", -- if there isn't available width for the control start a new row -- if a control is "fill" it will be on a row of its own full width if usedwidth == 0 or ((framewidth) + usedwidth > width) or child.width == "fill" then - if isfullheight then - -- a previous row has already filled the entire height, there's nothing we can usefully do anymore - -- (maybe error/warn about this?) - break - end --anchor the previous row, we will now know its height and offset - rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(height + (rowoffset - rowstartoffset) + 3)) + rowstart:SetPoint("TOPLEFT",content,"TOPLEFT",0,-(height+(rowoffset-rowstartoffset)+3)) height = height + rowheight + 3 --save this as the rowstart so we can anchor it after the row is complete and we have the max height and offset of controls in it rowstart = frame rowstartoffset = frameoffset rowheight = frameheight rowoffset = frameoffset - usedwidth = framewidth + usedwidth = frame.width or frame:GetWidth() if usedwidth > width then oversize = true end @@ -753,17 +655,17 @@ AceGUI:RegisterLayout("Flow", --math.max(rowheight-rowoffset+frameoffset, frameheight-frameoffset+rowoffset) --offset is always the larger of the two offsets - rowoffset = math_max(rowoffset, frameoffset) - rowheight = math_max(rowheight, rowoffset + (frameheight / 2)) + rowoffset = math.max(rowoffset, frameoffset) - frame:SetPoint("TOPLEFT", children[i-1].frame, "TOPRIGHT", 0, frameoffset - lastframeoffset) + rowheight = math.max(rowheight,rowoffset+(frameheight/2)) + frame:SetPoint("TOPLEFT",children[i-1].frame,"TOPRIGHT",0,frameoffset-lastframeoffset) usedwidth = framewidth + usedwidth end end if child.width == "fill" then child:SetWidth(width) - frame:SetPoint("RIGHT", content) + frame:SetPoint("RIGHT",content,"RIGHT",0,0) usedwidth = 0 rowstart = frame @@ -775,31 +677,27 @@ AceGUI:RegisterLayout("Flow", rowheight = frame.height or frame:GetHeight() or 0 rowoffset = child.alignoffset or (rowheight / 2) rowstartoffset = rowoffset - elseif child.width == "relative" then - child:SetWidth(width * child.relWidth) - - if child.DoLayout then - child:DoLayout() - end elseif oversize then if width > 1 then - frame:SetPoint("RIGHT", content) + frame:SetPoint("RIGHT",content,"RIGHT",0,0) end end if child.height == "fill" then - frame:SetPoint("BOTTOM", content) + frame:SetPoint("BOTTOM",content,"BOTTOM") isfullheight = true + break end end --anchor the last row, if its full height needs a special case since its height has just been changed by the anchor if isfullheight then - rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -height) + rowstart:SetPoint("TOPLEFT",content,"TOPLEFT",0,-height) elseif rowstart then - rowstart:SetPoint("TOPLEFT", content, "TOPLEFT", 0, -(height + (rowoffset - rowstartoffset) + 3)) + rowstart:SetPoint("TOPLEFT",content,"TOPLEFT",0,-(height+(rowoffset-rowstartoffset)+3)) end height = height + rowheight + 3 - safecall(content.obj.LayoutFinished, content.obj, nil, height) - end) + safecall( content.obj.LayoutFinished, content.obj, nil, height ) + end + ) diff --git a/lib/AceGUI-3.0/AceGUI-3.0.xml b/lib/AceGUI-3.0/AceGUI-3.0.xml index b515077..b5e2379 100644 --- a/lib/AceGUI-3.0/AceGUI-3.0.xml +++ b/lib/AceGUI-3.0/AceGUI-3.0.xml @@ -1,28 +1,24 @@