Version 0.2.2
- added Options UI under Interface Options - store settings in profiles - added more translations
This commit is contained in:
		
							
								
								
									
										58
									
								
								libs/AceConfig-3.0/AceConfig-3.0.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								libs/AceConfig-3.0/AceConfig-3.0.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| --- 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 1161 2017-08-12 14:30:16Z funkydude $ | ||||
|  | ||||
| --[[ | ||||
| AceConfig-3.0 | ||||
|  | ||||
| Very light wrapper library that combines all the AceConfig subcomponents into one more easily used whole. | ||||
|  | ||||
| ]] | ||||
|  | ||||
| local cfgreg = LibStub("AceConfigRegistry-3.0") | ||||
| local cfgcmd = LibStub("AceConfigCmd-3.0") | ||||
|  | ||||
| local MAJOR, MINOR = "AceConfig-3.0", 3 | ||||
| local AceConfig = LibStub:NewLibrary(MAJOR, MINOR) | ||||
|  | ||||
| if not AceConfig then return end | ||||
|  | ||||
| --TODO: local cfgdlg = LibStub("AceConfigDialog-3.0", true) | ||||
| --TODO: local cfgdrp = LibStub("AceConfigDropdown-3.0", true) | ||||
|  | ||||
| -- 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).  http://www.wowace.com/addons/ace3/pages/ace-config-3-0-options-tables/ | ||||
| -- @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) | ||||
| 	local ok,msg = pcall(cfgreg.RegisterOptionsTable, self, appName, options) | ||||
| 	if not ok then error(msg, 2) end | ||||
| 	 | ||||
| 	if slashcmd then | ||||
| 		if type(slashcmd) == "table" then | ||||
| 			for _,cmd in pairs(slashcmd) do | ||||
| 				cfgcmd:CreateChatCommand(cmd, appName) | ||||
| 			end | ||||
| 		else | ||||
| 			cfgcmd:CreateChatCommand(slashcmd, appName) | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
							
								
								
									
										8
									
								
								libs/AceConfig-3.0/AceConfig-3.0.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								libs/AceConfig-3.0/AceConfig-3.0.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ | ||||
| ..\FrameXML\UI.xsd"> | ||||
| 	<Include file="AceConfigRegistry-3.0\AceConfigRegistry-3.0.xml"/> | ||||
| 	<Include file="AceConfigCmd-3.0\AceConfigCmd-3.0.xml"/> | ||||
| 	<Include file="AceConfigDialog-3.0\AceConfigDialog-3.0.xml"/> | ||||
| 	<!--<Include file="AceConfigDropdown-3.0\AceConfigDropdown-3.0.xml"/>--> | ||||
| 	<Script file="AceConfig-3.0.lua"/> | ||||
| </Ui> | ||||
							
								
								
									
										794
									
								
								libs/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										794
									
								
								libs/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,794 @@ | ||||
| --- 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 1161 2017-08-12 14:30:16Z funkydude $ | ||||
|  | ||||
| --[[ | ||||
| AceConfigCmd-3.0 | ||||
|  | ||||
| Handles commandline optionstable access | ||||
|  | ||||
| REQUIRES: AceConsole-3.0 for command registration (loaded on demand) | ||||
|  | ||||
| ]] | ||||
|  | ||||
| -- TODO: plugin args | ||||
|  | ||||
| local cfgreg = LibStub("AceConfigRegistry-3.0") | ||||
|  | ||||
| local MAJOR, MINOR = "AceConfigCmd-3.0", 14 | ||||
| local AceConfigCmd = LibStub:NewLibrary(MAJOR, MINOR) | ||||
|  | ||||
| if not AceConfigCmd then return end | ||||
|  | ||||
| AceConfigCmd.commands = AceConfigCmd.commands or {} | ||||
| local commands = AceConfigCmd.commands | ||||
|  | ||||
| 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 | ||||
| }) | ||||
|  | ||||
|  | ||||
|  | ||||
| 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 | ||||
|  | ||||
| local function pickfirstset(...)	 | ||||
| 	for i=1,select("#",...) do | ||||
| 		if select(i,...)~=nil then | ||||
| 			return select(i,...) | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
|  | ||||
| -- err() - produce real error() regarding malformed options tables etc | ||||
|  | ||||
| local function err(info,inputpos,msg ) | ||||
| 	local cmdstr=" "..strsub(info.input, 1, inputpos-1) | ||||
| 	error(MAJOR..": /" ..info[0] ..cmdstr ..": "..(msg or "malformed options table"), 2) | ||||
| end | ||||
|  | ||||
|  | ||||
| -- usererr() - produce chatframe message regarding bad slash syntax etc | ||||
|  | ||||
| local function usererr(info,inputpos,msg ) | ||||
| 	local cmdstr=strsub(info.input, 1, inputpos-1); | ||||
| 	print("/" ..info[0] .. " "..cmdstr ..": "..(msg or "malformed options table")) | ||||
| end | ||||
|  | ||||
|  | ||||
| -- callmethod() - call a given named method (e.g. "get", "set") with given arguments | ||||
|  | ||||
| local function callmethod(info, inputpos, tab, methodtype, ...) | ||||
| 	local method = info[methodtype] | ||||
| 	if not method then | ||||
| 		err(info, inputpos, "'"..methodtype.."': not set") | ||||
| 	end | ||||
|  | ||||
| 	info.arg = tab.arg | ||||
| 	info.option = tab | ||||
| 	info.type = tab.type | ||||
|  | ||||
| 	if type(method)=="function" then | ||||
| 		return method(info, ...) | ||||
| 	elseif type(method)=="string" then | ||||
| 		if type(info.handler[method])~="function" then | ||||
| 			err(info, inputpos, "'"..methodtype.."': '"..method.."' is not a member function of "..tostring(info.handler)) | ||||
| 		end | ||||
| 		return info.handler[method](info.handler, info, ...) | ||||
| 	else | ||||
| 		assert(false)	-- type should have already been checked on read | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- callfunction() - call a given named function (e.g. "name", "desc") with given arguments | ||||
|  | ||||
| local function callfunction(info, tab, methodtype, ...) | ||||
| 	local method = tab[methodtype] | ||||
|  | ||||
| 	info.arg = tab.arg | ||||
| 	info.option = tab | ||||
| 	info.type = tab.type | ||||
| 	 | ||||
| 	if type(method)=="function" then | ||||
| 		return method(info, ...) | ||||
| 	else | ||||
| 		assert(false) -- type should have already been checked on read | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- do_final() - do the final step (set/execute) along with validation and confirmation | ||||
|  | ||||
| local function do_final(info, inputpos, tab, methodtype, ...) | ||||
| 	if info.validate then  | ||||
| 		local res = callmethod(info,inputpos,tab,"validate",...) | ||||
| 		if type(res)=="string" then | ||||
| 			usererr(info, inputpos, "'"..strsub(info.input, inputpos).."' - "..res) | ||||
| 			return | ||||
| 		end | ||||
| 	end | ||||
| 	-- console ignores .confirm | ||||
| 	 | ||||
| 	callmethod(info,inputpos,tab,methodtype, ...) | ||||
| end | ||||
|  | ||||
|  | ||||
| -- getparam() - used by handle() to retreive and store "handler", "get", "set", etc | ||||
|  | ||||
| local function getparam(info, inputpos, tab, depth, paramname, types, errormsg) | ||||
| 	local old,oldat = info[paramname], info[paramname.."_at"] | ||||
| 	local val=tab[paramname] | ||||
| 	if val~=nil then | ||||
| 		if val==false then | ||||
| 			val=nil | ||||
| 		elseif not types[type(val)] then  | ||||
| 			err(info, inputpos, "'" .. paramname.. "' - "..errormsg)  | ||||
| 		end | ||||
| 		info[paramname] = val | ||||
| 		info[paramname.."_at"] = depth | ||||
| 	end | ||||
| 	return old,oldat | ||||
| end | ||||
|  | ||||
|  | ||||
| -- iterateargs(tab) - custom iterator that iterates both t.args and t.plugins.* | ||||
| local dummytable={} | ||||
|  | ||||
| local function iterateargs(tab) | ||||
| 	if not tab.plugins then  | ||||
| 		return pairs(tab.args)  | ||||
| 	end | ||||
| 	 | ||||
| 	local argtabkey,argtab=next(tab.plugins) | ||||
| 	local v | ||||
| 	 | ||||
| 	return function(_, k) | ||||
| 		while argtab do | ||||
| 			k,v = next(argtab, k) | ||||
| 			if k then return k,v end | ||||
| 			if argtab==tab.args then | ||||
| 				argtab=nil | ||||
| 			else | ||||
| 				argtabkey,argtab = next(tab.plugins, argtabkey) | ||||
| 				if not argtabkey then | ||||
| 					argtab=tab.args | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| 	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) | ||||
| 	if not noHead then | ||||
| 		print("|cff33ff99"..info.appName.."|r: Arguments to |cffffff78/"..info[0].."|r "..strsub(info.input,1,inputpos-1)..":") | ||||
| 	end | ||||
| 	 | ||||
| 	local sortTbl = {}	-- [1..n]=name | ||||
| 	local refTbl = {}   -- [name]=tableref | ||||
| 	 | ||||
| 	for k,v in iterateargs(tab) do | ||||
| 		if not refTbl[k] then	-- a plugin overriding something in .args | ||||
| 			tinsert(sortTbl, k) | ||||
| 			refTbl[k] = v | ||||
| 		end | ||||
| 	end | ||||
| 	 | ||||
| 	tsort(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 | ||||
| 			info.order = o1 | ||||
| 			info[#info+1] = one | ||||
| 			o1 = callmethod(info, inputpos, refTbl[one], "order") | ||||
| 			info[#info] = nil | ||||
| 			info.order = nil | ||||
| 		end | ||||
| 		if type(o2) == "function" or type(o1) == "string" then | ||||
| 			info.order = o2 | ||||
| 			info[#info+1] = two | ||||
| 			o2 = callmethod(info, inputpos, refTbl[two], "order") | ||||
| 			info[#info] = nil | ||||
| 			info.order = nil | ||||
| 		end | ||||
| 		if o1<0 and o2<0 then return o1<o2 end | ||||
| 		if o2<0 then return true end | ||||
| 		if o1<0 then return false end | ||||
| 		if o1==o2 then return tostring(one)<tostring(two) end   -- compare names | ||||
| 		return o1<o2 | ||||
| 	end) | ||||
| 	 | ||||
| 	for i = 1, #sortTbl do | ||||
| 		local k = sortTbl[i] | ||||
| 		local v = refTbl[k] | ||||
| 		if not checkhidden(info, inputpos, v) then | ||||
| 			if v.type ~= "description" and v.type ~= "header" then | ||||
| 				-- recursively show all inline groups | ||||
| 				local name, desc = v.name, v.desc | ||||
| 				if type(name) == "function" then | ||||
| 					name = callfunction(info, v, 'name') | ||||
| 				end | ||||
| 				if type(desc) == "function" then | ||||
| 					desc = callfunction(info, v, 'desc') | ||||
| 				end | ||||
| 				if v.type == "group" and pickfirstset(v.cmdInline, v.inline, false) then | ||||
| 					print("  "..(desc or name)..":") | ||||
| 					local oldhandler,oldhandler_at = getparam(info, inputpos, v, depth, "handler", handlertypes, handlermsg) | ||||
| 					showhelp(info, inputpos, v, depth, true) | ||||
| 					info.handler,info.handler_at = oldhandler,oldhandler_at | ||||
| 				else | ||||
| 					local key = k:gsub(" ", "_") | ||||
| 					print("  |cffffff78"..key.."|r - "..(desc or name or "")) | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
|  | ||||
| local function keybindingValidateFunc(text) | ||||
| 	if text == nil or text == "NONE" then | ||||
| 		return nil | ||||
| 	end | ||||
| 	text = text:upper() | ||||
| 	local shift, ctrl, alt | ||||
| 	local modifier | ||||
| 	while true do | ||||
| 		if text == "-" then | ||||
| 			break | ||||
| 		end | ||||
| 		modifier, text = strsplit('-', text, 2) | ||||
| 		if text then | ||||
| 			if modifier ~= "SHIFT" and modifier ~= "CTRL" and modifier ~= "ALT" then | ||||
| 				return false | ||||
| 			end | ||||
| 			if modifier == "SHIFT" then | ||||
| 				if shift then | ||||
| 					return false | ||||
| 				end | ||||
| 				shift = true | ||||
| 			end | ||||
| 			if modifier == "CTRL" then | ||||
| 				if ctrl then | ||||
| 					return false | ||||
| 				end | ||||
| 				ctrl = true | ||||
| 			end | ||||
| 			if modifier == "ALT" then | ||||
| 				if alt then | ||||
| 					return false | ||||
| 				end | ||||
| 				alt = true | ||||
| 			end | ||||
| 		else | ||||
| 			text = modifier | ||||
| 			break | ||||
| 		end | ||||
| 	end | ||||
| 	if text == "" then | ||||
| 		return false | ||||
| 	end | ||||
| 	if not text:find("^F%d+$") and text ~= "CAPSLOCK" and text:len() ~= 1 and (text:byte() < 128 or text:len() > 4) and not _G["KEY_" .. text] then | ||||
| 		return false | ||||
| 	end | ||||
| 	local s = text | ||||
| 	if shift then | ||||
| 		s = "SHIFT-" .. s | ||||
| 	end | ||||
| 	if ctrl then | ||||
| 		s = "CTRL-" .. s | ||||
| 	end | ||||
| 	if alt then | ||||
| 		s = "ALT-" .. s | ||||
| 	end | ||||
| 	return s | ||||
| end | ||||
|  | ||||
| -- handle() - selfrecursing function that processes input->optiontable  | ||||
| -- - depth - starts at 0 | ||||
| -- - retfalse - return false rather than produce error if a match is not found (used by inlined groups) | ||||
|  | ||||
| local function handle(info, inputpos, tab, depth, retfalse) | ||||
|  | ||||
| 	if not(type(tab)=="table" and type(tab.type)=="string") then err(info,inputpos) end | ||||
|  | ||||
| 	------------------------------------------------------------------- | ||||
| 	-- Grab hold of handler,set,get,func,etc if set (and remember old ones) | ||||
| 	-- Note that we do NOT validate if method names are correct at this stage, | ||||
| 	-- the handler may change before they're actually used! | ||||
|  | ||||
| 	local oldhandler,oldhandler_at = getparam(info,inputpos,tab,depth,"handler",handlertypes,handlermsg) | ||||
| 	local oldset,oldset_at = getparam(info,inputpos,tab,depth,"set",functypes,funcmsg) | ||||
| 	local oldget,oldget_at = getparam(info,inputpos,tab,depth,"get",functypes,funcmsg) | ||||
| 	local oldfunc,oldfunc_at = getparam(info,inputpos,tab,depth,"func",functypes,funcmsg) | ||||
| 	local oldvalidate,oldvalidate_at = getparam(info,inputpos,tab,depth,"validate",functypes,funcmsg) | ||||
| 	--local oldconfirm,oldconfirm_at = getparam(info,inputpos,tab,depth,"confirm",functypes,funcmsg) | ||||
| 	 | ||||
| 	------------------------------------------------------------------- | ||||
| 	-- Act according to .type of this table | ||||
| 		 | ||||
| 	if tab.type=="group" then | ||||
| 		------------ group -------------------------------------------- | ||||
| 		 | ||||
| 		if type(tab.args)~="table" then err(info, inputpos) end | ||||
| 		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) | ||||
| 		if not arg then | ||||
| 			showhelp(info, inputpos, tab, depth) | ||||
| 			return | ||||
| 		end | ||||
| 		nextpos=nextpos+1 | ||||
| 		 | ||||
| 		-- loop .args and try to find a key with a matching name | ||||
| 		for k,v in iterateargs(tab) do | ||||
| 			if not(type(k)=="string" and type(v)=="table" and type(v.type)=="string") then err(info,inputpos, "options table child '"..tostring(k).."' is malformed") end | ||||
| 			 | ||||
| 			-- is this child an inline group? if so, traverse into it | ||||
| 			if v.type=="group" and pickfirstset(v.cmdInline, v.inline, false) then | ||||
| 				info[depth+1] = k | ||||
| 				if handle(info, inputpos, v, depth+1, true)==false then | ||||
| 					info[depth+1] = nil | ||||
| 					-- wasn't found in there, but that's ok, we just keep looking down here | ||||
| 				else | ||||
| 					return	-- done, name was found in inline group | ||||
| 				end | ||||
| 			-- matching name and not a inline group | ||||
| 			elseif strlower(arg)==strlower(k:gsub(" ", "_")) then | ||||
| 				info[depth+1] = k | ||||
| 				return handle(info,nextpos,v,depth+1) | ||||
| 			end | ||||
| 		end | ||||
| 			 | ||||
| 		-- no match  | ||||
| 		if retfalse then | ||||
| 			-- restore old infotable members and return false to indicate failure | ||||
| 			info.handler,info.handler_at = oldhandler,oldhandler_at | ||||
| 			info.set,info.set_at = oldset,oldset_at | ||||
| 			info.get,info.get_at = oldget,oldget_at | ||||
| 			info.func,info.func_at = oldfunc,oldfunc_at | ||||
| 			info.validate,info.validate_at = oldvalidate,oldvalidate_at | ||||
| 			--info.confirm,info.confirm_at = oldconfirm,oldconfirm_at | ||||
| 			return false | ||||
| 		end | ||||
| 		 | ||||
| 		-- couldn't find the command, display error | ||||
| 		usererr(info, inputpos, "'"..arg.."' - " .. L["unknown argument"]) | ||||
| 		return | ||||
| 	end | ||||
| 	 | ||||
| 	local str = strsub(info.input,inputpos); | ||||
| 	 | ||||
| 	if tab.type=="execute" then | ||||
| 		------------ execute -------------------------------------------- | ||||
| 		do_final(info, inputpos, tab, "func") | ||||
| 		 | ||||
|  | ||||
| 	 | ||||
| 	elseif tab.type=="input" then | ||||
| 		------------ input -------------------------------------------- | ||||
| 		 | ||||
| 		local res = true | ||||
| 		if tab.pattern then | ||||
| 			if not(type(tab.pattern)=="string") then err(info, inputpos, "'pattern' - expected a string") end | ||||
| 			if not strmatch(str, tab.pattern) then | ||||
| 				usererr(info, inputpos, "'"..str.."' - " .. L["invalid input"]) | ||||
| 				return | ||||
| 			end | ||||
| 		end | ||||
| 		 | ||||
| 		do_final(info, inputpos, tab, "set", str) | ||||
| 		 | ||||
|  | ||||
| 	 | ||||
| 	elseif tab.type=="toggle" then | ||||
| 		------------ toggle -------------------------------------------- | ||||
| 		local b | ||||
| 		local str = strtrim(strlower(str)) | ||||
| 		if str=="" then | ||||
| 			b = callmethod(info, inputpos, tab, "get") | ||||
|  | ||||
| 			if tab.tristate then | ||||
| 				--cycle in true, nil, false order | ||||
| 				if b then | ||||
| 					b = nil | ||||
| 				elseif b == nil then | ||||
| 					b = false | ||||
| 				else | ||||
| 					b = true | ||||
| 				end | ||||
| 			else | ||||
| 				b = not b | ||||
| 			end | ||||
| 			 | ||||
| 		elseif str==L["on"] then | ||||
| 			b = true | ||||
| 		elseif str==L["off"] then | ||||
| 			b = false | ||||
| 		elseif tab.tristate and str==L["default"] then | ||||
| 			b = nil | ||||
| 		else | ||||
| 			if tab.tristate then | ||||
| 				usererr(info, inputpos, format(L["'%s' - expected 'on', 'off' or 'default', or no argument to toggle."], str)) | ||||
| 			else | ||||
| 				usererr(info, inputpos, format(L["'%s' - expected 'on' or 'off', or no argument to toggle."], str)) | ||||
| 			end | ||||
| 			return | ||||
| 		end | ||||
| 		 | ||||
| 		do_final(info, inputpos, tab, "set", b) | ||||
| 		 | ||||
|  | ||||
| 	elseif tab.type=="range" then | ||||
| 		------------ range -------------------------------------------- | ||||
| 		local val = tonumber(str) | ||||
| 		if not val then | ||||
| 			usererr(info, inputpos, "'"..str.."' - "..L["expected number"]) | ||||
| 			return | ||||
| 		end | ||||
| 		if type(info.step)=="number" then | ||||
| 			val = val- (val % info.step) | ||||
| 		end | ||||
| 		if type(info.min)=="number" and val<info.min then | ||||
| 			usererr(info, inputpos, val.." - "..format(L["must be equal to or higher than %s"], tostring(info.min)) ) | ||||
| 			return | ||||
| 		end | ||||
| 		if type(info.max)=="number" and val>info.max then | ||||
| 			usererr(info, inputpos, val.." - "..format(L["must be equal to or lower than %s"], tostring(info.max)) ) | ||||
| 			return | ||||
| 		end | ||||
| 		 | ||||
| 		do_final(info, inputpos, tab, "set", val) | ||||
|  | ||||
| 	 | ||||
| 	elseif tab.type=="select" then | ||||
| 		------------ select ------------------------------------ | ||||
| 		local str = strtrim(strlower(str)) | ||||
| 		 | ||||
| 		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 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  | ||||
| 			if strlower(k)==str then | ||||
| 				str = k	-- overwrite with key (in case of case mismatches) | ||||
| 				ok = true | ||||
| 				break | ||||
| 			end | ||||
| 		end | ||||
| 		if not ok then | ||||
| 			usererr(info, inputpos, "'"..str.."' - "..L["unknown selection"]) | ||||
| 			return | ||||
| 		end | ||||
| 		 | ||||
| 		do_final(info, inputpos, tab, "set", str) | ||||
| 		 | ||||
| 	elseif tab.type=="multiselect" then | ||||
| 		------------ multiselect ------------------------------------------- | ||||
| 		local str = strtrim(strlower(str)) | ||||
| 		 | ||||
| 		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 | ||||
| 		 | ||||
| 		--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 | ||||
| 			--parse option=on etc | ||||
| 			local opt, val = v:match('(.+)=(.+)') | ||||
| 			--get option if toggling | ||||
| 			if not opt then  | ||||
| 				opt = v  | ||||
| 			end | ||||
| 			 | ||||
| 			--check that the opt is valid | ||||
| 			local ok | ||||
| 			for k,v in pairs(values) do  | ||||
| 				if strlower(k)==opt then | ||||
| 					opt = k	-- overwrite with key (in case of case mismatches) | ||||
| 					ok = true | ||||
| 					break | ||||
| 				end | ||||
| 			end | ||||
| 			 | ||||
| 			if not ok then | ||||
| 				usererr(info, inputpos, "'"..opt.."' - "..L["unknown selection"]) | ||||
| 				return | ||||
| 			end | ||||
| 			 | ||||
| 			--check that if val was supplied it is valid | ||||
| 			if val then | ||||
| 				if val == L["on"] or val == L["off"] or (tab.tristate and val == L["default"]) then | ||||
| 					--val is valid insert it | ||||
| 					sels[opt] = val | ||||
| 				else | ||||
| 					if tab.tristate then | ||||
| 						usererr(info, inputpos, format(L["'%s' '%s' - expected 'on', 'off' or 'default', or no argument to toggle."], v, val)) | ||||
| 					else | ||||
| 						usererr(info, inputpos, format(L["'%s' '%s' - expected 'on' or 'off', or no argument to toggle."], v, val)) | ||||
| 					end | ||||
| 					return | ||||
| 				end | ||||
| 			else | ||||
| 				-- no val supplied, toggle | ||||
| 				sels[opt] = true | ||||
| 			end | ||||
| 		end | ||||
| 		 | ||||
| 		for opt, val in pairs(sels) do | ||||
| 			local newval | ||||
| 			 | ||||
| 			if (val == true) then | ||||
| 				--toggle the option | ||||
| 				local b = callmethod(info, inputpos, tab, "get", opt) | ||||
| 				 | ||||
| 				if tab.tristate then | ||||
| 					--cycle in true, nil, false order | ||||
| 					if b then | ||||
| 						b = nil | ||||
| 					elseif b == nil then | ||||
| 						b = false | ||||
| 					else | ||||
| 						b = true | ||||
| 					end | ||||
| 				else | ||||
| 					b = not b | ||||
| 				end | ||||
| 				newval = b | ||||
| 			else | ||||
| 				--set the option as specified | ||||
| 				if val==L["on"] then | ||||
| 					newval = true | ||||
| 				elseif val==L["off"] then | ||||
| 					newval = false | ||||
| 				elseif val==L["default"] then | ||||
| 					newval = nil | ||||
| 				end | ||||
| 			end | ||||
| 			 | ||||
| 			do_final(info, inputpos, tab, "set", opt, newval) | ||||
| 		end | ||||
| 					 | ||||
| 		 | ||||
| 	elseif tab.type=="color" then | ||||
| 		------------ color -------------------------------------------- | ||||
| 		local str = strtrim(strlower(str)) | ||||
| 		if str == "" then | ||||
| 			--TODO: Show current value | ||||
| 			return | ||||
| 		end | ||||
| 		 | ||||
| 		local r, g, b, a | ||||
| 		 | ||||
| 		local hasAlpha = tab.hasAlpha | ||||
| 		if type(hasAlpha) == "function" or type(hasAlpha) == "string" then | ||||
| 			info.hasAlpha = hasAlpha | ||||
| 			hasAlpha = callmethod(info, inputpos, tab, 'hasAlpha') | ||||
| 			info.hasAlpha = nil | ||||
| 		end | ||||
| 		 | ||||
| 		if hasAlpha then | ||||
| 			if str:len() == 8 and str:find("^%x*$")  then | ||||
| 				--parse a hex string | ||||
| 				r,g,b,a = tonumber(str:sub(1, 2), 16) / 255, tonumber(str:sub(3, 4), 16) / 255, tonumber(str:sub(5, 6), 16) / 255, tonumber(str:sub(7, 8), 16) / 255 | ||||
| 			else | ||||
| 				--parse seperate values | ||||
| 				r,g,b,a = str:match("^([%d%.]+) ([%d%.]+) ([%d%.]+) ([%d%.]+)$") | ||||
| 				r,g,b,a = tonumber(r), tonumber(g), tonumber(b), tonumber(a) | ||||
| 			end | ||||
| 			if not (r and g and b and a) then | ||||
| 				usererr(info, inputpos, format(L["'%s' - expected 'RRGGBBAA' or 'r g b a'."], str)) | ||||
| 				return | ||||
| 			end | ||||
| 			 | ||||
| 			if r >= 0.0 and r <= 1.0 and g >= 0.0 and g <= 1.0 and b >= 0.0 and b <= 1.0 and a >= 0.0 and a <= 1.0 then | ||||
| 				--values are valid | ||||
| 			elseif r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255 and a >= 0 and a <= 255 then | ||||
| 				--values are valid 0..255, convert to 0..1 | ||||
| 				r = r / 255 | ||||
| 				g = g / 255 | ||||
| 				b = b / 255 | ||||
| 				a = a / 255 | ||||
| 			else | ||||
| 				--values are invalid | ||||
| 				usererr(info, inputpos, format(L["'%s' - values must all be either in the range 0..1 or 0..255."], str)) | ||||
| 			end | ||||
| 		else | ||||
| 			a = 1.0 | ||||
| 			if str:len() == 6 and str:find("^%x*$") then | ||||
| 				--parse a hex string | ||||
| 				r,g,b = tonumber(str:sub(1, 2), 16) / 255, tonumber(str:sub(3, 4), 16) / 255, tonumber(str:sub(5, 6), 16) / 255 | ||||
| 			else | ||||
| 				--parse seperate values | ||||
| 				r,g,b = str:match("^([%d%.]+) ([%d%.]+) ([%d%.]+)$") | ||||
| 				r,g,b = tonumber(r), tonumber(g), tonumber(b) | ||||
| 			end | ||||
| 			if not (r and g and b) then | ||||
| 				usererr(info, inputpos, format(L["'%s' - expected 'RRGGBB' or 'r g b'."], str)) | ||||
| 				return | ||||
| 			end | ||||
| 			if r >= 0.0 and r <= 1.0 and g >= 0.0 and g <= 1.0 and b >= 0.0 and b <= 1.0 then | ||||
| 				--values are valid | ||||
| 			elseif r >= 0 and r <= 255 and g >= 0 and g <= 255 and b >= 0 and b <= 255 then | ||||
| 				--values are valid 0..255, convert to 0..1 | ||||
| 				r = r / 255 | ||||
| 				g = g / 255 | ||||
| 				b = b / 255 | ||||
| 			else | ||||
| 				--values are invalid | ||||
| 				usererr(info, inputpos, format(L["'%s' - values must all be either in the range 0-1 or 0-255."], str)) | ||||
| 			end | ||||
| 		end | ||||
| 		 | ||||
| 		do_final(info, inputpos, tab, "set", r,g,b,a) | ||||
|  | ||||
| 	elseif tab.type=="keybinding" then | ||||
| 		------------ keybinding -------------------------------------------- | ||||
| 		local str = strtrim(strlower(str)) | ||||
| 		if str == "" then | ||||
| 			--TODO: Show current value | ||||
| 			return | ||||
| 		end | ||||
| 		local value = keybindingValidateFunc(str:upper()) | ||||
| 		if value == false then | ||||
| 			usererr(info, inputpos, format(L["'%s' - Invalid Keybinding."], str)) | ||||
| 			return | ||||
| 		end | ||||
|  | ||||
| 		do_final(info, inputpos, tab, "set", value) | ||||
|  | ||||
| 	elseif tab.type=="description" then | ||||
| 		------------ description -------------------- | ||||
| 		-- ignore description, GUI config only | ||||
| 	else | ||||
| 		err(info, inputpos, "unknown options table item type '"..tostring(tab.type).."'") | ||||
| 	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") | ||||
| --  | ||||
| -- -- 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) | ||||
|  | ||||
| 	local optgetter = cfgreg:GetOptionsTable(appName) | ||||
| 	if not optgetter then | ||||
| 		error([[Usage: HandleCommand("slashcmd", "appName", "input"): 'appName' - no options table "]]..tostring(appName)..[[" has been registered]], 2) | ||||
| 	end | ||||
| 	local options = assert( optgetter("cmd", MAJOR) ) | ||||
| 	 | ||||
| 	local info = {   -- Don't try to recycle this, it gets handed off to callbacks and whatnot | ||||
| 		[0] = slashcmd, | ||||
| 		appName = appName, | ||||
| 		options = options, | ||||
| 		input = input, | ||||
| 		self = self, | ||||
| 		handler = self, | ||||
| 		uiType = "cmd", | ||||
| 		uiName = MAJOR, | ||||
| 	} | ||||
| 	 | ||||
| 	handle(info, 1, options, 0)  -- (info, inputpos, table, depth) | ||||
| end | ||||
|  | ||||
| --- 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) | ||||
| 	if not AceConsole then | ||||
| 		AceConsole = LibStub(AceConsoleName) | ||||
| 	end | ||||
| 	if AceConsole.RegisterChatCommand(self, slashcmd, function(input) | ||||
| 				AceConfigCmd.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) | ||||
| 	return commands[slashcmd] | ||||
| end | ||||
							
								
								
									
										4
									
								
								libs/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								libs/AceConfig-3.0/AceConfigCmd-3.0/AceConfigCmd-3.0.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ | ||||
| ..\FrameXML\UI.xsd"> | ||||
| 	<Script file="AceConfigCmd-3.0.lua"/> | ||||
| </Ui> | ||||
							
								
								
									
										1983
									
								
								libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1983
									
								
								libs/AceConfig-3.0/AceConfigDialog-3.0/AceConfigDialog-3.0.lua
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,4 @@ | ||||
| <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ | ||||
| ..\FrameXML\UI.xsd"> | ||||
| 	<Script file="AceConfigDialog-3.0.lua"/> | ||||
| </Ui> | ||||
| @@ -0,0 +1,350 @@ | ||||
| --- 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 1169 2018-02-27 16:18:28Z nevcairiel $ | ||||
| local CallbackHandler = LibStub("CallbackHandler-1.0") | ||||
|  | ||||
| local MAJOR, MINOR = "AceConfigRegistry-3.0", 18 | ||||
| local AceConfigRegistry = LibStub:NewLibrary(MAJOR, MINOR) | ||||
|  | ||||
| if not AceConfigRegistry then return end | ||||
|  | ||||
| AceConfigRegistry.tables = AceConfigRegistry.tables or {} | ||||
|  | ||||
| if not AceConfigRegistry.callbacks then | ||||
| 	AceConfigRegistry.callbacks = CallbackHandler:New(AceConfigRegistry) | ||||
| 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 = { | ||||
| 	-- list of options table names ran through :ValidateOptionsTable automatically.  | ||||
| 	-- CLEARED ON PURPOSE, since newer versions may have newer validators | ||||
| 	cmd = {}, | ||||
| 	dropdown = {}, | ||||
| 	dialog = {}, | ||||
| } | ||||
|  | ||||
|  | ||||
|  | ||||
| local function err(msg, errlvl, ...) | ||||
| 	local t = {} | ||||
| 	for i=select("#",...),1,-1 do | ||||
| 		tinsert(t, (select(i, ...))) | ||||
| 	end | ||||
| 	error(MAJOR..":ValidateOptionsTable(): "..tconcat(t,".")..msg, errlvl+2) | ||||
| end | ||||
|  | ||||
|  | ||||
| local isstring={["string"]=true, _="string"} | ||||
| local isstringfunc={["string"]=true,["function"]=true, _="string or funcref"} | ||||
| local istable={["table"]=true,   _="table"} | ||||
| local ismethodtable={["table"]=true,["string"]=true,["function"]=true,   _="methodname, funcref or table"} | ||||
| local optstring={["nil"]=true,["string"]=true, _="string"} | ||||
| local optstringfunc={["nil"]=true,["string"]=true,["function"]=true, _="string or funcref"} | ||||
| local optstringnumberfunc={["nil"]=true,["string"]=true,["number"]=true,["function"]=true, _="string, number or funcref"} | ||||
| local optnumber={["nil"]=true,["number"]=true, _="number"} | ||||
| local optmethod={["nil"]=true,["string"]=true,["function"]=true, _="methodname or funcref"} | ||||
| local optmethodfalse={["nil"]=true,["string"]=true,["function"]=true,["boolean"]={[false]=true},  _="methodname, funcref or false"} | ||||
| local optmethodnumber={["nil"]=true,["string"]=true,["function"]=true,["number"]=true,  _="methodname, funcref or number"} | ||||
| local optmethodtable={["nil"]=true,["string"]=true,["function"]=true,["table"]=true,  _="methodname, funcref or table"} | ||||
| local optmethodbool={["nil"]=true,["string"]=true,["function"]=true,["boolean"]=true,  _="methodname, funcref or boolean"} | ||||
| local opttable={["nil"]=true,["table"]=true,  _="table"} | ||||
| local optbool={["nil"]=true,["boolean"]=true,  _="boolean"} | ||||
| local optboolnumber={["nil"]=true,["boolean"]=true,["number"]=true,  _="boolean or number"} | ||||
| local optstringnumber={["nil"]=true,["string"]=true,["number"]=true, _="string or number"} | ||||
|  | ||||
| local basekeys={ | ||||
| 	type=isstring, | ||||
| 	name=isstringfunc, | ||||
| 	desc=optstringfunc, | ||||
| 	descStyle=optstring, | ||||
| 	order=optmethodnumber, | ||||
| 	validate=optmethodfalse, | ||||
| 	confirm=optmethodbool, | ||||
| 	confirmText=optstring, | ||||
| 	disabled=optmethodbool, | ||||
| 	hidden=optmethodbool, | ||||
| 		guiHidden=optmethodbool, | ||||
| 		dialogHidden=optmethodbool, | ||||
| 		dropdownHidden=optmethodbool, | ||||
| 	cmdHidden=optmethodbool, | ||||
| 	icon=optstringnumberfunc, | ||||
| 	iconCoords=optmethodtable, | ||||
| 	handler=opttable, | ||||
| 	get=optmethodfalse, | ||||
| 	set=optmethodfalse, | ||||
| 	func=optmethodfalse, | ||||
| 	arg={["*"]=true}, | ||||
| 	width=optstringnumber, | ||||
| } | ||||
|  | ||||
| local typedkeys={ | ||||
| 	header={}, | ||||
| 	description={ | ||||
| 		image=optstringnumberfunc, | ||||
| 		imageCoords=optmethodtable, | ||||
| 		imageHeight=optnumber, | ||||
| 		imageWidth=optnumber, | ||||
| 		fontSize=optstringfunc, | ||||
| 	}, | ||||
| 	group={ | ||||
| 		args=istable, | ||||
| 		plugins=opttable, | ||||
| 		inline=optbool, | ||||
| 			cmdInline=optbool, | ||||
| 			guiInline=optbool, | ||||
| 			dropdownInline=optbool, | ||||
| 			dialogInline=optbool, | ||||
| 		childGroups=optstring, | ||||
| 	}, | ||||
| 	execute={ | ||||
| 		image=optstringnumberfunc, | ||||
| 		imageCoords=optmethodtable, | ||||
| 		imageHeight=optnumber, | ||||
| 		imageWidth=optnumber, | ||||
| 	}, | ||||
| 	input={ | ||||
| 		pattern=optstring, | ||||
| 		usage=optstring, | ||||
| 		control=optstring, | ||||
| 		dialogControl=optstring, | ||||
| 		dropdownControl=optstring, | ||||
| 		multiline=optboolnumber, | ||||
| 	}, | ||||
| 	toggle={ | ||||
| 		tristate=optbool, | ||||
| 		image=optstringnumberfunc, | ||||
| 		imageCoords=optmethodtable, | ||||
| 	}, | ||||
| 	tristate={ | ||||
| 	}, | ||||
| 	range={ | ||||
| 		min=optnumber, | ||||
| 		softMin=optnumber, | ||||
| 		max=optnumber, | ||||
| 		softMax=optnumber, | ||||
| 		step=optnumber, | ||||
| 		bigStep=optnumber, | ||||
| 		isPercent=optbool, | ||||
| 	}, | ||||
| 	select={ | ||||
| 		values=ismethodtable, | ||||
| 		style={ | ||||
| 			["nil"]=true,  | ||||
| 			["string"]={dropdown=true,radio=true},  | ||||
| 			_="string: 'dropdown' or 'radio'" | ||||
| 		}, | ||||
| 		control=optstring, | ||||
| 		dialogControl=optstring, | ||||
| 		dropdownControl=optstring, | ||||
| 		itemControl=optstring, | ||||
| 	}, | ||||
| 	multiselect={ | ||||
| 		values=ismethodtable, | ||||
| 		style=optstring, | ||||
| 		tristate=optbool, | ||||
| 		control=optstring, | ||||
| 		dialogControl=optstring, | ||||
| 		dropdownControl=optstring, | ||||
| 	}, | ||||
| 	color={ | ||||
| 		hasAlpha=optmethodbool, | ||||
| 	}, | ||||
| 	keybinding={ | ||||
| 		-- TODO | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| local function validateKey(k,errlvl,...) | ||||
| 	errlvl=(errlvl or 0)+1 | ||||
| 	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,...) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| local function validateVal(v, oktypes, errlvl,...) | ||||
| 	errlvl=(errlvl or 0)+1 | ||||
| 	local isok=oktypes[type(v)] or oktypes["*"] | ||||
|  | ||||
| 	if not isok then | ||||
| 		err(": expected a "..oktypes._..", got '"..tostring(v).."'", errlvl,...) | ||||
| 	end | ||||
| 	if type(isok)=="table" then		-- isok was a table containing specific values to be tested for! | ||||
| 		if not isok[v] then | ||||
| 			err(": did not expect "..type(v).." value '"..tostring(v).."'", errlvl,...) | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| local function validate(options,errlvl,...) | ||||
| 	errlvl=(errlvl or 0)+1 | ||||
| 	-- basic consistency | ||||
| 	if type(options)~="table" then | ||||
| 		err(": expected a table, got a "..type(options), errlvl,...) | ||||
| 	end | ||||
| 	if type(options.type)~="string" then | ||||
| 		err(".type: expected a string, got a "..type(options.type), errlvl,...) | ||||
| 	end | ||||
| 	 | ||||
| 	-- get type and 'typedkeys' member | ||||
| 	local tk = typedkeys[options.type] | ||||
| 	if not tk then | ||||
| 		err(".type: unknown type '"..options.type.."'", errlvl,...) | ||||
| 	end | ||||
| 	 | ||||
| 	-- make sure that all options[] are known parameters | ||||
| 	for k,v in pairs(options) do | ||||
| 		if not (tk[k] or basekeys[k]) then | ||||
| 			err(": unknown parameter", errlvl,tostring(k),...) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	-- verify that required params are there, and that everything is the right type | ||||
| 	for k,oktypes in pairs(basekeys) do | ||||
| 		validateVal(options[k], oktypes, errlvl,k,...) | ||||
| 	end | ||||
| 	for k,oktypes in pairs(tk) do | ||||
| 		validateVal(options[k], oktypes, errlvl,k,...) | ||||
| 	end | ||||
|  | ||||
| 	-- extra logic for groups | ||||
| 	if options.type=="group" then | ||||
| 		for k,v in pairs(options.args) do | ||||
| 			validateKey(k,errlvl,"args",...) | ||||
| 			validate(v, errlvl,k,"args",...) | ||||
| 		end | ||||
| 		if options.plugins then | ||||
| 			for plugname,plugin in pairs(options.plugins) do | ||||
| 				if type(plugin)~="table" then | ||||
| 					err(": expected a table, got '"..tostring(plugin).."'", errlvl,tostring(plugname),"plugins",...) | ||||
| 				end | ||||
| 				for k,v in pairs(plugin) do | ||||
| 					validateKey(k,errlvl,tostring(plugname),"plugins",...) | ||||
| 					validate(v, errlvl,k,tostring(plugname),"plugins",...) | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
|  | ||||
| --- 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) | ||||
| 	errlvl=(errlvl or 0)+1 | ||||
| 	name = name or "Optionstable" | ||||
| 	if not options.name then | ||||
| 		options.name=name	-- bit of a hack, the root level doesn't really need a .name :-/ | ||||
| 	end | ||||
| 	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) | ||||
| end | ||||
|  | ||||
| -- ------------------------------------------------------------------- | ||||
| -- Registering and retreiving options tables: | ||||
|  | ||||
|  | ||||
| -- validateGetterArgs: helper function for :GetOptionsTable (or, rather, the getter functions returned by it) | ||||
|  | ||||
| local function validateGetterArgs(uiType, uiName, errlvl) | ||||
| 	errlvl=(errlvl or 0)+2 | ||||
| 	if uiType~="cmd" and uiType~="dropdown" and uiType~="dialog" then | ||||
| 		error(MAJOR..": Requesting options table: 'uiType' - invalid configuration UI type, expected 'cmd', 'dropdown' or 'dialog'", errlvl) | ||||
| 	end | ||||
| 	if not strmatch(uiName, "[A-Za-z]%-[0-9]") then	-- Expecting e.g. "MyLib-1.2" | ||||
| 		error(MAJOR..": Requesting options table: 'uiName' - badly formatted or missing version number. Expected e.g. 'MyLib-1.2'", 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. | ||||
| -- @param skipValidation Skip options table validation (primarily useful for extremely huge options, with a noticeable slowdown) | ||||
| function AceConfigRegistry:RegisterOptionsTable(appName, options, skipValidation) | ||||
| 	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) | ||||
| 			errlvl=(errlvl or 0)+1 | ||||
| 			validateGetterArgs(uiType, uiName, errlvl) | ||||
| 			if not AceConfigRegistry.validated[uiType][appName] and not skipValidation then | ||||
| 				AceConfigRegistry:ValidateOptionsTable(options, appName, errlvl)	-- upgradable | ||||
| 				AceConfigRegistry.validated[uiType][appName] = true | ||||
| 			end | ||||
| 			return options  | ||||
| 		end | ||||
| 	elseif type(options)=="function" then | ||||
| 		AceConfigRegistry.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] and not skipValidation then | ||||
| 				AceConfigRegistry:ValidateOptionsTable(tab, appName, errlvl)	-- upgradable | ||||
| 				AceConfigRegistry.validated[uiType][appName] = true | ||||
| 			end | ||||
| 			return tab | ||||
| 		end | ||||
| 	else | ||||
| 		error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - expected table or function reference", 2) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| --- Returns an iterator of ["appName"]=funcref pairs | ||||
| function AceConfigRegistry:IterateOptionsTables() | ||||
| 	return pairs(AceConfigRegistry.tables) | ||||
| end | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| --- Query the registry for a specific options table. | ||||
| -- If only appName is given, a function is returned which you | ||||
| -- 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] | ||||
| 	if not f then | ||||
| 		return nil | ||||
| 	end | ||||
| 	 | ||||
| 	if uiType then | ||||
| 		return f(uiType,uiName,1)	-- get the table for us | ||||
| 	else | ||||
| 		return f	-- return the function | ||||
| 	end | ||||
| end | ||||
| @@ -0,0 +1,4 @@ | ||||
| <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ | ||||
| ..\FrameXML\UI.xsd"> | ||||
| 	<Script file="AceConfigRegistry-3.0.lua"/> | ||||
| </Ui> | ||||
							
								
								
									
										746
									
								
								libs/AceDB-3.0/AceDB-3.0.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										746
									
								
								libs/AceDB-3.0/AceDB-3.0.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,746 @@ | ||||
| --- **AceDB-3.0** manages the SavedVariables of your addon. | ||||
| -- It offers profile management, smart defaults and namespaces for modules.\\ | ||||
| -- Data can be saved in different data-types, depending on its intended usage. | ||||
| -- The most common data-type is the `profile` type, which allows the user to choose | ||||
| -- the active profile, and manage the profiles of all of his characters.\\ | ||||
| -- The following data types are available: | ||||
| -- * **char** Character-specific data. Every character has its own database. | ||||
| -- * **realm** Realm-specific data. All of the players characters on the same realm share this database. | ||||
| -- * **class** Class-specific data. All of the players characters of the same class share this database. | ||||
| -- * **race** Race-specific data. All of the players characters of the same race share this database. | ||||
| -- * **faction** Faction-specific data. All of the players characters of the same faction share this database. | ||||
| -- * **factionrealm** Faction and realm specific data. All of the players characters on the same realm and of the same faction share this database. | ||||
| -- * **locale** Locale specific data, based on the locale of the players game client. | ||||
| -- * **global** Global Data. All characters on the same account share this database. | ||||
| -- * **profile** Profile-specific data. All characters using the same profile share this database. The user can control which profile should be used. | ||||
| -- | ||||
| -- Creating a new Database using the `:New` function will return a new DBObject. A database will inherit all functions | ||||
| -- of the DBObjectLib listed here. \\ | ||||
| -- If you create a new namespaced child-database (`:RegisterNamespace`), you'll get a DBObject as well, but note | ||||
| -- that the child-databases cannot individually change their profile, and are linked to their parents profile - and because of that, | ||||
| -- the profile related APIs are not available. Only `:RegisterDefaults` and `:ResetProfile` are available on child-databases. | ||||
| -- | ||||
| -- For more details on how to use AceDB-3.0, see the [[AceDB-3.0 Tutorial]]. | ||||
| -- | ||||
| -- You may also be interested in [[libdualspec-1-0|LibDualSpec-1.0]] to do profile switching automatically when switching specs. | ||||
| -- | ||||
| -- @usage | ||||
| -- MyAddon = LibStub("AceAddon-3.0"):NewAddon("DBExample") | ||||
| -- | ||||
| -- -- declare defaults to be used in the DB | ||||
| -- local defaults = { | ||||
| --   profile = { | ||||
| --     setting = true, | ||||
| --   } | ||||
| -- } | ||||
| -- | ||||
| -- function MyAddon:OnInitialize() | ||||
| --   -- Assuming the .toc says ## SavedVariables: MyAddonDB | ||||
| --   self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true) | ||||
| -- end | ||||
| -- @class file | ||||
| -- @name AceDB-3.0.lua | ||||
| -- @release $Id: AceDB-3.0.lua 1142 2016-07-11 08:36:19Z nevcairiel $ | ||||
| local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 26 | ||||
| local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR) | ||||
|  | ||||
| if not AceDB then return end -- No upgrade needed | ||||
|  | ||||
| -- Lua APIs | ||||
| local type, pairs, next, error = type, pairs, next, error | ||||
| local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget | ||||
|  | ||||
| -- 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 | ||||
|  | ||||
| AceDB.db_registry = AceDB.db_registry or {} | ||||
| AceDB.frame = AceDB.frame or CreateFrame("Frame") | ||||
|  | ||||
| local CallbackHandler | ||||
| local CallbackDummy = { Fire = function() end } | ||||
|  | ||||
| local DBObjectLib = {} | ||||
|  | ||||
| --[[------------------------------------------------------------------------- | ||||
| 	AceDB Utility Functions | ||||
| ---------------------------------------------------------------------------]] | ||||
|  | ||||
| -- Simple shallow copy for copying defaults | ||||
| local function copyTable(src, dest) | ||||
| 	if type(dest) ~= "table" then dest = {} end | ||||
| 	if type(src) == "table" then | ||||
| 		for k,v in pairs(src) do | ||||
| 			if type(v) == "table" then | ||||
| 				-- try to index the key first so that the metatable creates the defaults, if set, and use that table | ||||
| 				v = copyTable(v, dest[k]) | ||||
| 			end | ||||
| 			dest[k] = v | ||||
| 		end | ||||
| 	end | ||||
| 	return dest | ||||
| end | ||||
|  | ||||
| -- Called to add defaults to a section of the database | ||||
| -- | ||||
| -- When a ["*"] default section is indexed with a new key, a table is returned | ||||
| -- and set in the host table.  These tables must be cleaned up by removeDefaults | ||||
| -- in order to ensure we don't write empty default tables. | ||||
| local function copyDefaults(dest, src) | ||||
| 	-- this happens if some value in the SV overwrites our default value with a non-table | ||||
| 	--if type(dest) ~= "table" then return end | ||||
| 	for k, v in pairs(src) do | ||||
| 		if k == "*" or k == "**" then | ||||
| 			if type(v) == "table" then | ||||
| 				-- This is a metatable used for table defaults | ||||
| 				local mt = { | ||||
| 					-- This handles the lookup and creation of new subtables | ||||
| 					__index = function(t,k) | ||||
| 							if k == nil then return nil end | ||||
| 							local tbl = {} | ||||
| 							copyDefaults(tbl, v) | ||||
| 							rawset(t, k, tbl) | ||||
| 							return tbl | ||||
| 						end, | ||||
| 				} | ||||
| 				setmetatable(dest, mt) | ||||
| 				-- handle already existing tables in the SV | ||||
| 				for dk, dv in pairs(dest) do | ||||
| 					if not rawget(src, dk) and type(dv) == "table" then | ||||
| 						copyDefaults(dv, v) | ||||
| 					end | ||||
| 				end | ||||
| 			else | ||||
| 				-- Values are not tables, so this is just a simple return | ||||
| 				local mt = {__index = function(t,k) return k~=nil and v or nil end} | ||||
| 				setmetatable(dest, mt) | ||||
| 			end | ||||
| 		elseif type(v) == "table" then | ||||
| 			if not rawget(dest, k) then rawset(dest, k, {}) end | ||||
| 			if type(dest[k]) == "table" then | ||||
| 				copyDefaults(dest[k], v) | ||||
| 				if src['**'] then | ||||
| 					copyDefaults(dest[k], src['**']) | ||||
| 				end | ||||
| 			end | ||||
| 		else | ||||
| 			if rawget(dest, k) == nil then | ||||
| 				rawset(dest, k, v) | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- Called to remove all defaults in the default table from the database | ||||
| local function removeDefaults(db, defaults, blocker) | ||||
| 	-- remove all metatables from the db, so we don't accidentally create new sub-tables through them | ||||
| 	setmetatable(db, nil) | ||||
| 	-- loop through the defaults and remove their content | ||||
| 	for k,v in pairs(defaults) do | ||||
| 		if k == "*" or k == "**" then | ||||
| 			if type(v) == "table" then | ||||
| 				-- Loop through all the actual k,v pairs and remove | ||||
| 				for key, value in pairs(db) do | ||||
| 					if type(value) == "table" then | ||||
| 						-- if the key was not explicitly specified in the defaults table, just strip everything from * and ** tables | ||||
| 						if defaults[key] == nil and (not blocker or blocker[key] == nil) then | ||||
| 							removeDefaults(value, v) | ||||
| 							-- if the table is empty afterwards, remove it | ||||
| 							if next(value) == nil then | ||||
| 								db[key] = nil | ||||
| 							end | ||||
| 						-- if it was specified, only strip ** content, but block values which were set in the key table | ||||
| 						elseif k == "**" then | ||||
| 							removeDefaults(value, v, defaults[key]) | ||||
| 						end | ||||
| 					end | ||||
| 				end | ||||
| 			elseif k == "*" then | ||||
| 				-- check for non-table default | ||||
| 				for key, value in pairs(db) do | ||||
| 					if defaults[key] == nil and v == value then | ||||
| 						db[key] = nil | ||||
| 					end | ||||
| 				end | ||||
| 			end | ||||
| 		elseif type(v) == "table" and type(db[k]) == "table" then | ||||
| 			-- if a blocker was set, dive into it, to allow multi-level defaults | ||||
| 			removeDefaults(db[k], v, blocker and blocker[k]) | ||||
| 			if next(db[k]) == nil then | ||||
| 				db[k] = nil | ||||
| 			end | ||||
| 		else | ||||
| 			-- check if the current value matches the default, and that its not blocked by another defaults table | ||||
| 			if db[k] == defaults[k] and (not blocker or blocker[k] == nil) then | ||||
| 				db[k] = nil | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| -- This is called when a table section is first accessed, to set up the defaults | ||||
| local function initSection(db, section, svstore, key, defaults) | ||||
| 	local sv = rawget(db, "sv") | ||||
|  | ||||
| 	local tableCreated | ||||
| 	if not sv[svstore] then sv[svstore] = {} end | ||||
| 	if not sv[svstore][key] then | ||||
| 		sv[svstore][key] = {} | ||||
| 		tableCreated = true | ||||
| 	end | ||||
|  | ||||
| 	local tbl = sv[svstore][key] | ||||
|  | ||||
| 	if defaults then | ||||
| 		copyDefaults(tbl, defaults) | ||||
| 	end | ||||
| 	rawset(db, section, tbl) | ||||
|  | ||||
| 	return tableCreated, tbl | ||||
| end | ||||
|  | ||||
| -- Metatable to handle the dynamic creation of sections and copying of sections. | ||||
| local dbmt = { | ||||
| 	__index = function(t, section) | ||||
| 			local keys = rawget(t, "keys") | ||||
| 			local key = keys[section] | ||||
| 			if key then | ||||
| 				local defaultTbl = rawget(t, "defaults") | ||||
| 				local defaults = defaultTbl and defaultTbl[section] | ||||
|  | ||||
| 				if section == "profile" then | ||||
| 					local new = initSection(t, section, "profiles", key, defaults) | ||||
| 					if new then | ||||
| 						-- Callback: OnNewProfile, database, newProfileKey | ||||
| 						t.callbacks:Fire("OnNewProfile", t, key) | ||||
| 					end | ||||
| 				elseif section == "profiles" then | ||||
| 					local sv = rawget(t, "sv") | ||||
| 					if not sv.profiles then sv.profiles = {} end | ||||
| 					rawset(t, "profiles", sv.profiles) | ||||
| 				elseif section == "global" then | ||||
| 					local sv = rawget(t, "sv") | ||||
| 					if not sv.global then sv.global = {} end | ||||
| 					if defaults then | ||||
| 						copyDefaults(sv.global, defaults) | ||||
| 					end | ||||
| 					rawset(t, section, sv.global) | ||||
| 				else | ||||
| 					initSection(t, section, section, key, defaults) | ||||
| 				end | ||||
| 			end | ||||
|  | ||||
| 			return rawget(t, section) | ||||
| 		end | ||||
| } | ||||
|  | ||||
| local function validateDefaults(defaults, keyTbl, offset) | ||||
| 	if not defaults then return end | ||||
| 	offset = offset or 0 | ||||
| 	for k in pairs(defaults) do | ||||
| 		if not keyTbl[k] or k == "profiles" then | ||||
| 			error(("Usage: AceDBObject:RegisterDefaults(defaults): '%s' is not a valid datatype."):format(k), 3 + offset) | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| local preserve_keys = { | ||||
| 	["callbacks"] = true, | ||||
| 	["RegisterCallback"] = true, | ||||
| 	["UnregisterCallback"] = true, | ||||
| 	["UnregisterAllCallbacks"] = true, | ||||
| 	["children"] = true, | ||||
| } | ||||
|  | ||||
| local realmKey = GetRealmName() | ||||
| local charKey = UnitName("player") .. " - " .. realmKey | ||||
| local _, classKey = UnitClass("player") | ||||
| local _, raceKey = UnitRace("player") | ||||
| local factionKey = UnitFactionGroup("player") | ||||
| local factionrealmKey = factionKey .. " - " .. realmKey | ||||
| local localeKey = GetLocale():lower() | ||||
|  | ||||
| local regionTable = { "US", "KR", "EU", "TW", "CN" } | ||||
| local regionKey = regionTable[GetCurrentRegion()] | ||||
| local factionrealmregionKey = factionrealmKey .. " - " .. regionKey | ||||
|  | ||||
| -- Actual database initialization function | ||||
| local function initdb(sv, defaults, defaultProfile, olddb, parent) | ||||
| 	-- Generate the database keys for each section | ||||
|  | ||||
| 	-- map "true" to our "Default" profile | ||||
| 	if defaultProfile == true then defaultProfile = "Default" end | ||||
|  | ||||
| 	local profileKey | ||||
| 	if not parent then | ||||
| 		-- Make a container for profile keys | ||||
| 		if not sv.profileKeys then sv.profileKeys = {} end | ||||
|  | ||||
| 		-- Try to get the profile selected from the char db | ||||
| 		profileKey = sv.profileKeys[charKey] or defaultProfile or charKey | ||||
|  | ||||
| 		-- save the selected profile for later | ||||
| 		sv.profileKeys[charKey] = profileKey | ||||
| 	else | ||||
| 		-- Use the profile of the parents DB | ||||
| 		profileKey = parent.keys.profile or defaultProfile or charKey | ||||
|  | ||||
| 		-- clear the profileKeys in the DB, namespaces don't need to store them | ||||
| 		sv.profileKeys = nil | ||||
| 	end | ||||
|  | ||||
| 	-- This table contains keys that enable the dynamic creation | ||||
| 	-- of each section of the table.  The 'global' and 'profiles' | ||||
| 	-- have a key of true, since they are handled in a special case | ||||
| 	local keyTbl= { | ||||
| 		["char"] = charKey, | ||||
| 		["realm"] = realmKey, | ||||
| 		["class"] = classKey, | ||||
| 		["race"] = raceKey, | ||||
| 		["faction"] = factionKey, | ||||
| 		["factionrealm"] = factionrealmKey, | ||||
| 		["factionrealmregion"] = factionrealmregionKey, | ||||
| 		["profile"] = profileKey, | ||||
| 		["locale"] = localeKey, | ||||
| 		["global"] = true, | ||||
| 		["profiles"] = true, | ||||
| 	} | ||||
|  | ||||
| 	validateDefaults(defaults, keyTbl, 1) | ||||
|  | ||||
| 	-- This allows us to use this function to reset an entire database | ||||
| 	-- Clear out the old database | ||||
| 	if olddb then | ||||
| 		for k,v in pairs(olddb) do if not preserve_keys[k] then olddb[k] = nil end end | ||||
| 	end | ||||
|  | ||||
| 	-- Give this database the metatable so it initializes dynamically | ||||
| 	local db = setmetatable(olddb or {}, dbmt) | ||||
|  | ||||
| 	if not rawget(db, "callbacks") then | ||||
| 		-- try to load CallbackHandler-1.0 if it loaded after our library | ||||
| 		if not CallbackHandler then CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0", true) end | ||||
| 		db.callbacks = CallbackHandler and CallbackHandler:New(db) or CallbackDummy | ||||
| 	end | ||||
|  | ||||
| 	-- Copy methods locally into the database object, to avoid hitting | ||||
| 	-- the metatable when calling methods | ||||
|  | ||||
| 	if not parent then | ||||
| 		for name, func in pairs(DBObjectLib) do | ||||
| 			db[name] = func | ||||
| 		end | ||||
| 	else | ||||
| 		-- hack this one in | ||||
| 		db.RegisterDefaults = DBObjectLib.RegisterDefaults | ||||
| 		db.ResetProfile = DBObjectLib.ResetProfile | ||||
| 	end | ||||
|  | ||||
| 	-- Set some properties in the database object | ||||
| 	db.profiles = sv.profiles | ||||
| 	db.keys = keyTbl | ||||
| 	db.sv = sv | ||||
| 	--db.sv_name = name | ||||
| 	db.defaults = defaults | ||||
| 	db.parent = parent | ||||
|  | ||||
| 	-- store the DB in the registry | ||||
| 	AceDB.db_registry[db] = true | ||||
|  | ||||
| 	return db | ||||
| end | ||||
|  | ||||
| -- handle PLAYER_LOGOUT | ||||
| -- strip all defaults from all databases | ||||
| -- and cleans up empty sections | ||||
| local function logoutHandler(frame, event) | ||||
| 	if event == "PLAYER_LOGOUT" then | ||||
| 		for db in pairs(AceDB.db_registry) do | ||||
| 			db.callbacks:Fire("OnDatabaseShutdown", db) | ||||
| 			db:RegisterDefaults(nil) | ||||
|  | ||||
| 			-- cleanup sections that are empty without defaults | ||||
| 			local sv = rawget(db, "sv") | ||||
| 			for section in pairs(db.keys) do | ||||
| 				if rawget(sv, section) then | ||||
| 					-- global is special, all other sections have sub-entrys | ||||
| 					-- also don't delete empty profiles on main dbs, only on namespaces | ||||
| 					if section ~= "global" and (section ~= "profiles" or rawget(db, "parent")) then | ||||
| 						for key in pairs(sv[section]) do | ||||
| 							if not next(sv[section][key]) then | ||||
| 								sv[section][key] = nil | ||||
| 							end | ||||
| 						end | ||||
| 					end | ||||
| 					if not next(sv[section]) then | ||||
| 						sv[section] = nil | ||||
| 					end | ||||
| 				end | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| AceDB.frame:RegisterEvent("PLAYER_LOGOUT") | ||||
| AceDB.frame:SetScript("OnEvent", logoutHandler) | ||||
|  | ||||
|  | ||||
| --[[------------------------------------------------------------------------- | ||||
| 	AceDB Object Method Definitions | ||||
| ---------------------------------------------------------------------------]] | ||||
|  | ||||
| --- Sets the defaults table for the given database object by clearing any | ||||
| -- that are currently set, and then setting the new defaults. | ||||
| -- @param defaults A table of defaults for this database | ||||
| function DBObjectLib:RegisterDefaults(defaults) | ||||
| 	if defaults and type(defaults) ~= "table" then | ||||
| 		error("Usage: AceDBObject:RegisterDefaults(defaults): 'defaults' - table or nil expected.", 2) | ||||
| 	end | ||||
|  | ||||
| 	validateDefaults(defaults, self.keys) | ||||
|  | ||||
| 	-- Remove any currently set defaults | ||||
| 	if self.defaults then | ||||
| 		for section,key in pairs(self.keys) do | ||||
| 			if self.defaults[section] and rawget(self, section) then | ||||
| 				removeDefaults(self[section], self.defaults[section]) | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	-- Set the DBObject.defaults table | ||||
| 	self.defaults = defaults | ||||
|  | ||||
| 	-- Copy in any defaults, only touching those sections already created | ||||
| 	if defaults then | ||||
| 		for section,key in pairs(self.keys) do | ||||
| 			if defaults[section] and rawget(self, section) then | ||||
| 				copyDefaults(self[section], defaults[section]) | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
| end | ||||
|  | ||||
| --- Changes the profile of the database and all of it's namespaces to the | ||||
| -- supplied named profile | ||||
| -- @param name The name of the profile to set as the current profile | ||||
| function DBObjectLib:SetProfile(name) | ||||
| 	if type(name) ~= "string" then | ||||
| 		error("Usage: AceDBObject:SetProfile(name): 'name' - string expected.", 2) | ||||
| 	end | ||||
|  | ||||
| 	-- changing to the same profile, dont do anything | ||||
| 	if name == self.keys.profile then return end | ||||
|  | ||||
| 	local oldProfile = self.profile | ||||
| 	local defaults = self.defaults and self.defaults.profile | ||||
|  | ||||
| 	-- Callback: OnProfileShutdown, database | ||||
| 	self.callbacks:Fire("OnProfileShutdown", self) | ||||
|  | ||||
| 	if oldProfile and defaults then | ||||
| 		-- Remove the defaults from the old profile | ||||
| 		removeDefaults(oldProfile, defaults) | ||||
| 	end | ||||
|  | ||||
| 	self.profile = nil | ||||
| 	self.keys["profile"] = name | ||||
|  | ||||
| 	-- if the storage exists, save the new profile | ||||
| 	-- this won't exist on namespaces. | ||||
| 	if self.sv.profileKeys then | ||||
| 		self.sv.profileKeys[charKey] = name | ||||
| 	end | ||||
|  | ||||
| 	-- populate to child namespaces | ||||
| 	if self.children then | ||||
| 		for _, db in pairs(self.children) do | ||||
| 			DBObjectLib.SetProfile(db, name) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	-- Callback: OnProfileChanged, database, newProfileKey | ||||
| 	self.callbacks:Fire("OnProfileChanged", self, name) | ||||
| end | ||||
|  | ||||
| --- Returns a table with the names of the existing profiles in the database. | ||||
| -- You can optionally supply a table to re-use for this purpose. | ||||
| -- @param tbl A table to store the profile names in (optional) | ||||
| function DBObjectLib:GetProfiles(tbl) | ||||
| 	if tbl and type(tbl) ~= "table" then | ||||
| 		error("Usage: AceDBObject:GetProfiles(tbl): 'tbl' - table or nil expected.", 2) | ||||
| 	end | ||||
|  | ||||
| 	-- Clear the container table | ||||
| 	if tbl then | ||||
| 		for k,v in pairs(tbl) do tbl[k] = nil end | ||||
| 	else | ||||
| 		tbl = {} | ||||
| 	end | ||||
|  | ||||
| 	local curProfile = self.keys.profile | ||||
|  | ||||
| 	local i = 0 | ||||
| 	for profileKey in pairs(self.profiles) do | ||||
| 		i = i + 1 | ||||
| 		tbl[i] = profileKey | ||||
| 		if curProfile and profileKey == curProfile then curProfile = nil end | ||||
| 	end | ||||
|  | ||||
| 	-- Add the current profile, if it hasn't been created yet | ||||
| 	if curProfile then | ||||
| 		i = i + 1 | ||||
| 		tbl[i] = curProfile | ||||
| 	end | ||||
|  | ||||
| 	return tbl, i | ||||
| end | ||||
|  | ||||
| --- Returns the current profile name used by the database | ||||
| function DBObjectLib:GetCurrentProfile() | ||||
| 	return self.keys.profile | ||||
| end | ||||
|  | ||||
| --- Deletes a named profile.  This profile must not be the active profile. | ||||
| -- @param name The name of the profile to be deleted | ||||
| -- @param silent If true, do not raise an error when the profile does not exist | ||||
| function DBObjectLib:DeleteProfile(name, silent) | ||||
| 	if type(name) ~= "string" then | ||||
| 		error("Usage: AceDBObject:DeleteProfile(name): 'name' - string expected.", 2) | ||||
| 	end | ||||
|  | ||||
| 	if self.keys.profile == name then | ||||
| 		error("Cannot delete the active profile in an AceDBObject.", 2) | ||||
| 	end | ||||
|  | ||||
| 	if not rawget(self.profiles, name) and not silent then | ||||
| 		error("Cannot delete profile '" .. name .. "'. It does not exist.", 2) | ||||
| 	end | ||||
|  | ||||
| 	self.profiles[name] = nil | ||||
|  | ||||
| 	-- populate to child namespaces | ||||
| 	if self.children then | ||||
| 		for _, db in pairs(self.children) do | ||||
| 			DBObjectLib.DeleteProfile(db, name, true) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	-- switch all characters that use this profile back to the default | ||||
| 	if self.sv.profileKeys then | ||||
| 		for key, profile in pairs(self.sv.profileKeys) do | ||||
| 			if profile == name then | ||||
| 				self.sv.profileKeys[key] = nil | ||||
| 			end | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	-- Callback: OnProfileDeleted, database, profileKey | ||||
| 	self.callbacks:Fire("OnProfileDeleted", self, name) | ||||
| end | ||||
|  | ||||
| --- Copies a named profile into the current profile, overwriting any conflicting | ||||
| -- settings. | ||||
| -- @param name The name of the profile to be copied into the current profile | ||||
| -- @param silent If true, do not raise an error when the profile does not exist | ||||
| function DBObjectLib:CopyProfile(name, silent) | ||||
| 	if type(name) ~= "string" then | ||||
| 		error("Usage: AceDBObject:CopyProfile(name): 'name' - string expected.", 2) | ||||
| 	end | ||||
|  | ||||
| 	if name == self.keys.profile then | ||||
| 		error("Cannot have the same source and destination profiles.", 2) | ||||
| 	end | ||||
|  | ||||
| 	if not rawget(self.profiles, name) and not silent then | ||||
| 		error("Cannot copy profile '" .. name .. "'. It does not exist.", 2) | ||||
| 	end | ||||
|  | ||||
| 	-- Reset the profile before copying | ||||
| 	DBObjectLib.ResetProfile(self, nil, true) | ||||
|  | ||||
| 	local profile = self.profile | ||||
| 	local source = self.profiles[name] | ||||
|  | ||||
| 	copyTable(source, profile) | ||||
|  | ||||
| 	-- populate to child namespaces | ||||
| 	if self.children then | ||||
| 		for _, db in pairs(self.children) do | ||||
| 			DBObjectLib.CopyProfile(db, name, true) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	-- Callback: OnProfileCopied, database, sourceProfileKey | ||||
| 	self.callbacks:Fire("OnProfileCopied", self, name) | ||||
| end | ||||
|  | ||||
| --- Resets the current profile to the default values (if specified). | ||||
| -- @param noChildren if set to true, the reset will not be populated to the child namespaces of this DB object | ||||
| -- @param noCallbacks if set to true, won't fire the OnProfileReset callback | ||||
| function DBObjectLib:ResetProfile(noChildren, noCallbacks) | ||||
| 	local profile = self.profile | ||||
|  | ||||
| 	for k,v in pairs(profile) do | ||||
| 		profile[k] = nil | ||||
| 	end | ||||
|  | ||||
| 	local defaults = self.defaults and self.defaults.profile | ||||
| 	if defaults then | ||||
| 		copyDefaults(profile, defaults) | ||||
| 	end | ||||
|  | ||||
| 	-- populate to child namespaces | ||||
| 	if self.children and not noChildren then | ||||
| 		for _, db in pairs(self.children) do | ||||
| 			DBObjectLib.ResetProfile(db, nil, noCallbacks) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	-- Callback: OnProfileReset, database | ||||
| 	if not noCallbacks then | ||||
| 		self.callbacks:Fire("OnProfileReset", self) | ||||
| 	end | ||||
| end | ||||
|  | ||||
| --- Resets the entire database, using the string defaultProfile as the new default | ||||
| -- profile. | ||||
| -- @param defaultProfile The profile name to use as the default | ||||
| function DBObjectLib:ResetDB(defaultProfile) | ||||
| 	if defaultProfile and type(defaultProfile) ~= "string" then | ||||
| 		error("Usage: AceDBObject:ResetDB(defaultProfile): 'defaultProfile' - string or nil expected.", 2) | ||||
| 	end | ||||
|  | ||||
| 	local sv = self.sv | ||||
| 	for k,v in pairs(sv) do | ||||
| 		sv[k] = nil | ||||
| 	end | ||||
|  | ||||
| 	local parent = self.parent | ||||
|  | ||||
| 	initdb(sv, self.defaults, defaultProfile, self) | ||||
|  | ||||
| 	-- fix the child namespaces | ||||
| 	if self.children then | ||||
| 		if not sv.namespaces then sv.namespaces = {} end | ||||
| 		for name, db in pairs(self.children) do | ||||
| 			if not sv.namespaces[name] then sv.namespaces[name] = {} end | ||||
| 			initdb(sv.namespaces[name], db.defaults, self.keys.profile, db, self) | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	-- Callback: OnDatabaseReset, database | ||||
| 	self.callbacks:Fire("OnDatabaseReset", self) | ||||
| 	-- Callback: OnProfileChanged, database, profileKey | ||||
| 	self.callbacks:Fire("OnProfileChanged", self, self.keys["profile"]) | ||||
|  | ||||
| 	return self | ||||
| end | ||||
|  | ||||
| --- Creates a new database namespace, directly tied to the database.  This | ||||
| -- is a full scale database in it's own rights other than the fact that | ||||
| -- it cannot control its profile individually | ||||
| -- @param name The name of the new namespace | ||||
| -- @param defaults A table of values to use as defaults | ||||
| function DBObjectLib:RegisterNamespace(name, defaults) | ||||
| 	if type(name) ~= "string" then | ||||
| 		error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - string expected.", 2) | ||||
| 	end | ||||
| 	if defaults and type(defaults) ~= "table" then | ||||
| 		error("Usage: AceDBObject:RegisterNamespace(name, defaults): 'defaults' - table or nil expected.", 2) | ||||
| 	end | ||||
| 	if self.children and self.children[name] then | ||||
| 		error ("Usage: AceDBObject:RegisterNamespace(name, defaults): 'name' - a namespace with that name already exists.", 2) | ||||
| 	end | ||||
|  | ||||
| 	local sv = self.sv | ||||
| 	if not sv.namespaces then sv.namespaces = {} end | ||||
| 	if not sv.namespaces[name] then | ||||
| 		sv.namespaces[name] = {} | ||||
| 	end | ||||
|  | ||||
| 	local newDB = initdb(sv.namespaces[name], defaults, self.keys.profile, nil, self) | ||||
|  | ||||
| 	if not self.children then self.children = {} end | ||||
| 	self.children[name] = newDB | ||||
| 	return newDB | ||||
| end | ||||
|  | ||||
| --- Returns an already existing namespace from the database object. | ||||
| -- @param name The name of the new namespace | ||||
| -- @param silent if true, the addon is optional, silently return nil if its not found | ||||
| -- @usage | ||||
| -- local namespace = self.db:GetNamespace('namespace') | ||||
| -- @return the namespace object if found | ||||
| function DBObjectLib:GetNamespace(name, silent) | ||||
| 	if type(name) ~= "string" then | ||||
| 		error("Usage: AceDBObject:GetNamespace(name): 'name' - string expected.", 2) | ||||
| 	end | ||||
| 	if not silent and not (self.children and self.children[name]) then | ||||
| 		error ("Usage: AceDBObject:GetNamespace(name): 'name' - namespace does not exist.", 2) | ||||
| 	end | ||||
| 	if not self.children then self.children = {} end | ||||
| 	return self.children[name] | ||||
| end | ||||
|  | ||||
| --[[------------------------------------------------------------------------- | ||||
| 	AceDB Exposed Methods | ||||
| ---------------------------------------------------------------------------]] | ||||
|  | ||||
| --- Creates a new database object that can be used to handle database settings and profiles. | ||||
| -- By default, an empty DB is created, using a character specific profile. | ||||
| -- | ||||
| -- You can override the default profile used by passing any profile name as the third argument, | ||||
| -- or by passing //true// as the third argument to use a globally shared profile called "Default". | ||||
| -- | ||||
| -- Note that there is no token replacement in the default profile name, passing a defaultProfile as "char" | ||||
| -- will use a profile named "char", and not a character-specific profile. | ||||
| -- @param tbl The name of variable, or table to use for the database | ||||
| -- @param defaults A table of database defaults | ||||
| -- @param defaultProfile The name of the default profile. If not set, a character specific profile will be used as the default. | ||||
| -- You can also pass //true// to use a shared global profile called "Default". | ||||
| -- @usage | ||||
| -- -- Create an empty DB using a character-specific default profile. | ||||
| -- self.db = LibStub("AceDB-3.0"):New("MyAddonDB") | ||||
| -- @usage | ||||
| -- -- Create a DB using defaults and using a shared default profile | ||||
| -- self.db = LibStub("AceDB-3.0"):New("MyAddonDB", defaults, true) | ||||
| function AceDB:New(tbl, defaults, defaultProfile) | ||||
| 	if type(tbl) == "string" then | ||||
| 		local name = tbl | ||||
| 		tbl = _G[name] | ||||
| 		if not tbl then | ||||
| 			tbl = {} | ||||
| 			_G[name] = tbl | ||||
| 		end | ||||
| 	end | ||||
|  | ||||
| 	if type(tbl) ~= "table" then | ||||
| 		error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'tbl' - table expected.", 2) | ||||
| 	end | ||||
|  | ||||
| 	if defaults and type(defaults) ~= "table" then | ||||
| 		error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaults' - table expected.", 2) | ||||
| 	end | ||||
|  | ||||
| 	if defaultProfile and type(defaultProfile) ~= "string" and defaultProfile ~= true then | ||||
| 		error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string or true expected.", 2) | ||||
| 	end | ||||
|  | ||||
| 	return initdb(tbl, defaults, defaultProfile) | ||||
| end | ||||
|  | ||||
| -- upgrade existing databases | ||||
| for db in pairs(AceDB.db_registry) do | ||||
| 	if not db.parent then | ||||
| 		for name,func in pairs(DBObjectLib) do | ||||
| 			db[name] = func | ||||
| 		end | ||||
| 	else | ||||
| 		db.RegisterDefaults = DBObjectLib.RegisterDefaults | ||||
| 		db.ResetProfile = DBObjectLib.ResetProfile | ||||
| 	end | ||||
| end | ||||
							
								
								
									
										4
									
								
								libs/AceDB-3.0/AceDB-3.0.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								libs/AceDB-3.0/AceDB-3.0.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ | ||||
| ..\FrameXML\UI.xsd"> | ||||
| 	<Script file="AceDB-3.0.lua"/> | ||||
| </Ui> | ||||
							
								
								
									
										460
									
								
								libs/AceDBOptions-3.0/AceDBOptions-3.0.lua
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										460
									
								
								libs/AceDBOptions-3.0/AceDBOptions-3.0.lua
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,460 @@ | ||||
| --- AceDBOptions-3.0 provides a universal AceConfig options screen for managing AceDB-3.0 profiles. | ||||
| -- @class file | ||||
| -- @name AceDBOptions-3.0 | ||||
| -- @release $Id: AceDBOptions-3.0.lua 1140 2016-07-03 07:53:29Z nevcairiel $ | ||||
| local ACEDBO_MAJOR, ACEDBO_MINOR = "AceDBOptions-3.0", 15 | ||||
| local AceDBOptions, oldminor = LibStub:NewLibrary(ACEDBO_MAJOR, ACEDBO_MINOR) | ||||
|  | ||||
| if not AceDBOptions then return end -- No upgrade needed | ||||
|  | ||||
| -- Lua APIs | ||||
| local pairs, next = pairs, next | ||||
|  | ||||
| -- WoW APIs | ||||
| local UnitClass = UnitClass | ||||
|  | ||||
| -- 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_CODE, FONT_COLOR_CODE_CLOSE | ||||
|  | ||||
| AceDBOptions.optionTables = AceDBOptions.optionTables or {} | ||||
| AceDBOptions.handlers = AceDBOptions.handlers or {} | ||||
|  | ||||
| --[[ | ||||
| 	Localization of AceDBOptions-3.0 | ||||
| ]] | ||||
|  | ||||
| local L = { | ||||
| 	choose = "Existing Profiles", | ||||
| 	choose_desc = "You can either create a new profile by entering a name in the editbox, or choose one of the already existing profiles.", | ||||
| 	choose_sub = "Select one of your currently available profiles.", | ||||
| 	copy = "Copy From", | ||||
| 	copy_desc = "Copy the settings from one existing profile into the currently active profile.", | ||||
| 	current = "Current Profile:", | ||||
| 	default = "Default", | ||||
| 	delete = "Delete a Profile", | ||||
| 	delete_confirm = "Are you sure you want to delete the selected profile?", | ||||
| 	delete_desc = "Delete existing and unused profiles from the database to save space, and cleanup the SavedVariables file.", | ||||
| 	delete_sub = "Deletes a profile from the database.", | ||||
| 	intro = "You can change the active database profile, so you can have different settings for every character.", | ||||
| 	new = "New", | ||||
| 	new_sub = "Create a new empty profile.", | ||||
| 	profiles = "Profiles", | ||||
| 	profiles_sub = "Manage Profiles", | ||||
| 	reset = "Reset Profile", | ||||
| 	reset_desc = "Reset the current profile back to its default values, in case your configuration is broken, or you simply want to start over.", | ||||
| 	reset_sub = "Reset the current profile to the default", | ||||
| } | ||||
|  | ||||
| local LOCALE = GetLocale() | ||||
| if LOCALE == "deDE" then | ||||
| 	L["choose"] = "Vorhandene Profile" | ||||
| 	L["choose_desc"] = "Du kannst ein neues Profil erstellen, indem du einen neuen Namen in der Eingabebox 'Neu' eingibst, oder wähle eines der vorhandenen Profile aus." | ||||
| 	L["choose_sub"] = "Wählt ein bereits vorhandenes Profil aus." | ||||
| 	L["copy"] = "Kopieren von..." | ||||
| 	L["copy_desc"] = "Kopiere die Einstellungen von einem vorhandenen Profil in das aktive Profil." | ||||
| 	L["current"] = "Aktuelles Profil:" | ||||
| 	L["default"] = "Standard" | ||||
| 	L["delete"] = "Profil löschen" | ||||
| 	L["delete_confirm"] = "Willst du das ausgewählte Profil wirklich löschen?" | ||||
| 	L["delete_desc"] = "Lösche vorhandene oder unbenutzte Profile aus der Datenbank, um Platz zu sparen und die SavedVariables-Datei 'sauber' zu halten." | ||||
| 	L["delete_sub"] = "Löscht ein Profil aus der Datenbank." | ||||
| 	L["intro"] = "Hier kannst du das aktive Datenbankprofil ändern, damit du verschiedene Einstellungen für jeden Charakter erstellen kannst, wodurch eine sehr flexible Konfiguration möglich wird." | ||||
| 	L["new"] = "Neu" | ||||
| 	L["new_sub"] = "Ein neues Profil erstellen." | ||||
| 	L["profiles"] = "Profile" | ||||
| 	L["profiles_sub"] = "Profile verwalten" | ||||
| 	L["reset"] = "Profil zurücksetzen" | ||||
| 	L["reset_desc"] = "Setzt das momentane Profil auf Standardwerte zurück, für den Fall, dass mit der Konfiguration etwas schief lief oder weil du einfach neu starten willst." | ||||
| 	L["reset_sub"] = "Das aktuelle Profil auf Standard zurücksetzen." | ||||
| elseif LOCALE == "frFR" then | ||||
| 	L["choose"] = "Profils existants" | ||||
| 	L["choose_desc"] = "Vous pouvez créer un nouveau profil en entrant un nouveau nom dans la boîte de saisie, ou en choississant un des profils déjà existants." | ||||
| 	L["choose_sub"] = "Permet de choisir un des profils déjà disponibles." | ||||
| 	L["copy"] = "Copier à partir de" | ||||
| 	L["copy_desc"] = "Copie les paramètres d'un profil déjà existant dans le profil actuellement actif." | ||||
| 	L["current"] = "Profil actuel :" | ||||
| 	L["default"] = "Défaut" | ||||
| 	L["delete"] = "Supprimer un profil" | ||||
| 	L["delete_confirm"] = "Etes-vous sûr de vouloir supprimer le profil sélectionné ?" | ||||
| 	L["delete_desc"] = "Supprime les profils existants inutilisés de la base de données afin de gagner de la place et de nettoyer le fichier SavedVariables." | ||||
| 	L["delete_sub"] = "Supprime un profil de la base de données." | ||||
| 	L["intro"] = "Vous pouvez changer le profil actuel afin d'avoir des paramètres différents pour chaque personnage, permettant ainsi d'avoir une configuration très flexible." | ||||
| 	L["new"] = "Nouveau" | ||||
| 	L["new_sub"] = "Créée un nouveau profil vierge." | ||||
| 	L["profiles"] = "Profils" | ||||
| 	L["profiles_sub"] = "Gestion des profils" | ||||
| 	L["reset"] = "Réinitialiser le profil" | ||||
| 	L["reset_desc"] = "Réinitialise le profil actuel au cas où votre configuration est corrompue ou si vous voulez tout simplement faire table rase." | ||||
| 	L["reset_sub"] = "Réinitialise le profil actuel avec les paramètres par défaut." | ||||
| elseif LOCALE == "koKR" then | ||||
| 	L["choose"] = "저장 중인 프로필" | ||||
| 	L["choose_desc"] = "입력창에 새로운 이름을 입력하거나 저장 중인 프로필 중 하나를 선택하여 새로운 프로필을 만들 수 있습니다." | ||||
| 	L["choose_sub"] = "현재 이용할 수 있는 프로필 중 하나를 선택합니다." | ||||
| 	L["copy"] = "복사해오기" | ||||
| 	L["copy_desc"] = "현재 사용 중인 프로필에 선택한 프로필의 설정을 복사합니다." | ||||
| 	L["current"] = "현재 프로필:" | ||||
| 	L["default"] = "기본값" | ||||
| 	L["delete"] = "프로필 삭제" | ||||
| 	L["delete_confirm"] = "정말로 선택한 프로필을 삭제할까요?" | ||||
| 	L["delete_desc"] = "저장 공간 절약과 SavedVariables 파일의 정리를 위해 데이터베이스에서 사용하지 않는 프로필을 삭제하세요." | ||||
| 	L["delete_sub"] = "데이터베이스의 프로필을 삭제합니다." | ||||
| 	L["intro"] = "활성 데이터베이스 프로필을 변경할 수 있고, 각 캐릭터 별로 다른 설정을 할 수 있습니다." | ||||
| 	L["new"] = "새로운 프로필" | ||||
| 	L["new_sub"] = "새로운 프로필을 만듭니다." | ||||
| 	L["profiles"] = "프로필" | ||||
| 	L["profiles_sub"] = "프로필 관리" | ||||
| 	L["reset"] = "프로필 초기화" | ||||
| 	L["reset_desc"] = "설정이 깨졌거나 처음부터 다시 설정을 원하는 경우, 현재 프로필을 기본값으로 초기화하세요." | ||||
| 	L["reset_sub"] = "현재 프로필을 기본값으로 초기화합니다" | ||||
| elseif LOCALE == "esES" or LOCALE == "esMX" then | ||||
| 	L["choose"] = "Perfiles existentes" | ||||
| 	L["choose_desc"] = "Puedes crear un nuevo perfil introduciendo un nombre en el recuadro o puedes seleccionar un perfil de los ya existentes." | ||||
| 	L["choose_sub"] = "Selecciona uno de los perfiles disponibles." | ||||
| 	L["copy"] = "Copiar de" | ||||
| 	L["copy_desc"] = "Copia los ajustes de un perfil existente al perfil actual." | ||||
| 	L["current"] = "Perfil actual:" | ||||
| 	L["default"] = "Por defecto" | ||||
| 	L["delete"] = "Borrar un Perfil" | ||||
| 	L["delete_confirm"] = "¿Estas seguro que quieres borrar el perfil seleccionado?" | ||||
| 	L["delete_desc"] = "Borra los perfiles existentes y sin uso de la base de datos para ganar espacio y limpiar el archivo SavedVariables." | ||||
| 	L["delete_sub"] = "Borra un perfil de la base de datos." | ||||
| 	L["intro"] = "Puedes cambiar el perfil activo de tal manera que cada personaje tenga diferentes configuraciones." | ||||
| 	L["new"] = "Nuevo" | ||||
| 	L["new_sub"] = "Crear un nuevo perfil vacio." | ||||
| 	L["profiles"] = "Perfiles" | ||||
| 	L["profiles_sub"] = "Manejar Perfiles" | ||||
| 	L["reset"] = "Reiniciar Perfil" | ||||
| 	L["reset_desc"] = "Reinicia el perfil actual a los valores por defectos, en caso de que se haya estropeado la configuración o quieras volver a empezar de nuevo." | ||||
| 	L["reset_sub"] = "Reinicar el perfil actual al de por defecto" | ||||
| elseif LOCALE == "zhTW" then | ||||
| 	L["choose"] = "現有的設定檔" | ||||
| 	L["choose_desc"] = "您可以在文字方塊內輸入名字以建立新的設定檔,或是選擇一個現有的設定檔使用。" | ||||
| 	L["choose_sub"] = "從當前可用的設定檔裡面選擇一個。" | ||||
| 	L["copy"] = "複製自" | ||||
| 	L["copy_desc"] = "從一個現有的設定檔,將設定複製到現在使用中的設定檔。" | ||||
| 	L["current"] = "目前設定檔:" | ||||
| 	L["default"] = "預設" | ||||
| 	L["delete"] = "刪除一個設定檔" | ||||
| 	L["delete_confirm"] = "確定要刪除所選擇的設定檔嗎?" | ||||
| 	L["delete_desc"] = "從資料庫裡刪除不再使用的設定檔,以節省空間,並且清理 SavedVariables 檔案。" | ||||
| 	L["delete_sub"] = "從資料庫裡刪除一個設定檔。" | ||||
| 	L["intro"] = "您可以從資料庫中選擇一個設定檔來使用,如此就可以讓每個角色使用不同的設定。" | ||||
| 	L["new"] = "新建" | ||||
| 	L["new_sub"] = "新建一個空的設定檔。" | ||||
| 	L["profiles"] = "設定檔" | ||||
| 	L["profiles_sub"] = "管理設定檔" | ||||
| 	L["reset"] = "重置設定檔" | ||||
| 	L["reset_desc"] = "將現用的設定檔重置為預設值;用於設定檔損壞,或者單純想要重來的情況。" | ||||
| 	L["reset_sub"] = "將目前的設定檔重置為預設值" | ||||
| elseif LOCALE == "zhCN" then | ||||
| 	L["choose"] = "现有的配置文件" | ||||
| 	L["choose_desc"] = "你可以通过在文本框内输入一个名字创立一个新的配置文件,也可以选择一个已经存在的配置文件。" | ||||
| 	L["choose_sub"] = "从当前可用的配置文件里面选择一个。" | ||||
| 	L["copy"] = "复制自" | ||||
| 	L["copy_desc"] = "从当前某个已保存的配置文件复制到当前正使用的配置文件。" | ||||
| 	L["current"] = "当前配置文件:" | ||||
| 	L["default"] = "默认" | ||||
| 	L["delete"] = "删除一个配置文件" | ||||
| 	L["delete_confirm"] = "你确定要删除所选择的配置文件么?" | ||||
| 	L["delete_desc"] = "从数据库里删除不再使用的配置文件,以节省空间,并且清理SavedVariables文件。" | ||||
| 	L["delete_sub"] = "从数据库里删除一个配置文件。" | ||||
| 	L["intro"] = "你可以选择一个活动的数据配置文件,这样你的每个角色就可以拥有不同的设置值,可以给你的插件配置带来极大的灵活性。" | ||||
| 	L["new"] = "新建" | ||||
| 	L["new_sub"] = "新建一个空的配置文件。" | ||||
| 	L["profiles"] = "配置文件" | ||||
| 	L["profiles_sub"] = "管理配置文件" | ||||
| 	L["reset"] = "重置配置文件" | ||||
| 	L["reset_desc"] = "将当前的配置文件恢复到它的默认值,用于你的配置文件损坏,或者你只是想重来的情况。" | ||||
| 	L["reset_sub"] = "将当前的配置文件恢复为默认值" | ||||
| elseif LOCALE == "ruRU" then | ||||
| 	L["choose"] = "Существующие профили" | ||||
| 	L["choose_desc"] = "Вы можете создать новый профиль, введя название в поле ввода, или выбрать один из уже существующих профилей." | ||||
| 	L["choose_sub"] = "Выбор одиного из уже доступных профилей" | ||||
| 	L["copy"] = "Скопировать из" | ||||
| 	L["copy_desc"] = "Скопировать настройки из выбранного профиля в активный." | ||||
| 	L["current"] = "Текущий профиль:" | ||||
| 	L["default"] = "По умолчанию" | ||||
| 	L["delete"] = "Удалить профиль" | ||||
| 	L["delete_confirm"] = "Вы уверены, что вы хотите удалить выбранный профиль?" | ||||
| 	L["delete_desc"] = "Удалить существующий и неиспользуемый профиль из БД для сохранения места, и очистить SavedVariables файл." | ||||
| 	L["delete_sub"] = "Удаление профиля из БД" | ||||
| 	L["intro"] = "Изменяя активный профиль, вы можете задать различные настройки модификаций для каждого персонажа." | ||||
| 	L["new"] = "Новый" | ||||
| 	L["new_sub"] = "Создать новый чистый профиль" | ||||
| 	L["profiles"] = "Профили" | ||||
| 	L["profiles_sub"] = "Управление профилями" | ||||
| 	L["reset"] = "Сброс профиля" | ||||
| 	L["reset_desc"] = "Сбросить текущий профиль к стандартным настройкам, если ваша конфигурация испорчена или вы хотите настроить всё заново." | ||||
| 	L["reset_sub"] = "Сброс текущего профиля на стандартный" | ||||
| elseif LOCALE == "itIT" then | ||||
| 	L["choose"] = "Profili Esistenti" | ||||
| 	L["choose_desc"] = "Puoi creare un nuovo profilo digitando il nome della casella di testo, oppure scegliendone uno tra i profili già esistenti." | ||||
| 	L["choose_sub"] = "Seleziona uno dei profili attualmente disponibili." | ||||
| 	L["copy"] = "Copia Da" | ||||
| 	L["copy_desc"] = "Copia le impostazioni da un profilo esistente, nel profilo attivo in questo momento." | ||||
| 	L["current"] = "Profilo Attivo:" | ||||
| 	L["default"] = "Standard" | ||||
| 	L["delete"] = "Cancella un Profilo" | ||||
| 	L["delete_confirm"] = "Sei sicuro di voler cancellare il profilo selezionato?" | ||||
| 	L["delete_desc"] = "Cancella i profili non utilizzati dal database per risparmiare spazio e mantenere puliti i file di configurazione SavedVariables." | ||||
| 	L["delete_sub"] = "Cancella un profilo dal Database." | ||||
| 	L["intro"] = "Puoi cambiare il profilo attivo, in modo da usare impostazioni diverse per ogni personaggio." | ||||
| 	L["new"] = "Nuovo" | ||||
| 	L["new_sub"] = "Crea un nuovo profilo vuoto." | ||||
| 	L["profiles"] = "Profili" | ||||
| 	L["profiles_sub"] = "Gestisci Profili" | ||||
| 	L["reset"] = "Reimposta Profilo" | ||||
| 	L["reset_desc"] = "Riporta il tuo profilo attivo alle sue impostazioni predefinite, nel caso in cui la tua configurazione si sia corrotta, o semplicemente tu voglia re-inizializzarla." | ||||
| 	L["reset_sub"] = "Reimposta il profilo ai suoi valori predefiniti." | ||||
| elseif LOCALE == "ptBR" then | ||||
| 	L["choose"] = "Perfis Existentes" | ||||
| 	L["choose_desc"] = "Você pode tanto criar um perfil novo tanto digitando um nome na caixa de texto, quanto escolher um dos perfis já existentes." | ||||
| 	L["choose_sub"] = "Selecione um de seus perfis atualmente disponíveis." | ||||
| 	L["copy"] = "Copiar De" | ||||
| 	L["copy_desc"] = "Copia as definições de um perfil existente no perfil atualmente ativo." | ||||
| 	L["current"] = "Perfil Autal:" | ||||
| 	L["default"] = "Padrão" | ||||
| 	L["delete"] = "Remover um Perfil" | ||||
| 	L["delete_confirm"] = "Tem certeza que deseja remover o perfil selecionado?" | ||||
| 	L["delete_desc"] = "Remove perfis existentes e inutilizados do banco de dados para economizar espaço, e limpar o arquivo SavedVariables." | ||||
| 	L["delete_sub"] = "Remove um perfil do banco de dados." | ||||
| 	L["intro"] = "Você pode alterar o perfil do banco de dados ativo, para que possa ter definições diferentes para cada personagem." | ||||
| 	L["new"] = "Novo" | ||||
| 	L["new_sub"] = "Cria um novo perfil vazio." | ||||
| 	L["profiles"] = "Perfis" | ||||
| 	L["profiles_sub"] = "Gerenciar Perfis" | ||||
| 	L["reset"] = "Resetar Perfil" | ||||
| 	L["reset_desc"] = "Reseta o perfil atual para os valores padrões, no caso de sua configuração estar quebrada, ou simplesmente se deseja começar novamente." | ||||
| 	L["reset_sub"] = "Resetar o perfil atual ao padrão" | ||||
| end | ||||
|  | ||||
| local defaultProfiles | ||||
| local tmpprofiles = {} | ||||
|  | ||||
| -- Get a list of available profiles for the specified database. | ||||
| -- You can specify which profiles to include/exclude in the list using the two boolean parameters listed below. | ||||
| -- @param db The db object to retrieve the profiles from | ||||
| -- @param common If true, getProfileList will add the default profiles to the return list, even if they have not been created yet | ||||
| -- @param nocurrent If true, then getProfileList will not display the current profile in the list | ||||
| -- @return Hashtable of all profiles with the internal name as keys and the display name as value. | ||||
| local function getProfileList(db, common, nocurrent) | ||||
| 	local profiles = {} | ||||
| 	 | ||||
| 	-- copy existing profiles into the table | ||||
| 	local currentProfile = db:GetCurrentProfile() | ||||
| 	for i,v in pairs(db:GetProfiles(tmpprofiles)) do  | ||||
| 		if not (nocurrent and v == currentProfile) then  | ||||
| 			profiles[v] = v  | ||||
| 		end  | ||||
| 	end | ||||
| 	 | ||||
| 	-- add our default profiles to choose from ( or rename existing profiles) | ||||
| 	for k,v in pairs(defaultProfiles) do | ||||
| 		if (common or profiles[k]) and not (nocurrent and k == currentProfile) then | ||||
| 			profiles[k] = v | ||||
| 		end | ||||
| 	end | ||||
| 	 | ||||
| 	return profiles | ||||
| end | ||||
|  | ||||
| --[[ | ||||
| 	OptionsHandlerPrototype | ||||
| 	prototype class for handling the options in a sane way | ||||
| ]] | ||||
| local OptionsHandlerPrototype = {} | ||||
|  | ||||
| --[[ Reset the profile ]] | ||||
| function OptionsHandlerPrototype:Reset() | ||||
| 	self.db:ResetProfile() | ||||
| end | ||||
|  | ||||
| --[[ Set the profile to value ]] | ||||
| function OptionsHandlerPrototype:SetProfile(info, value) | ||||
| 	self.db:SetProfile(value) | ||||
| end | ||||
|  | ||||
| --[[ returns the currently active profile ]] | ||||
| function OptionsHandlerPrototype:GetCurrentProfile() | ||||
| 	return self.db:GetCurrentProfile() | ||||
| end | ||||
|  | ||||
| --[[  | ||||
| 	List all active profiles | ||||
| 	you can control the output with the .arg variable | ||||
| 	currently four modes are supported | ||||
| 	 | ||||
| 	(empty) - return all available profiles | ||||
| 	"nocurrent" - returns all available profiles except the currently active profile | ||||
| 	"common" - returns all avaialble profiles + some commonly used profiles ("char - realm", "realm", "class", "Default") | ||||
| 	"both" - common except the active profile | ||||
| ]] | ||||
| function OptionsHandlerPrototype:ListProfiles(info) | ||||
| 	local arg = info.arg | ||||
| 	local profiles | ||||
| 	if arg == "common" and not self.noDefaultProfiles then | ||||
| 		profiles = getProfileList(self.db, true, nil) | ||||
| 	elseif arg == "nocurrent" then | ||||
| 		profiles = getProfileList(self.db, nil, true) | ||||
| 	elseif arg == "both" then -- currently not used | ||||
| 		profiles = getProfileList(self.db, (not self.noDefaultProfiles) and true, true) | ||||
| 	else | ||||
| 		profiles = getProfileList(self.db) | ||||
| 	end | ||||
| 	 | ||||
| 	return profiles | ||||
| end | ||||
|  | ||||
| function OptionsHandlerPrototype:HasNoProfiles(info) | ||||
| 	local profiles = self:ListProfiles(info) | ||||
| 	return ((not next(profiles)) and true or false) | ||||
| end | ||||
|  | ||||
| --[[ Copy a profile ]] | ||||
| function OptionsHandlerPrototype:CopyProfile(info, value) | ||||
| 	self.db:CopyProfile(value) | ||||
| end | ||||
|  | ||||
| --[[ Delete a profile from the db ]] | ||||
| function OptionsHandlerPrototype:DeleteProfile(info, value) | ||||
| 	self.db:DeleteProfile(value) | ||||
| end | ||||
|  | ||||
| --[[ fill defaultProfiles with some generic values ]] | ||||
| local function generateDefaultProfiles(db) | ||||
| 	defaultProfiles = { | ||||
| 		["Default"] = L["default"], | ||||
| 		[db.keys.char] = db.keys.char, | ||||
| 		[db.keys.realm] = db.keys.realm, | ||||
| 		[db.keys.class] = UnitClass("player") | ||||
| 	} | ||||
| end | ||||
|  | ||||
| --[[ create and return a handler object for the db, or upgrade it if it already existed ]] | ||||
| local function getOptionsHandler(db, noDefaultProfiles) | ||||
| 	if not defaultProfiles then | ||||
| 		generateDefaultProfiles(db) | ||||
| 	end | ||||
| 	 | ||||
| 	local handler = AceDBOptions.handlers[db] or { db = db, noDefaultProfiles = noDefaultProfiles } | ||||
| 	 | ||||
| 	for k,v in pairs(OptionsHandlerPrototype) do | ||||
| 		handler[k] = v | ||||
| 	end | ||||
| 	 | ||||
| 	AceDBOptions.handlers[db] = handler | ||||
| 	return handler | ||||
| end | ||||
|  | ||||
| --[[ | ||||
| 	the real options table  | ||||
| ]] | ||||
| local optionsTable = { | ||||
| 	desc = { | ||||
| 		order = 1, | ||||
| 		type = "description", | ||||
| 		name = L["intro"] .. "\n", | ||||
| 	}, | ||||
| 	descreset = { | ||||
| 		order = 9, | ||||
| 		type = "description", | ||||
| 		name = L["reset_desc"], | ||||
| 	}, | ||||
| 	reset = { | ||||
| 		order = 10, | ||||
| 		type = "execute", | ||||
| 		name = L["reset"], | ||||
| 		desc = L["reset_sub"], | ||||
| 		func = "Reset", | ||||
| 	}, | ||||
| 	current = { | ||||
| 		order = 11, | ||||
| 		type = "description", | ||||
| 		name = function(info) return L["current"] .. " " .. NORMAL_FONT_COLOR_CODE .. info.handler:GetCurrentProfile() .. FONT_COLOR_CODE_CLOSE end, | ||||
| 		width = "default", | ||||
| 	}, | ||||
| 	choosedesc = { | ||||
| 		order = 20, | ||||
| 		type = "description", | ||||
| 		name = "\n" .. L["choose_desc"], | ||||
| 	}, | ||||
| 	new = { | ||||
| 		name = L["new"], | ||||
| 		desc = L["new_sub"], | ||||
| 		type = "input", | ||||
| 		order = 30, | ||||
| 		get = false, | ||||
| 		set = "SetProfile", | ||||
| 	}, | ||||
| 	choose = { | ||||
| 		name = L["choose"], | ||||
| 		desc = L["choose_sub"], | ||||
| 		type = "select", | ||||
| 		order = 40, | ||||
| 		get = "GetCurrentProfile", | ||||
| 		set = "SetProfile", | ||||
| 		values = "ListProfiles", | ||||
| 		arg = "common", | ||||
| 	}, | ||||
| 	copydesc = { | ||||
| 		order = 50, | ||||
| 		type = "description", | ||||
| 		name = "\n" .. L["copy_desc"], | ||||
| 	}, | ||||
| 	copyfrom = { | ||||
| 		order = 60, | ||||
| 		type = "select", | ||||
| 		name = L["copy"], | ||||
| 		desc = L["copy_desc"], | ||||
| 		get = false, | ||||
| 		set = "CopyProfile", | ||||
| 		values = "ListProfiles", | ||||
| 		disabled = "HasNoProfiles", | ||||
| 		arg = "nocurrent", | ||||
| 	}, | ||||
| 	deldesc = { | ||||
| 		order = 70, | ||||
| 		type = "description", | ||||
| 		name = "\n" .. L["delete_desc"], | ||||
| 	}, | ||||
| 	delete = { | ||||
| 		order = 80, | ||||
| 		type = "select", | ||||
| 		name = L["delete"], | ||||
| 		desc = L["delete_sub"], | ||||
| 		get = false, | ||||
| 		set = "DeleteProfile", | ||||
| 		values = "ListProfiles", | ||||
| 		disabled = "HasNoProfiles", | ||||
| 		arg = "nocurrent", | ||||
| 		confirm = true, | ||||
| 		confirmText = L["delete_confirm"], | ||||
| 	}, | ||||
| } | ||||
|  | ||||
| --- Get/Create a option table that you can use in your addon to control the profiles of AceDB-3.0. | ||||
| -- @param db The database object to create the options table for. | ||||
| -- @return The options table to be used in AceConfig-3.0 | ||||
| -- @usage  | ||||
| -- -- Assuming `options` is your top-level options table and `self.db` is your database: | ||||
| -- options.args.profiles = LibStub("AceDBOptions-3.0"):GetOptionsTable(self.db) | ||||
| function AceDBOptions:GetOptionsTable(db, noDefaultProfiles) | ||||
| 	local tbl = AceDBOptions.optionTables[db] or { | ||||
| 			type = "group", | ||||
| 			name = L["profiles"], | ||||
| 			desc = L["profiles_sub"], | ||||
| 		} | ||||
| 	 | ||||
| 	tbl.handler = getOptionsHandler(db, noDefaultProfiles) | ||||
| 	tbl.args = optionsTable | ||||
|  | ||||
| 	AceDBOptions.optionTables[db] = tbl | ||||
| 	return tbl | ||||
| end | ||||
|  | ||||
| -- upgrade existing tables | ||||
| for db,tbl in pairs(AceDBOptions.optionTables) do | ||||
| 	tbl.handler = getOptionsHandler(db) | ||||
| 	tbl.args = optionsTable | ||||
| end | ||||
							
								
								
									
										4
									
								
								libs/AceDBOptions-3.0/AceDBOptions-3.0.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								libs/AceDBOptions-3.0/AceDBOptions-3.0.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| <Ui xmlns="http://www.blizzard.com/wow/ui/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.blizzard.com/wow/ui/ | ||||
| ..\FrameXML\UI.xsd"> | ||||
| 	<Script file="AceDBOptions-3.0.lua"/> | ||||
| </Ui> | ||||
		Reference in New Issue
	
	Block a user