<!--Ace3 Libraries-->
<Include file="libs\CallbackHandler-1.0\CallbackHandler-1.0.xml" />
-<Include file="libs\AceAddon-3.0\AceAddon-3.0.xml" />
<Include file="libs\AceGUI-3.0\AceGUI-3.0.xml" />
<Include file="libs\AceConfig-3.0\AceConfig-3.0.xml" />
-<Include file="libs\AceConsole-3.0\AceConsole-3.0.xml" />
-<Include file="libs\AceDB-3.0\AceDB-3.0.xml" />
<Include file="libs\AceDBOptions-3.0\AceDBOptions-3.0.xml" />
</Ui>
+++ /dev/null
---- **AceAddon-3.0** provides a template for creating addon objects.
--- It'll provide you with a set of callback functions that allow you to simplify the loading
--- process of your addon.\\
--- Callbacks provided are:\\
--- * **OnInitialize**, which is called directly after the addon is fully loaded.
--- * **OnEnable** which gets called during the PLAYER_LOGIN event, when most of the data provided by the game is already present.
--- * **OnDisable**, which is only called when your addon is manually being disabled.
--- @usage
--- -- A small (but complete) addon, that doesn't do anything,
--- -- but shows usage of the callbacks.
--- local MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
---
--- function MyAddon:OnInitialize()
--- -- do init tasks here, like loading the Saved Variables,
--- -- or setting up slash commands.
--- end
---
--- function MyAddon:OnEnable()
--- -- Do more initialization here, that really enables the use of your addon.
--- -- Register Events, Hook functions, Create Frames, Get information from
--- -- the game that wasn't available in OnInitialize
--- end
---
--- function MyAddon:OnDisable()
--- -- Unhook, Unregister Events, Hide frames that you created.
--- -- You would probably only use an OnDisable if you want to
--- -- build a "standby" mode, or be able to toggle modules on/off.
--- end
--- @class file
--- @name AceAddon-3.0.lua
--- @release $Id: AceAddon-3.0.lua 1084 2013-04-27 20:14:11Z nevcairiel $
-
-local MAJOR, MINOR = "AceAddon-3.0", 12
-local AceAddon, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
-
-if not AceAddon then return end -- No Upgrade needed.
-
-AceAddon.frame = AceAddon.frame or CreateFrame("Frame", "AceAddon30Frame") -- Our very own frame
-AceAddon.addons = AceAddon.addons or {} -- addons in general
-AceAddon.statuses = AceAddon.statuses or {} -- statuses of addon.
-AceAddon.initializequeue = AceAddon.initializequeue or {} -- addons that are new and not initialized
-AceAddon.enablequeue = AceAddon.enablequeue or {} -- addons that are initialized and waiting to be enabled
-AceAddon.embeds = AceAddon.embeds or setmetatable({}, {__index = function(tbl, key) tbl[key] = {} return tbl[key] end }) -- contains a list of libraries embedded in an addon
-
--- Lua APIs
-local tinsert, tconcat, tremove = table.insert, table.concat, table.remove
-local fmt, tostring = string.format, tostring
-local select, pairs, next, type, unpack = select, pairs, next, type, unpack
-local loadstring, assert, error = loadstring, assert, error
-local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
-
--- 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, IsLoggedIn, geterrorhandler
-
---[[
- xpcall safecall implementation
-]]
-local xpcall = xpcall
-
-local function errorhandler(err)
- return geterrorhandler()(err)
-end
-
-local function CreateDispatcher(argCount)
- local code = [[
- local xpcall, eh = ...
- local method, ARGS
- local function call() return method(ARGS) end
-
- local function dispatch(func, ...)
- method = func
- if not method then return end
- ARGS = ...
- return xpcall(call, eh)
- end
-
- return dispatch
- ]]
-
- local ARGS = {}
- for i = 1, argCount do ARGS[i] = "arg"..i end
- code = code:gsub("ARGS", tconcat(ARGS, ", "))
- return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
-end
-
-local Dispatchers = setmetatable({}, {__index=function(self, argCount)
- local dispatcher = CreateDispatcher(argCount)
- rawset(self, argCount, dispatcher)
- return dispatcher
-end})
-Dispatchers[0] = function(func)
- return xpcall(func, errorhandler)
-end
-
-local function safecall(func, ...)
- -- we check to see if the func is passed is actually a function here and don't error when it isn't
- -- this safecall is used for optional functions like OnInitialize OnEnable etc. When they are not
- -- present execution should continue without hinderance
- if type(func) == "function" then
- return Dispatchers[select('#', ...)](func, ...)
- end
-end
-
--- local functions that will be implemented further down
-local Enable, Disable, EnableModule, DisableModule, Embed, NewModule, GetModule, GetName, SetDefaultModuleState, SetDefaultModuleLibraries, SetEnabledState, SetDefaultModulePrototype
-
--- used in the addon metatable
-local function addontostring( self ) return self.name end
-
--- Check if the addon is queued for initialization
-local function queuedForInitialization(addon)
- for i = 1, #AceAddon.initializequeue do
- if AceAddon.initializequeue[i] == addon then
- return true
- end
- end
- return false
-end
-
---- Create a new AceAddon-3.0 addon.
--- Any libraries you specified will be embeded, and the addon will be scheduled for
--- its OnInitialize and OnEnable callbacks.
--- The final addon object, with all libraries embeded, will be returned.
--- @paramsig [object ,]name[, lib, ...]
--- @param object Table to use as a base for the addon (optional)
--- @param name Name of the addon object to create
--- @param lib List of libraries to embed into the addon
--- @usage
--- -- Create a simple addon object
--- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceEvent-3.0")
---
--- -- Create a Addon object based on the table of a frame
--- local MyFrame = CreateFrame("Frame")
--- MyAddon = LibStub("AceAddon-3.0"):NewAddon(MyFrame, "MyAddon", "AceEvent-3.0")
-function AceAddon:NewAddon(objectorname, ...)
- local object,name
- local i=1
- if type(objectorname)=="table" then
- object=objectorname
- name=...
- i=2
- else
- name=objectorname
- end
- if type(name)~="string" then
- error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2)
- end
- if self.addons[name] then
- error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - Addon '%s' already exists."):format(name), 2)
- end
-
- object = object or {}
- object.name = name
-
- local addonmeta = {}
- local oldmeta = getmetatable(object)
- if oldmeta then
- for k, v in pairs(oldmeta) do addonmeta[k] = v end
- end
- addonmeta.__tostring = addontostring
-
- setmetatable( object, addonmeta )
- self.addons[name] = object
- object.modules = {}
- object.orderedModules = {}
- object.defaultModuleLibraries = {}
- Embed( object ) -- embed NewModule, GetModule methods
- self:EmbedLibraries(object, select(i,...))
-
- -- add to queue of addons to be initialized upon ADDON_LOADED
- tinsert(self.initializequeue, object)
- return object
-end
-
-
---- Get the addon object by its name from the internal AceAddon registry.
--- Throws an error if the addon object cannot be found (except if silent is set).
--- @param name unique name of the addon object
--- @param silent if true, the addon is optional, silently return nil if its not found
--- @usage
--- -- Get the Addon
--- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
-function AceAddon:GetAddon(name, silent)
- if not silent and not self.addons[name] then
- error(("Usage: GetAddon(name): 'name' - Cannot find an AceAddon '%s'."):format(tostring(name)), 2)
- end
- return self.addons[name]
-end
-
--- - Embed a list of libraries into the specified addon.
--- This function will try to embed all of the listed libraries into the addon
--- and error if a single one fails.
---
--- **Note:** This function is for internal use by :NewAddon/:NewModule
--- @paramsig addon, [lib, ...]
--- @param addon addon object to embed the libs in
--- @param lib List of libraries to embed into the addon
-function AceAddon:EmbedLibraries(addon, ...)
- for i=1,select("#", ... ) do
- local libname = select(i, ...)
- self:EmbedLibrary(addon, libname, false, 4)
- end
-end
-
--- - Embed a library into the addon object.
--- This function will check if the specified library is registered with LibStub
--- and if it has a :Embed function to call. It'll error if any of those conditions
--- fails.
---
--- **Note:** This function is for internal use by :EmbedLibraries
--- @paramsig addon, libname[, silent[, offset]]
--- @param addon addon object to embed the library in
--- @param libname name of the library to embed
--- @param silent marks an embed to fail silently if the library doesn't exist (optional)
--- @param offset will push the error messages back to said offset, defaults to 2 (optional)
-function AceAddon:EmbedLibrary(addon, libname, silent, offset)
- local lib = LibStub:GetLibrary(libname, true)
- if not lib and not silent then
- error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Cannot find a library instance of %q."):format(tostring(libname)), offset or 2)
- elseif lib and type(lib.Embed) == "function" then
- lib:Embed(addon)
- tinsert(self.embeds[addon], libname)
- return true
- elseif lib then
- error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Library '%s' is not Embed capable"):format(libname), offset or 2)
- end
-end
-
---- Return the specified module from an addon object.
--- Throws an error if the addon object cannot be found (except if silent is set)
--- @name //addon//:GetModule
--- @paramsig name[, silent]
--- @param name unique name of the module
--- @param silent if true, the module is optional, silently return nil if its not found (optional)
--- @usage
--- -- Get the Addon
--- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
--- -- Get the Module
--- MyModule = MyAddon:GetModule("MyModule")
-function GetModule(self, name, silent)
- if not self.modules[name] and not silent then
- error(("Usage: GetModule(name, silent): 'name' - Cannot find module '%s'."):format(tostring(name)), 2)
- end
- return self.modules[name]
-end
-
-local function IsModuleTrue(self) return true end
-
---- Create a new module for the addon.
--- The new module can have its own embeded libraries and/or use a module prototype to be mixed into the module.\\
--- A module has the same functionality as a real addon, it can have modules of its own, and has the same API as
--- an addon object.
--- @name //addon//:NewModule
--- @paramsig name[, prototype|lib[, lib, ...]]
--- @param name unique name of the module
--- @param prototype object to derive this module from, methods and values from this table will be mixed into the module (optional)
--- @param lib List of libraries to embed into the addon
--- @usage
--- -- Create a module with some embeded libraries
--- MyModule = MyAddon:NewModule("MyModule", "AceEvent-3.0", "AceHook-3.0")
---
--- -- Create a module with a prototype
--- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
--- MyModule = MyAddon:NewModule("MyModule", prototype, "AceEvent-3.0", "AceHook-3.0")
-function NewModule(self, name, prototype, ...)
- if type(name) ~= "string" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2) end
- if type(prototype) ~= "string" and type(prototype) ~= "table" and type(prototype) ~= "nil" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'prototype' - table (prototype), string (lib) or nil expected got '%s'."):format(type(prototype)), 2) end
-
- if self.modules[name] then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - Module '%s' already exists."):format(name), 2) end
-
- -- modules are basically addons. We treat them as such. They will be added to the initializequeue properly as well.
- -- NewModule can only be called after the parent addon is present thus the modules will be initialized after their parent is.
- local module = AceAddon:NewAddon(fmt("%s_%s", self.name or tostring(self), name))
-
- module.IsModule = IsModuleTrue
- module:SetEnabledState(self.defaultModuleState)
- module.moduleName = name
-
- if type(prototype) == "string" then
- AceAddon:EmbedLibraries(module, prototype, ...)
- else
- AceAddon:EmbedLibraries(module, ...)
- end
- AceAddon:EmbedLibraries(module, unpack(self.defaultModuleLibraries))
-
- if not prototype or type(prototype) == "string" then
- prototype = self.defaultModulePrototype or nil
- end
-
- if type(prototype) == "table" then
- local mt = getmetatable(module)
- mt.__index = prototype
- setmetatable(module, mt) -- More of a Base class type feel.
- end
-
- safecall(self.OnModuleCreated, self, module) -- Was in Ace2 and I think it could be a cool thing to have handy.
- self.modules[name] = module
- tinsert(self.orderedModules, module)
-
- return module
-end
-
---- Returns the real name of the addon or module, without any prefix.
--- @name //addon//:GetName
--- @paramsig
--- @usage
--- print(MyAddon:GetName())
--- -- prints "MyAddon"
-function GetName(self)
- return self.moduleName or self.name
-end
-
---- Enables the Addon, if possible, return true or false depending on success.
--- This internally calls AceAddon:EnableAddon(), thus dispatching a OnEnable callback
--- and enabling all modules of the addon (unless explicitly disabled).\\
--- :Enable() also sets the internal `enableState` variable to true
--- @name //addon//:Enable
--- @paramsig
--- @usage
--- -- Enable MyModule
--- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
--- MyModule = MyAddon:GetModule("MyModule")
--- MyModule:Enable()
-function Enable(self)
- self:SetEnabledState(true)
-
- -- nevcairiel 2013-04-27: don't enable an addon/module if its queued for init still
- -- it'll be enabled after the init process
- if not queuedForInitialization(self) then
- return AceAddon:EnableAddon(self)
- end
-end
-
---- Disables the Addon, if possible, return true or false depending on success.
--- This internally calls AceAddon:DisableAddon(), thus dispatching a OnDisable callback
--- and disabling all modules of the addon.\\
--- :Disable() also sets the internal `enableState` variable to false
--- @name //addon//:Disable
--- @paramsig
--- @usage
--- -- Disable MyAddon
--- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
--- MyAddon:Disable()
-function Disable(self)
- self:SetEnabledState(false)
- return AceAddon:DisableAddon(self)
-end
-
---- Enables the Module, if possible, return true or false depending on success.
--- Short-hand function that retrieves the module via `:GetModule` and calls `:Enable` on the module object.
--- @name //addon//:EnableModule
--- @paramsig name
--- @usage
--- -- Enable MyModule using :GetModule
--- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
--- MyModule = MyAddon:GetModule("MyModule")
--- MyModule:Enable()
---
--- -- Enable MyModule using the short-hand
--- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
--- MyAddon:EnableModule("MyModule")
-function EnableModule(self, name)
- local module = self:GetModule( name )
- return module:Enable()
-end
-
---- Disables the Module, if possible, return true or false depending on success.
--- Short-hand function that retrieves the module via `:GetModule` and calls `:Disable` on the module object.
--- @name //addon//:DisableModule
--- @paramsig name
--- @usage
--- -- Disable MyModule using :GetModule
--- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
--- MyModule = MyAddon:GetModule("MyModule")
--- MyModule:Disable()
---
--- -- Disable MyModule using the short-hand
--- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
--- MyAddon:DisableModule("MyModule")
-function DisableModule(self, name)
- local module = self:GetModule( name )
- return module:Disable()
-end
-
---- Set the default libraries to be mixed into all modules created by this object.
--- Note that you can only change the default module libraries before any module is created.
--- @name //addon//:SetDefaultModuleLibraries
--- @paramsig lib[, lib, ...]
--- @param lib List of libraries to embed into the addon
--- @usage
--- -- Create the addon object
--- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
--- -- Configure default libraries for modules (all modules need AceEvent-3.0)
--- MyAddon:SetDefaultModuleLibraries("AceEvent-3.0")
--- -- Create a module
--- MyModule = MyAddon:NewModule("MyModule")
-function SetDefaultModuleLibraries(self, ...)
- if next(self.modules) then
- error("Usage: SetDefaultModuleLibraries(...): cannot change the module defaults after a module has been registered.", 2)
- end
- self.defaultModuleLibraries = {...}
-end
-
---- Set the default state in which new modules are being created.
--- Note that you can only change the default state before any module is created.
--- @name //addon//:SetDefaultModuleState
--- @paramsig state
--- @param state Default state for new modules, true for enabled, false for disabled
--- @usage
--- -- Create the addon object
--- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
--- -- Set the default state to "disabled"
--- MyAddon:SetDefaultModuleState(false)
--- -- Create a module and explicilty enable it
--- MyModule = MyAddon:NewModule("MyModule")
--- MyModule:Enable()
-function SetDefaultModuleState(self, state)
- if next(self.modules) then
- error("Usage: SetDefaultModuleState(state): cannot change the module defaults after a module has been registered.", 2)
- end
- self.defaultModuleState = state
-end
-
---- Set the default prototype to use for new modules on creation.
--- Note that you can only change the default prototype before any module is created.
--- @name //addon//:SetDefaultModulePrototype
--- @paramsig prototype
--- @param prototype Default prototype for the new modules (table)
--- @usage
--- -- Define a prototype
--- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
--- -- Set the default prototype
--- MyAddon:SetDefaultModulePrototype(prototype)
--- -- Create a module and explicitly Enable it
--- MyModule = MyAddon:NewModule("MyModule")
--- MyModule:Enable()
--- -- should print "OnEnable called!" now
--- @see NewModule
-function SetDefaultModulePrototype(self, prototype)
- if next(self.modules) then
- error("Usage: SetDefaultModulePrototype(prototype): cannot change the module defaults after a module has been registered.", 2)
- end
- if type(prototype) ~= "table" then
- error(("Usage: SetDefaultModulePrototype(prototype): 'prototype' - table expected got '%s'."):format(type(prototype)), 2)
- end
- self.defaultModulePrototype = prototype
-end
-
---- Set the state of an addon or module
--- This should only be called before any enabling actually happend, e.g. in/before OnInitialize.
--- @name //addon//:SetEnabledState
--- @paramsig state
--- @param state the state of an addon or module (enabled=true, disabled=false)
-function SetEnabledState(self, state)
- self.enabledState = state
-end
-
-
---- Return an iterator of all modules associated to the addon.
--- @name //addon//:IterateModules
--- @paramsig
--- @usage
--- -- Enable all modules
--- for name, module in MyAddon:IterateModules() do
--- module:Enable()
--- end
-local function IterateModules(self) return pairs(self.modules) end
-
--- Returns an iterator of all embeds in the addon
--- @name //addon//:IterateEmbeds
--- @paramsig
-local function IterateEmbeds(self) return pairs(AceAddon.embeds[self]) end
-
---- Query the enabledState of an addon.
--- @name //addon//:IsEnabled
--- @paramsig
--- @usage
--- if MyAddon:IsEnabled() then
--- MyAddon:Disable()
--- end
-local function IsEnabled(self) return self.enabledState end
-local mixins = {
- NewModule = NewModule,
- GetModule = GetModule,
- Enable = Enable,
- Disable = Disable,
- EnableModule = EnableModule,
- DisableModule = DisableModule,
- IsEnabled = IsEnabled,
- SetDefaultModuleLibraries = SetDefaultModuleLibraries,
- SetDefaultModuleState = SetDefaultModuleState,
- SetDefaultModulePrototype = SetDefaultModulePrototype,
- SetEnabledState = SetEnabledState,
- IterateModules = IterateModules,
- IterateEmbeds = IterateEmbeds,
- GetName = GetName,
-}
-local function IsModule(self) return false end
-local pmixins = {
- defaultModuleState = true,
- enabledState = true,
- IsModule = IsModule,
-}
--- Embed( target )
--- target (object) - target object to embed aceaddon in
---
--- this is a local function specifically since it's meant to be only called internally
-function Embed(target, skipPMixins)
- for k, v in pairs(mixins) do
- target[k] = v
- end
- if not skipPMixins then
- for k, v in pairs(pmixins) do
- target[k] = target[k] or v
- end
- end
-end
-
-
--- - Initialize the addon after creation.
--- This function is only used internally during the ADDON_LOADED event
--- It will call the **OnInitialize** function on the addon object (if present),
--- and the **OnEmbedInitialize** function on all embeded libraries.
---
--- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
--- @param addon addon object to intialize
-function AceAddon:InitializeAddon(addon)
- safecall(addon.OnInitialize, addon)
-
- local embeds = self.embeds[addon]
- for i = 1, #embeds do
- local lib = LibStub:GetLibrary(embeds[i], true)
- if lib then safecall(lib.OnEmbedInitialize, lib, addon) end
- end
-
- -- we don't call InitializeAddon on modules specifically, this is handled
- -- from the event handler and only done _once_
-end
-
--- - Enable the addon after creation.
--- Note: This function is only used internally during the PLAYER_LOGIN event, or during ADDON_LOADED,
--- if IsLoggedIn() already returns true at that point, e.g. for LoD Addons.
--- It will call the **OnEnable** function on the addon object (if present),
--- and the **OnEmbedEnable** function on all embeded libraries.\\
--- This function does not toggle the enable state of the addon itself, and will return early if the addon is disabled.
---
--- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
--- Use :Enable on the addon itself instead.
--- @param addon addon object to enable
-function AceAddon:EnableAddon(addon)
- if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
- if self.statuses[addon.name] or not addon.enabledState then return false end
-
- -- set the statuses first, before calling the OnEnable. this allows for Disabling of the addon in OnEnable.
- self.statuses[addon.name] = true
-
- safecall(addon.OnEnable, addon)
-
- -- make sure we're still enabled before continueing
- if self.statuses[addon.name] then
- local embeds = self.embeds[addon]
- for i = 1, #embeds do
- local lib = LibStub:GetLibrary(embeds[i], true)
- if lib then safecall(lib.OnEmbedEnable, lib, addon) end
- end
-
- -- enable possible modules.
- local modules = addon.orderedModules
- for i = 1, #modules do
- self:EnableAddon(modules[i])
- end
- end
- return self.statuses[addon.name] -- return true if we're disabled
-end
-
--- - Disable the addon
--- Note: This function is only used internally.
--- It will call the **OnDisable** function on the addon object (if present),
--- and the **OnEmbedDisable** function on all embeded libraries.\\
--- This function does not toggle the enable state of the addon itself, and will return early if the addon is still enabled.
---
--- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
--- Use :Disable on the addon itself instead.
--- @param addon addon object to enable
-function AceAddon:DisableAddon(addon)
- if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
- if not self.statuses[addon.name] then return false end
-
- -- set statuses first before calling OnDisable, this allows for aborting the disable in OnDisable.
- self.statuses[addon.name] = false
-
- safecall( addon.OnDisable, addon )
-
- -- make sure we're still disabling...
- if not self.statuses[addon.name] then
- local embeds = self.embeds[addon]
- for i = 1, #embeds do
- local lib = LibStub:GetLibrary(embeds[i], true)
- if lib then safecall(lib.OnEmbedDisable, lib, addon) end
- end
- -- disable possible modules.
- local modules = addon.orderedModules
- for i = 1, #modules do
- self:DisableAddon(modules[i])
- end
- end
-
- return not self.statuses[addon.name] -- return true if we're disabled
-end
-
---- Get an iterator over all registered addons.
--- @usage
--- -- Print a list of all installed AceAddon's
--- for name, addon in AceAddon:IterateAddons() do
--- print("Addon: " .. name)
--- end
-function AceAddon:IterateAddons() return pairs(self.addons) end
-
---- Get an iterator over the internal status registry.
--- @usage
--- -- Print a list of all enabled addons
--- for name, status in AceAddon:IterateAddonStatus() do
--- if status then
--- print("EnabledAddon: " .. name)
--- end
--- end
-function AceAddon:IterateAddonStatus() return pairs(self.statuses) end
-
--- Following Iterators are deprecated, and their addon specific versions should be used
--- e.g. addon:IterateEmbeds() instead of :IterateEmbedsOnAddon(addon)
-function AceAddon:IterateEmbedsOnAddon(addon) return pairs(self.embeds[addon]) end
-function AceAddon:IterateModulesOfAddon(addon) return pairs(addon.modules) end
-
--- Event Handling
-local function onEvent(this, event, arg1)
- -- 2011-08-17 nevcairiel - ignore the load event of Blizzard_DebugTools, so a potential startup error isn't swallowed up
- if (event == "ADDON_LOADED" and arg1 ~= "Blizzard_DebugTools") or event == "PLAYER_LOGIN" then
- -- if a addon loads another addon, recursion could happen here, so we need to validate the table on every iteration
- while(#AceAddon.initializequeue > 0) do
- local addon = tremove(AceAddon.initializequeue, 1)
- -- this might be an issue with recursion - TODO: validate
- if event == "ADDON_LOADED" then addon.baseName = arg1 end
- AceAddon:InitializeAddon(addon)
- tinsert(AceAddon.enablequeue, addon)
- end
-
- if IsLoggedIn() then
- while(#AceAddon.enablequeue > 0) do
- local addon = tremove(AceAddon.enablequeue, 1)
- AceAddon:EnableAddon(addon)
- end
- end
- end
-end
-
-AceAddon.frame:RegisterEvent("ADDON_LOADED")
-AceAddon.frame:RegisterEvent("PLAYER_LOGIN")
-AceAddon.frame:SetScript("OnEvent", onEvent)
-
--- upgrade embeded
-for name, addon in pairs(AceAddon.addons) do
- Embed(addon, true)
-end
-
--- 2010-10-27 nevcairiel - add new "orderedModules" table
-if oldminor and oldminor < 10 then
- for name, addon in pairs(AceAddon.addons) do
- addon.orderedModules = {}
- for module_name, module in pairs(addon.modules) do
- tinsert(addon.orderedModules, module)
- end
- end
-end
+++ /dev/null
-<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="AceAddon-3.0.lua"/>
-</Ui>
]]
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)
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
<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"/>
+++ /dev/null
---- 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
+++ /dev/null
-<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>
+++ /dev/null
---- **AceConsole-3.0** provides registration facilities for slash commands.
--- You can register slash commands to your custom functions and use the `GetArgs` function to parse them
--- to your addons individual needs.
---
--- **AceConsole-3.0** can be embeded into your addon, either explicitly by calling AceConsole:Embed(MyAddon) or by
--- specifying it as an embeded library in your AceAddon. All functions will be available on your addon object
--- and can be accessed directly, without having to explicitly call AceConsole itself.\\
--- It is recommended to embed AceConsole, otherwise you'll have to specify a custom `self` on all calls you
--- make into AceConsole.
--- @class file
--- @name AceConsole-3.0
--- @release $Id: AceConsole-3.0.lua 1143 2016-07-11 08:52:03Z nevcairiel $
-local MAJOR,MINOR = "AceConsole-3.0", 7
-
-local AceConsole, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
-
-if not AceConsole then return end -- No upgrade needed
-
-AceConsole.embeds = AceConsole.embeds or {} -- table containing objects AceConsole is embedded in.
-AceConsole.commands = AceConsole.commands or {} -- table containing commands registered
-AceConsole.weakcommands = AceConsole.weakcommands or {} -- table containing self, command => func references for weak commands that don't persist through enable/disable
-
--- Lua APIs
-local tconcat, tostring, select = table.concat, tostring, select
-local type, pairs, error = type, pairs, error
-local format, strfind, strsub = string.format, string.find, string.sub
-local max = math.max
-
--- 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: DEFAULT_CHAT_FRAME, SlashCmdList, hash_SlashCmdList
-
-local tmp={}
-local function Print(self,frame,...)
- local n=0
- if self ~= AceConsole then
- n=n+1
- tmp[n] = "|cff33ff99"..tostring( self ).."|r:"
- end
- for i=1, select("#", ...) do
- n=n+1
- tmp[n] = tostring(select(i, ...))
- end
- frame:AddMessage( tconcat(tmp," ",1,n) )
-end
-
---- Print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
--- @paramsig [chatframe ,] ...
--- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
--- @param ... List of any values to be printed
-function AceConsole:Print(...)
- local frame = ...
- if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
- return Print(self, frame, select(2,...))
- else
- return Print(self, DEFAULT_CHAT_FRAME, ...)
- end
-end
-
-
---- Formatted (using format()) print to DEFAULT_CHAT_FRAME or given ChatFrame (anything with an .AddMessage function)
--- @paramsig [chatframe ,] "format"[, ...]
--- @param chatframe Custom ChatFrame to print to (or any frame with an .AddMessage function)
--- @param format Format string - same syntax as standard Lua format()
--- @param ... Arguments to the format string
-function AceConsole:Printf(...)
- local frame = ...
- if type(frame) == "table" and frame.AddMessage then -- Is first argument something with an .AddMessage member?
- return Print(self, frame, format(select(2,...)))
- else
- return Print(self, DEFAULT_CHAT_FRAME, format(...))
- end
-end
-
-
-
-
---- Register a simple chat command
--- @param command Chat command to be registered WITHOUT leading "/"
--- @param func Function to call when the slash command is being used (funcref or methodname)
--- @param persist if false, the command will be soft disabled/enabled when aceconsole is used as a mixin (default: true)
-function AceConsole:RegisterChatCommand( command, func, persist )
- if type(command)~="string" then error([[Usage: AceConsole:RegisterChatCommand( "command", func[, persist ]): 'command' - expected a string]], 2) end
-
- if persist==nil then persist=true end -- I'd rather have my addon's "/addon enable" around if the author screws up. Having some extra slash regged when it shouldnt be isn't as destructive. True is a better default. /Mikk
-
- local name = "ACECONSOLE_"..command:upper()
-
- if type( func ) == "string" then
- SlashCmdList[name] = function(input, editBox)
- self[func](self, input, editBox)
- end
- else
- SlashCmdList[name] = func
- end
- _G["SLASH_"..name.."1"] = "/"..command:lower()
- AceConsole.commands[command] = name
- -- non-persisting commands are registered for enabling disabling
- if not persist then
- if not AceConsole.weakcommands[self] then AceConsole.weakcommands[self] = {} end
- AceConsole.weakcommands[self][command] = func
- end
- return true
-end
-
---- Unregister a chatcommand
--- @param command Chat command to be unregistered WITHOUT leading "/"
-function AceConsole:UnregisterChatCommand( command )
- local name = AceConsole.commands[command]
- if name then
- SlashCmdList[name] = nil
- _G["SLASH_" .. name .. "1"] = nil
- hash_SlashCmdList["/" .. command:upper()] = nil
- AceConsole.commands[command] = nil
- end
-end
-
---- Get an iterator over all Chat Commands registered with AceConsole
--- @return Iterator (pairs) over all commands
-function AceConsole:IterateChatCommands() return pairs(AceConsole.commands) end
-
-
-local function nils(n, ...)
- if n>1 then
- return nil, nils(n-1, ...)
- elseif n==1 then
- return nil, ...
- else
- return ...
- end
-end
-
-
---- Retreive one or more space-separated arguments from a string.
--- Treats quoted strings and itemlinks as non-spaced.
--- @param str The raw argument string
--- @param numargs How many arguments to get (default 1)
--- @param startpos Where in the string to start scanning (default 1)
--- @return Returns arg1, arg2, ..., nextposition\\
--- Missing arguments will be returned as nils. 'nextposition' is returned as 1e9 at the end of the string.
-function AceConsole:GetArgs(str, numargs, startpos)
- numargs = numargs or 1
- startpos = max(startpos or 1, 1)
-
- local pos=startpos
-
- -- find start of new arg
- pos = strfind(str, "[^ ]", pos)
- if not pos then -- whoops, end of string
- return nils(numargs, 1e9)
- end
-
- if numargs<1 then
- return pos
- end
-
- -- quoted or space separated? find out which pattern to use
- local delim_or_pipe
- local ch = strsub(str, pos, pos)
- if ch=='"' then
- pos = pos + 1
- delim_or_pipe='([|"])'
- elseif ch=="'" then
- pos = pos + 1
- delim_or_pipe="([|'])"
- else
- delim_or_pipe="([| ])"
- end
-
- startpos = pos
-
- while true do
- -- find delimiter or hyperlink
- local ch,_
- pos,_,ch = strfind(str, delim_or_pipe, pos)
-
- if not pos then break end
-
- if ch=="|" then
- -- some kind of escape
-
- if strsub(str,pos,pos+1)=="|H" then
- -- It's a |H....|hhyper link!|h
- pos=strfind(str, "|h", pos+2) -- first |h
- if not pos then break end
-
- pos=strfind(str, "|h", pos+2) -- second |h
- if not pos then break end
- elseif strsub(str,pos, pos+1) == "|T" then
- -- It's a |T....|t texture
- pos=strfind(str, "|t", pos+2)
- if not pos then break end
- end
-
- pos=pos+2 -- skip past this escape (last |h if it was a hyperlink)
-
- else
- -- found delimiter, done with this arg
- return strsub(str, startpos, pos-1), AceConsole:GetArgs(str, numargs-1, pos+1)
- end
-
- end
-
- -- search aborted, we hit end of string. return it all as one argument. (yes, even if it's an unterminated quote or hyperlink)
- return strsub(str, startpos), nils(numargs-1, 1e9)
-end
-
-
---- embedding and embed handling
-
-local mixins = {
- "Print",
- "Printf",
- "RegisterChatCommand",
- "UnregisterChatCommand",
- "GetArgs",
-}
-
--- Embeds AceConsole into the target object making the functions from the mixins list available on target:..
--- @param target target object to embed AceBucket in
-function AceConsole:Embed( target )
- for k, v in pairs( mixins ) do
- target[v] = self[v]
- end
- self.embeds[target] = true
- return target
-end
-
-function AceConsole:OnEmbedEnable( target )
- if AceConsole.weakcommands[target] then
- for command, func in pairs( AceConsole.weakcommands[target] ) do
- target:RegisterChatCommand( command, func, false, true ) -- nonpersisting and silent registry
- end
- end
-end
-
-function AceConsole:OnEmbedDisable( target )
- if AceConsole.weakcommands[target] then
- for command, func in pairs( AceConsole.weakcommands[target] ) do
- target:UnregisterChatCommand( command ) -- TODO: this could potentially unregister a command from another application in case of command conflicts. Do we care?
- end
- end
-end
-
-for addon in pairs(AceConsole.embeds) do
- AceConsole:Embed(addon)
-end
+++ /dev/null
-<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="AceConsole-3.0.lua"/>
-</Ui>
+++ /dev/null
---- **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
+++ /dev/null
-<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>
-- List them here for Mikk's FindGlobals script
-- GLOBALS: geterrorhandler, LibStub
---local con = LibStub("AceConsole-3.0",true)
-
AceGUI.WidgetRegistry = AceGUI.WidgetRegistry or {}
AceGUI.LayoutRegistry = AceGUI.LayoutRegistry or {}
AceGUI.WidgetBase = AceGUI.WidgetBase or {}