/trunk
## Interface: 30100 |
## Interface: 30200 |
## Title: MyThreat |
## Notes: Summarized threat information based on the WoW Threat API. |
## Author: Brimm |
## SavedVariables: MyThreatDB |
## SavedVariablesPerCharacter: MyThreatDBPC |
## Version: 1.5.1 |
## Version: 1.5.2 |
## X-Category: Interface Enhancements |
## OptionalDeps: Ace3 |
--[[ $Id: CallbackHandler-1.0.lua 60697 2008-02-09 16:51:20Z nevcairiel $ ]] |
--[[ $Id: CallbackHandler-1.0.lua 504 2008-02-07 11:04:06Z nevcairiel $ ]] |
local MAJOR, MINOR = "CallbackHandler-1.0", 3 |
local CallbackHandler = LibStub:NewLibrary(MAJOR, MINOR) |
--[[ $Id: AceDBOptions-3.0.lua 81438 2008-09-06 13:44:36Z nevcairiel $ ]] |
local ACEDBO_MAJOR, ACEDBO_MINOR = "AceDBOptions-3.0", 7 |
--- 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 765 2009-04-03 19:14:41Z nevcairiel $ |
local ACEDBO_MAJOR, ACEDBO_MINOR = "AceDBOptions-3.0", 10 |
local AceDBOptions, oldminor = LibStub:NewLibrary(ACEDBO_MAJOR, ACEDBO_MINOR) |
if not AceDBOptions then return end -- No upgrade needed |
L["profiles"] = "íë¡í" |
L["profiles_sub"] = "íë¡í ì¤ì " |
elseif LOCALE == "esES" then |
L["default"] = "Por defecto" |
L["intro"] = "Puedes cambiar el perfil activo de tal manera que cada personaje tenga diferentes configuraciones." |
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"] = "Reiniciar Perfil" |
L["reset_sub"] = "Reinicar el perfil actual al de por defecto" |
L["choose_desc"] = "Puedes crear un nuevo perfil introduciendo un nombre en el recuadro o puedes seleccionar un perfil de los ya existentes." |
L["new"] = "Nuevo" |
L["new_sub"] = "Crear un nuevo perfil vacio." |
L["choose"] = "Perfiles existentes" |
L["choose_sub"] = "Selecciona uno de los perfiles disponibles." |
L["copy_desc"] = "Copia los ajustes de un perfil existente al perfil actual." |
L["copy"] = "Copiar de" |
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"] = "Borrar un Perfil" |
L["delete_sub"] = "Borra un perfil de la base de datos." |
L["delete_confirm"] = "¿Estas seguro que quieres borrar el perfil seleccionado?" |
L["profiles"] = "Perfiles" |
L["profiles_sub"] = "Manejar Perfiles" |
elseif LOCALE == "zhTW" then |
L["default"] = "é è¨" |
L["intro"] = "ä½ å¯ä»¥é¸æä¸åæ´»åçè³æè¨å®æªï¼éæ¨£ä½ çæ¯åè§è²å°±å¯ä»¥ææä¸åçè¨å®å¼ï¼å¯ä»¥çµ¦ä½ çæ件è¨å®å¸¶ä¾æ¥µå¤§çéæ´»æ§ã" |
L["profiles_sub"] = "管çé ç½®æ件" |
elseif LOCALE == "ruRU" then |
L["default"] = "Ðо ÑмолÑаниÑ" |
L["intro"] = "ÐÑ Ð¼Ð¾Ð¶ÐµÑе ÑмениÑÑ Ð°ÐºÑивнÑй пÑоÑÐ¸Ð»Ñ ÐÐ, ÑÑим Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе ÑÑÑанавливаÑÑ ÑазлиÑнÑе наÑÑÑойки Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ пеÑÑонажа." |
L["reset_desc"] = "СбÑÐ¾Ñ ÑекÑÑего пÑоÑÐ¸Ð»Ñ Ð½Ð° его ÑÑандаÑÑнÑе знаÑениÑ, в Ñом ÑлÑÑаи еÑли ваÑа конÑигÑÑаÑÐ¸Ñ Ð¸ÑпоÑÑена, или Ð²Ñ Ð¶ÐµÐ»Ð°ÐµÑе вÑÑ Ð¿ÐµÑенаÑÑÑоиÑÑ Ð·Ð°Ð½Ð¾Ð²Ð¾." |
L["intro"] = "ÐзменÑÑ Ð°ÐºÑивнÑй пÑоÑилÑ, Ð²Ñ Ð¼Ð¾Ð¶ÐµÑе задаÑÑ ÑазлиÑнÑе наÑÑÑойки модиÑикаÑий Ð´Ð»Ñ ÐºÐ°Ð¶Ð´Ð¾Ð³Ð¾ пеÑÑонажа." |
L["reset_desc"] = "ÐÑли ваÑа конÑигÑÑаÑии иÑпоÑÑена или еÑли Ð²Ñ Ñ Ð¾ÑиÑе наÑÑÑоиÑÑ Ð²ÑÑ Ð·Ð°Ð½Ð¾Ð²Ð¾ - ÑбÑоÑÑÑе ÑекÑÑий пÑоÑÐ¸Ð»Ñ Ð½Ð° ÑÑандаÑÑнÑе знаÑениÑ." |
L["reset"] = "СбÑÐ¾Ñ Ð¿ÑоÑилÑ" |
L["reset"] = "СбÑÐ¾Ñ ÑекÑÑего пÑоÑÐ¸Ð»Ñ Ð½Ð° ÑÑандаÑÑнÑй" |
L["choose_desc"] = "ÐÑ Ð¼Ð¾Ð¶ÐµÑе ÑоздаÑÑ Ð½Ð¾Ð²Ñй пÑоÑÐ¸Ð»Ñ Ð²Ð²ÐµÐ´Ñ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ðµ в поле ввода, или вÑбÑаÑÑ Ð¾Ð´Ð¸Ð½ из Ñже ÑÑÑеÑÑвÑÑÑÐ¸Ñ Ð¿ÑоÑилей." |
L["reset_sub"] = "СбÑÐ¾Ñ ÑекÑÑего пÑоÑÐ¸Ð»Ñ Ð½Ð° ÑÑандаÑÑнÑй" |
L["choose_desc"] = "ÐÑ Ð¼Ð¾Ð¶ÐµÑе ÑоздаÑÑ Ð½Ð¾Ð²Ñй пÑоÑилÑ, Ð²Ð²ÐµÐ´Ñ Ð½Ð°Ð·Ð²Ð°Ð½Ð¸Ðµ в поле ввода, или вÑбÑаÑÑ Ð¾Ð´Ð¸Ð½ из Ñже ÑÑÑеÑÑвÑÑÑÐ¸Ñ Ð¿ÑоÑилей." |
L["new"] = "ÐовÑй" |
L["new_sub"] = "СоздаÑÑ Ð½Ð¾Ð²Ñй ÑиÑÑÑй пÑоÑилÑ." |
L["choose"] = "ÐÑоÑилÑ" |
L["choose_sub"] = "ÐÑбеÑиÑе один из Ñже доÑÑÑпнÑÑ Ð¿ÑоÑилей." |
L["copy_desc"] = "СкопиÑоваÑÑ Ð½Ð°ÑÑÑойки пÑоÑÐ¸Ð»Ñ Ð² на даннÑй Ð¼Ð¾Ð¼ÐµÐ½Ñ Ð°ÐºÑивнÑй пÑоÑилÑ." |
L["copy"] = "СкопиÑоваÑÑ Ñ" |
L["new_sub"] = "СоздаÑÑ Ð½Ð¾Ð²Ñй ÑиÑÑÑй пÑоÑилÑ" |
L["choose"] = "СÑÑеÑÑвÑÑÑие пÑоÑили" |
L["choose_sub"] = "ÐÑÐ±Ð¾Ñ Ð¾Ð´Ð¸Ð½Ð¾Ð³Ð¾ из Ñже доÑÑÑпнÑÑ Ð¿ÑоÑилей" |
L["copy_desc"] = "СкопиÑоваÑÑ Ð½Ð°ÑÑÑойки из вÑбÑанного пÑоÑÐ¸Ð»Ñ Ð² акÑивнÑй." |
L["copy"] = "СкопиÑоваÑÑ Ð¸Ð·" |
L["delete_desc"] = "УдалиÑÑ ÑÑÑеÑÑвÑÑÑий и неиÑполÑзÑемÑй пÑоÑÐ¸Ð»Ñ Ð¸Ð· ÐÐ Ð´Ð»Ñ ÑÐ¾Ñ ÑÐ°Ð½ÐµÐ½Ð¸Ñ Ð¼ÐµÑÑа, и оÑиÑÑиÑÑ SavedVariables Ñайл." |
L["delete"] = "УдалиÑÑ Ð¿ÑоÑилÑ" |
L["delete_sub"] = "Ð£Ð´Ð°Ð»ÐµÐ½Ð¸Ñ Ð¿ÑоÑÐ¸Ð»Ñ Ð¸Ð· ÐÐ." |
L["delete_confirm"] = "ÐÑ ÑвеÑÐµÐ½Ñ ÑÑо Ð²Ñ Ñ Ð¾ÑиÑе ÑдалиÑÑ Ð²ÑбÑаннÑй пÑоÑилÑ?" |
L["profiles"] = "ÐÑоÑилÑ" |
L["delete_sub"] = "Удаление пÑоÑÐ¸Ð»Ñ Ð¸Ð· ÐÐ" |
L["delete_confirm"] = "ÐÑ ÑвеÑенÑ, ÑÑо Ð²Ñ Ñ Ð¾ÑиÑе ÑдалиÑÑ Ð²ÑбÑаннÑй пÑоÑилÑ?" |
L["profiles"] = "ÐÑоÑили" |
L["profiles_sub"] = "УпÑавление пÑоÑилÑми" |
end |
local defaultProfiles |
local tmpprofiles = {} |
--[[ |
getProfileList(db, common, nocurrent) |
db - the db object to retrieve the profiles from |
common (boolean) - if common is true, getProfileList will add the default profiles to the return list, even if they have not been created yet |
nocurrent (boolean) - if true then getProfileList will not display the current profile in the list |
]]-- |
-- 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 = {} |
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) |
get = false, |
set = "CopyProfile", |
values = "ListProfiles", |
disabled = "HasNoProfiles", |
arg = "nocurrent", |
}, |
deldesc = { |
get = false, |
set = "DeleteProfile", |
values = "ListProfiles", |
disabled = "HasNoProfiles", |
arg = "nocurrent", |
confirm = true, |
confirmText = L["delete_confirm"], |
}, |
} |
--[[ |
GetOptionsTable(db) |
db - the database object to create the options table for |
creates and returns a option table to be used in your addon |
]] |
--- 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", |
--[[ $Id: AceEvent-3.0.lua 60131 2008-02-03 13:03:56Z nevcairiel $ ]] |
--- AceEvent-3.0 provides event registration and secure dispatching. |
-- All dispatching is done using **CallbackHandler-1.0**. AceEvent is a simple wrapper around |
-- CallbackHandler, and dispatches all game events or addon message to the registrees. |
-- |
-- **AceEvent-3.0** can be embeded into your addon, either explicitly by calling AceEvent: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 AceEvent itself.\\ |
-- It is recommended to embed AceEvent, otherwise you'll have to specify a custom `self` on all calls you |
-- make into AceEvent. |
-- @class file |
-- @name AceEvent-3.0 |
-- @release $Id: AceEvent-3.0.lua 766 2009-04-04 08:26:05Z nevcairiel $ |
local MAJOR, MINOR = "AceEvent-3.0", 3 |
local AceEvent = LibStub:NewLibrary(MAJOR, MINOR) |
"RegisterMessage", "UnregisterMessage", |
"SendMessage", |
"UnregisterAllEvents", "UnregisterAllMessages", |
} |
} |
-- AceEvent:Embed( target ) |
-- target (object) - target object to embed AceEvent in |
-- |
--- Register for a Blizzard Event. |
-- The callback will always be called with the event as the first argument, and if supplied, the `arg` as second argument. |
-- Any arguments to the event will be passed on after that. |
-- @name AceEvent:RegisterEvent |
-- @class function |
-- @paramsig event[, callback [, arg]] |
-- @param event The event to register for |
-- @param callback The callback function to call when the event is triggered (funcref or method, defaults to a method with the event name) |
-- @param arg An optional argument to pass to the callback function |
--- Unregister an event. |
-- @name AceEvent:UnregisterEvent |
-- @class function |
-- @paramsig event |
-- @param event The event to unregister |
--- Register for a custom AceEvent-internal message. |
-- The callback will always be called with the event as the first argument, and if supplied, the `arg` as second argument. |
-- Any arguments to the event will be passed on after that. |
-- @name AceEvent:RegisterMessage |
-- @class function |
-- @paramsig message[, callback [, arg]] |
-- @param message The message to register for |
-- @param callback The callback function to call when the message is triggered (funcref or method, defaults to a method with the event name) |
-- @param arg An optional argument to pass to the callback function |
--- Unregister a message |
-- @name AceEvent:UnregisterMessage |
-- @class function |
-- @paramsig message |
-- @param message The message to unregister |
--- Send a message over the AceEvent-3.0 internal message system to other addons registered for this message. |
-- @name AceEvent:SendMessage |
-- @class function |
-- @paramsig message, ... |
-- @param message The message to send |
-- @param ... Any arguments to the message |
-- Embeds AceEvent into the target object making the functions from the mixins list available on target:.. |
-- @param target target object to embed AceEvent in |
function AceEvent:Embed(target) |
for k, v in pairs(mixins) do |
target[v] = self[v] |
--[[ $Id: AceConsole-3.0.lua 74633 2008-05-21 08:20:50Z nevcairiel $ ]] |
--- **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 779 2009-04-05 08:52:46Z nevcairiel $ |
local MAJOR,MINOR = "AceConsole-3.0", 6 |
local AceConsole, oldminor = LibStub:NewLibrary(MAJOR, MINOR) |
local strsub = string.sub |
local max = math.max |
-- AceConsole:Print( [chatframe,] ... ) |
-- |
-- Print to DEFAULT_CHAT_FRAME or given chatframe (anything with an .AddMessage member) |
--- 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 text = "" |
if self ~= AceConsole then |
end |
-- AceConsole:RegisterChatCommand(. command, func, persist ) |
-- |
-- command (string) - chat command to be registered WITHOUT leading "/" |
-- func (function|membername) - function to call, or self[membername](self, ...) call |
-- persist (boolean) - false: the command will be soft disabled/enabled when aceconsole is used as a mixin (default: true) |
-- |
-- Register a simple chat command |
--- 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 |
local name = "ACECONSOLE_"..command:upper() |
if type( func ) == "string" then |
SlashCmdList[name] = function(input) |
self[func](self, input) |
SlashCmdList[name] = function(input, editBox) |
self[func](self, input, editBox) |
end |
else |
SlashCmdList[name] = func |
return true |
end |
-- AceConsole:UnregisterChatCommand( command ) |
-- |
-- Unregister a chatcommand |
--- Unregister a chatcommand |
-- @param command Chat command to be unregistered WITHOUT leading "/" |
function AceConsole:UnregisterChatCommand( command ) |
local name = AceConsole.commands[command] |
if name then |
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 |
end |
-- AceConsole:GetArgs(string, numargs, startpos) |
-- |
-- Retreive one or more space-separated arguments from a string. |
--- Retreive one or more space-separated arguments from a string. |
-- Treats quoted strings and itemlinks as non-spaced. |
-- |
-- string - The raw argument string |
-- numargs - How many arguments to get (default 1) |
-- startpos - Where in the string to start scanning (default 1) |
-- |
-- Returns arg1, arg2, ..., nextposition |
-- @param string 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) |
"GetArgs", |
} |
-- AceConsole:Embed( target ) |
-- target (object) - target object to embed AceBucket in |
-- |
-- 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] |
<Script file="widgets\AceGUIWidget-Label.lua"/> |
<Script file="widgets\AceGUIWidget-MultiLineEditBox.lua"/> |
<Script file="widgets\AceGUIWidget-BlizOptionsGroup.lua"/> |
<Script file="widgets\AceGUIWidget-InteractiveLabel.lua"/> |
<Script file="widgets\AceGUIWidget-Icon.lua"/> |
</Ui> |
--[[ $Id: AceGUI-3.0.lua 81438 2008-09-06 13:44:36Z nevcairiel $ ]] |
local ACEGUI_MAJOR, ACEGUI_MINOR = "AceGUI-3.0", 16 |
--- **AceGUI-3.0** provides access to numerous widgets which can be used to create GUIs. |
-- AceGUI is used by AceConfigDialog to create the option GUIs, but you can use it by itself |
-- to create any custom GUI. There are more extensive examples in the test suite in the Ace3 |
-- stand-alone distribution. |
-- |
-- **Note**: When using AceGUI-3.0 directly, please do not modify the frames of the widgets directly, |
-- as any "unknown" change to the widgets will cause addons that get your widget out of the widget pool |
-- to misbehave. If you think some part of a widget should be modifiable, please open a ticket, and we'll |
-- implement a proper API to modify it. |
-- @usage |
-- local AceGUI = LibStub("AceGUI-3.0") |
-- -- Create a container frame |
-- local f = AceGUI:Create("Frame") |
-- f:SetCallback("OnClose",function(widget) AceGUI:Release(widget) end) |
-- f:SetTitle("AceGUI-3.0 Example") |
-- f:SetStatusText("Status Bar") |
-- f:SetLayout("Flow") |
-- -- Create a button |
-- local btn = AceGUI:Create("Button") |
-- btn:SetWidth(170) |
-- btn:SetText("Button !") |
-- btn:SetCallback("OnClick", function() print("Click!") end) |
-- -- Add the button to the container |
-- f:AddChild(btn) |
-- @class file |
-- @name AceGUI-3.0 |
-- @release $Id: AceGUI-3.0.lua 815 2009-07-08 20:58:17Z nevcairiel $ |
local ACEGUI_MAJOR, ACEGUI_MINOR = "AceGUI-3.0", 25 |
local AceGUI, oldminor = LibStub:NewLibrary(ACEGUI_MAJOR, ACEGUI_MINOR) |
if not AceGUI then return end -- No upgrade needed |
-- Gets a widget Object |
--- Create a new Widget of the given type. |
-- This function will instantiate a new widget (or use one from the widget pool), and call the |
-- OnAcquire function on it, before returning. |
-- @param type The type of the widget. |
-- @return The newly created widget. |
function AceGUI:Create(type) |
local reg = WidgetRegistry |
if reg[type] then |
widget:OnAcquire() |
else |
error(("Widget type %s doesn't supply an OnAcquire Function"):format(type)) |
end |
end |
-- Set the default Layout ('List') |
safecall(widget.SetLayout, widget, 'List') |
safecall(widget.ResumeLayout, widget) |
return widget |
end |
end |
-- Releases a widget Object |
--- Releases a widget Object. |
-- This function calls OnRelease on the widget and places it back in the widget pool. |
-- Any data on the widget is being erased, and the widget will be hidden.\\ |
-- If this widget is a Container-Widget, all of its Child-Widgets will be releases as well. |
-- @param widget The widget to release |
function AceGUI:Release(widget) |
safecall( widget.PauseLayout, widget ) |
widget:Fire("OnRelease") |
for k in pairs(widget.events) do |
widget.events[k] = nil |
end |
widget.width = nil |
--widget.frame:SetParent(nil) |
widget.width = nil |
widget.relWidth = nil |
widget.height = nil |
widget.relHeight = nil |
widget.noAutoHeight = nil |
widget.frame:ClearAllPoints() |
widget.frame:Hide() |
widget.frame:SetParent(nil) |
widget.frame:SetParent(UIParent) |
widget.frame.width = nil |
widget.frame.height = nil |
if widget.content then |
widget.content.width = nil |
widget.content.height = nil |
-- Focus -- |
----------- |
----- |
-- Called when a widget has taken focus |
--- Called when a widget has taken focus. |
-- e.g. Dropdowns opening, Editboxes gaining kb focus |
----- |
-- @param widget The widget that should be focused |
function AceGUI:SetFocus(widget) |
if self.FocusedWidget and self.FocusedWidget ~= widget then |
safecall(self.FocusedWidget.ClearFocus, self.FocusedWidget) |
self.FocusedWidget = widget |
end |
----- |
-- Called when something has happened that could cause widgets with focus to drop it |
--- Called when something has happened that could cause widgets with focus to drop it |
-- e.g. titlebar of a frame being clicked |
----- |
function AceGUI:ClearFocus() |
if self.FocusedWidget then |
safecall(self.FocusedWidget.ClearFocus, self.FocusedWidget) |
frame:SetParent(nil) |
frame:SetParent(parent.content) |
self.parent = parent |
fixlevels(parent.frame,parent.frame:GetChildren()) |
--fixlevels(parent.frame,parent.frame:GetChildren()) |
end |
WidgetBase.SetCallback = function(self, name, func) |
end |
end |
WidgetBase.SetRelativeWidth = function(self, width) |
if width <= 0 or width > 1 then |
error(":SetRelativeWidth(width): Invalid relative width.", 2) |
end |
self.relWidth = width |
self.width = "relative" |
end |
WidgetBase.SetHeight = function(self, height) |
self.frame:SetHeight(height) |
self.frame.height = height |
self:OnHeightSet(height) |
end |
end |
--[[ WidgetBase.SetRelativeHeight = function(self, height) |
if height <= 0 or height > 1 then |
error(":SetRelativeHeight(height): Invalid relative height.", 2) |
end |
self.relHeight = height |
self.height = "relative" |
end ]] |
WidgetBase.IsVisible = function(self) |
return self.frame:IsVisible() |
-- end |
end |
WidgetContainerBase.AddChild = function(self, child) |
tinsert(self.children,child) |
WidgetContainerBase.AddChild = function(self, child, beforeWidget) |
if beforeWidget then |
local siblingIndex = 1 |
for _, widget in pairs(self.children) do |
if widget == beforeWidget then |
break |
end |
siblingIndex = siblingIndex + 1 |
end |
tinsert(self.children, siblingIndex, child) |
else |
tinsert(self.children, child) |
end |
child:SetParent(self) |
child.frame:Show() |
self:DoLayout() |
end |
WidgetContainerBase.AddChildren = function(self, ...) |
for i = 1, select("#", ...) do |
local child = select(i, ...) |
tinsert(self.children, child) |
child:SetParent(self) |
child.frame:Show() |
end |
self:DoLayout() |
end |
WidgetContainerBase.ReleaseChildren = function(self) |
local children = self.children |
for i in ipairs(children) do |
for i = 1,#children do |
AceGUI:Release(children[i]) |
children[i] = nil |
end |
self.LayoutFunc = AceGUI:GetLayout(Layout) |
end |
WidgetContainerBase.SetAutoAdjustHeight = function(self, adjust) |
if adjust then |
self.noAutoHeight = nil |
else |
self.noAutoHeight = true |
end |
end |
local function FrameResize(this) |
local self = this.obj |
if this:GetWidth() and this:GetHeight() then |
setmetatable(WidgetContainerBase,{__index=WidgetBase}) |
--One of these function should be called on each Widget Instance as part of its creation process |
--- Register a widget-class as a container for newly created widgets. |
-- @param widget The widget class |
function AceGUI:RegisterAsContainer(widget) |
widget.children = {} |
widget.userdata = {} |
widget:SetLayout("List") |
end |
--- Register a widget-class as a widget. |
-- @param widget The widget class |
function AceGUI:RegisterAsWidget(widget) |
widget.userdata = {} |
widget.events = {} |
------------------ |
-- Widget API -- |
------------------ |
-- Registers a widget Constructor, this function returns a new instance of the Widget |
--- Registers a widget Constructor, this function returns a new instance of the Widget |
-- @param Name The name of the widget |
-- @param Constructor The widget constructor function |
-- @param Version The version of the widget |
function AceGUI:RegisterWidgetType(Name, Constructor, Version) |
assert(type(Constructor) == "function") |
assert(type(Version) == "number") |
WidgetRegistry[Name] = Constructor |
end |
-- Registers a Layout Function |
--- Registers a Layout Function |
-- @param Name The name of the layout |
-- @param LayoutFunc Reference to the layout function |
function AceGUI:RegisterLayout(Name, LayoutFunc) |
assert(type(LayoutFunc) == "function") |
if type(Name) == "string" then |
LayoutRegistry[Name] = LayoutFunc |
end |
--- Get a Layout Function from the registry |
-- @param Name The name of the layout |
function AceGUI:GetLayout(Name) |
if type(Name) == "string" then |
Name = Name:upper() |
AceGUI.counts = AceGUI.counts or {} |
--- A type-based counter to count the number of widgets created. |
-- This is used by widgets that require a named frame, e.g. when a Blizzard |
-- Template requires it. |
-- @param type The widget type |
function AceGUI:GetNextWidgetNum(type) |
if not self.counts[type] then |
self.counts[type] = 0 |
if child.DoLayout then |
child:DoLayout() |
end |
elseif child.width == "relative" then |
child:SetWidth(width * child.relWidth) |
if child.OnWidthSet then |
child:OnWidthSet(content.width or content:GetWidth()) |
end |
if child.DoLayout then |
child:DoLayout() |
end |
end |
height = height + (frame.height or frame:GetHeight() or 0) |
lastframeoffset = frameoffset |
frameoffset = child.alignoffset or (frameheight / 2) |
if child.width == "relative" then |
framewidth = width * child.relWidth |
end |
frame:Show() |
frame:ClearAllPoints() |
if i == 1 then |
-- anchor the first control to the top left |
--frame:SetPoint("TOPLEFT",content,"TOPLEFT",0,0) |
frame:SetPoint("TOPLEFT",content,"TOPLEFT",0,0) |
rowheight = frameheight |
rowoffset = frameoffset |
rowstart = frame |
rowstartoffset = frameoffset |
rowheight = frameheight |
rowoffset = frameoffset |
usedwidth = frame.width or frame:GetWidth() |
usedwidth = framewidth |
if usedwidth > width then |
oversize = true |
end |
rowstart = frame |
rowstartoffset = frameoffset |
if child.OnWidthSet then |
child:OnWidthSet(width) |
end |
if child.DoLayout then |
child:DoLayout() |
end |
rowheight = frame.height or frame:GetHeight() or 0 |
rowoffset = child.alignoffset or (rowheight / 2) |
rowstartoffset = rowoffset |
elseif child.width == "relative" then |
child:SetWidth(width * child.relWidth) |
if child.OnWidthSet then |
child:OnWidthSet(width) |
end |
if child.DoLayout then |
child:DoLayout() |
end |
elseif oversize then |
if width > 1 then |
frame:SetPoint("RIGHT",content,"RIGHT",0,0) |
local AceGUI = LibStub("AceGUI-3.0") |
local Version = 6 |
local Version = 10 |
--------------------- |
-- Common Elements -- |
--------------------- |
self:Fire("OnEnterPressed",name) |
ClearCursor() |
end |
self.button:Disable() |
--self.button:Disable() |
AceGUI:ClearFocus() |
end |
function MultiLineEditBox:OnAcquire() |
self:SetWidth(200) |
self:SetHeight(116) |
self:SetNumLines(4) |
self:SetDisabled(false) |
self:ShowButton(true) |
end |
self.disabled = disabled |
if disabled then |
self.editbox:EnableMouse(false) |
self.scrollframe:EnableMouse(false) |
self.editbox:ClearFocus() |
self.editbox:SetTextColor(0.5, 0.5, 0.5) |
self.label:SetTextColor(0.5,0.5,0.5) |
else |
self.editbox:EnableMouse(true) |
self.scrollframe:EnableMouse(true) |
self.editbox:SetTextColor(1, 1, 1) |
self.label:SetTextColor(1,.82,0) |
end |
end |
self.label:SetText(text) |
end |
end |
function MultiLineEditBox:SetNumLines(number) |
number = number or 4 |
self:SetHeight(60 + (14*number)) |
end |
function MultiLineEditBox:GetText() |
return self.editbox:GetText() |
scrollframe:SetPoint("TOPLEFT", 5, -6) |
scrollframe:SetPoint("BOTTOMRIGHT", -28, 6) |
scrollframe.obj = self |
self.scrollframe = scrollframe |
local scrollchild = CreateFrame("Frame", nil, scrollframe) |
scrollframe:SetScrollChild(scrollchild) |
scrollchild:SetHeight(2) |
scrollchild:SetWidth(2) |
--local scrollchild = CreateFrame("Frame", nil, scrollframe) |
--scrollframe:SetScrollChild(scrollchild) |
--scrollchild:SetHeight(2) |
--scrollchild:SetWidth(2) |
local label = frame:CreateFontString(nil,"OVERLAY","GameFontHighlight") |
label:SetPoint("TOPLEFT",frame,"TOPLEFT",14,0) |
label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",-14,0) |
local label = frame:CreateFontString(nil,"OVERLAY","GameFontNormalSmall") |
label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,-2) |
label:SetPoint("TOPRIGHT",frame,"TOPRIGHT",0,-2) |
label:SetJustifyH("LEFT") |
label:SetHeight(18) |
self.label = label |
local editbox = CreateFrame("EditBox", nil, scrollchild) |
local editbox = CreateFrame("EditBox", nil, scrollframe) |
self.editbox = editbox |
editbox.obj = self |
editbox:SetPoint("TOPLEFT") |
editbox:SetPoint("BOTTOMLEFT") |
editbox:SetHeight(50) |
editbox:SetWidth(50) |
editbox:SetMultiLine(true) |
editbox:EnableMouse(true) |
editbox:SetAutoFocus(false) |
editbox:SetFontObject(ChatFontNormal) |
scrollframe:SetScrollChild(editbox) |
local button = CreateFrame("Button",nil,scrollframe,"UIPanelButtonTemplate") |
button:SetWidth(80) |
button:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,2) |
button:SetText(ACCEPT) |
button:SetScript("OnClick", Button_OnClick) |
button:SetFrameLevel(editbox:GetFrameLevel() + 1) |
button:Disable() |
button:Hide() |
self.button = button |
editbox:SetScript("OnLeave", function(this) this.obj:Fire("OnLeave") end) |
local function FixSize() |
scrollchild:SetHeight(scrollframe:GetHeight()) |
scrollchild:SetWidth(scrollframe:GetWidth()) |
--scrollchild:SetHeight(scrollframe:GetHeight()) |
--scrollchild:SetWidth(scrollframe:GetWidth()) |
editbox:SetWidth(scrollframe:GetWidth()) |
end |
scrollframe:SetScript("OnShow", FixSize) |
scrollframe:UpdateScrollChildRect() |
local value = editbox:GetText() |
if value ~= self.lasttext then |
self:Fire("OnTextChanged", value) |
self.lasttext = value |
self.button:Enable() |
self:Fire("OnTextChanged", value) |
self.lasttext = value |
self.button:Enable() |
end |
end) |
local cursorOffset, cursorHeight |
local idleTime |
local function FixScroll(_, elapsed) |
if cursorOffset and cursorHeight then |
idleTime = 0 |
local height = scrollframe:GetHeight() |
local range = scrollframe:GetVerticalScrollRange() |
local scroll = scrollframe:GetVerticalScroll() |
local size = height + range |
cursorOffset = -cursorOffset |
while cursorOffset < scroll do |
scroll = scroll - (height / 2) |
if scroll < 0 then scroll = 0 end |
scrollframe:SetVerticalScroll(scroll) |
if cursorOffset and cursorHeight then |
idleTime = 0 |
local height = scrollframe:GetHeight() |
local range = scrollframe:GetVerticalScrollRange() |
local scroll = scrollframe:GetVerticalScroll() |
local size = height + range |
cursorOffset = -cursorOffset |
while cursorOffset < scroll do |
scroll = scroll - (height / 2) |
if scroll < 0 then scroll = 0 end |
scrollframe:SetVerticalScroll(scroll) |
end |
while cursorOffset + cursorHeight > scroll + height and scroll < range do |
scroll = scroll + (height / 2) |
if scroll > range then scroll = range end |
scrollframe:SetVerticalScroll(scroll) |
end |
elseif not idleTime or idleTime > 2 then |
frame:SetScript("OnUpdate", nil) |
idleTime = nil |
else |
idleTime = idleTime + elapsed |
end |
while cursorOffset + cursorHeight > scroll + height and scroll < range do |
scroll = scroll + (height / 2) |
if scroll > range then scroll = range end |
scrollframe:SetVerticalScroll(scroll) |
end |
elseif not idleTime or idleTime > 2 then |
frame:SetScript("OnUpdate", nil) |
idleTime = nil |
else |
idleTime = idleTime + elapsed |
cursorOffset = nil |
end |
cursorOffset = nil |
end |
editbox:SetScript("OnCursorChanged", function(_, x, y, w, h) |
cursorOffset, cursorHeight = y, h |
if not idleTime then |
frame:SetScript("OnUpdate", FixScroll) |
end |
cursorOffset, cursorHeight = y, h |
if not idleTime then |
frame:SetScript("OnUpdate", FixScroll) |
end |
end) |
end |
-------------------------- |
do |
local Type = "Slider" |
local Version = 5 |
local Version = 7 |
local function OnAcquire(self) |
self:SetWidth(200) |
self:SetHeight(44) |
self:SetDisabled(false) |
self:SetIsPercent(nil) |
self:SetSliderValues(0,100,1) |
self:SetIsPercent(nil) |
self:SetValue(0) |
end |
end |
local function UpdateText(self) |
local value = self.value or 0 |
if self.ispercent then |
self.editbox:SetText((math.floor(self.value*1000+0.5)/10)..'%') |
self.editbox:SetText(("%s%%"):format(math.floor(value*1000+0.5)/10)) |
else |
self.editbox:SetText(math.floor(self.value*100+0.5)/100) |
self.editbox:SetText(math.floor(value*100+0.5)/100) |
end |
end |
local function UpdateLabels(self) |
local min, max = (self.min or 0), (self.max or 100) |
if self.ispercent then |
self.lowtext:SetFormattedText("%s%%",(min * 100)) |
self.hightext:SetFormattedText("%s%%",(max * 100)) |
else |
self.lowtext:SetText(min) |
self.hightext:SetText(max) |
end |
end |
local function Slider_OnValueChanged(this) |
local self = this.obj |
if not this.setup then |
self.label:SetText(text) |
end |
local function SetSliderValues(self,min, max, step) |
local function SetSliderValues(self, min, max, step) |
local frame = self.slider |
frame.setup = true |
self.min = min |
self.max = max |
self.step = step |
frame:SetMinMaxValues(min or 0,max or 100) |
self.lowtext:SetText(min or 0) |
self.hightext:SetText(max or 100) |
UpdateLabels(self) |
frame:SetValueStep(step or 1) |
frame.setup = nil |
end |
local function SetIsPercent(self, value) |
self.ispercent = value |
UpdateLabels(self) |
UpdateText(self) |
end |
local function FrameOnMouseDown(this) |
]] |
local WotLK = select(4, GetBuildInfo()) >= 30000 |
-------------------------- |
-- Tab Group -- |
-------------------------- |
do |
local Type = "TabGroup" |
local Version = 15 |
local Version = 20 |
local PaneBackdrop = { |
bgFile = "Interface\\ChatFrame\\ChatFrameBackground", |
self.localstatus[k] = nil |
end |
self.tablist = nil |
for _, tab in pairs(self.tabs) do |
tab:Hide() |
end |
end |
local function Tab_SetText(self, text) |
self:_SetText(text) |
-- TODO: Remove when 3.0 hits live |
if WotLK then |
PanelTemplates_TabResize(self, 0) |
else |
PanelTemplates_TabResize(0, self) |
end |
local width = self.obj.frame.width or self.obj.frame:GetWidth() or 0 |
PanelTemplates_TabResize(self, 0, nil, width) |
end |
local function UpdateTabLook(self) |
self:Fire("OnTabLeave", self.tabs[this.id].value, this) |
end |
local function Tab_OnShow(this) |
_G[this:GetName().."HighlightTexture"]:SetWidth(this:GetTextWidth() + 30) |
end |
local function CreateTab(self, id) |
local tabname = "AceGUITabGroup"..self.num.."Tab"..id |
local tab = CreateFrame("Button",tabname,self.border,"OptionsFrameTabButtonTemplate") |
tab.obj = self |
tab.id = id |
tab.text = _G[tabname .. "Text"] |
tab.text:ClearAllPoints() |
tab.text:SetPoint("LEFT", tab, "LEFT", 14, -3) |
tab.text:SetPoint("RIGHT", tab, "RIGHT", -12, -3) |
tab:SetScript("OnClick",Tab_OnClick) |
tab:SetScript("OnEnter",Tab_OnEnter) |
tab:SetScript("OnLeave",Tab_OnLeave) |
tab:SetScript("OnShow", Tab_OnShow) |
tab._SetText = tab.SetText |
tab.SetText = Tab_SetText |
v:SetSelected(true) |
found = true |
else |
v:SetSelected(false) |
v:SetSelected(false) |
end |
end |
status.selected = value |
local widths = {} |
local rowwidths = {} |
local rowends = {} |
local rowends = {} |
local function BuildTabs(self) |
local status = self.status or self.localstatus |
local tablist = self.tablist |
local tabs = self.tabs |
for i, v in ipairs(tabs) do |
v:Hide() |
end |
if not tablist then return end |
local width = self.frame.width or self.frame:GetWidth() or 0 |
tab = self:CreateTab(i) |
tabs[i] = tab |
end |
tab:Show() |
tab:SetText(v.text) |
tab:SetDisabled(v.disabled) |
tab.value = v.value |
widths[i] = tab:GetWidth() - 10 --tabs are anchored 10 pixels from the right side of the previous one to reduce spacing |
widths[i] = tab:GetWidth() - 6 --tabs are anchored 10 pixels from the right side of the previous one to reduce spacing, but add a fixed 4px padding for the text |
end |
for i = (#tablist)+1, #tabs, 1 do |
tabs[i]:Hide() |
end |
--First pass, find the minimum number of rows needed to hold all tabs and the initial tab layout |
local numtabs = #tablist |
local numrows = 1 |
rowwidths[numrows] = usedwidth + 10 --first tab in each row takes up an extra 10px |
rowends[numrows] = i - 1 |
numrows = numrows + 1 |
usedwidth = 0 |
usedwidth = 0 |
end |
usedwidth = usedwidth + widths[i] |
end |
if rowends[numrows-1] == numtabs-1 then |
--if there are more than 2 tabs in the 2nd last row |
if (numrows == 2 and rowends[numrows-1] > 2) or (rowends[numrows] - rowends[numrows-1] > 2) then |
--move 1 tab from the second last row to the last |
rowends[numrows-1] = rowends[numrows-1] - 1 |
rowwidths[numrows] = rowwidths[numrows] + widths[numtabs-1] |
rowwidths[numrows-1] = rowwidths[numrows-1] - widths[numtabs-1] |
--move 1 tab from the second last row to the last, if there is enough space |
if (rowwidths[numrows] + widths[numtabs-1]) <= width then |
rowends[numrows-1] = rowends[numrows-1] - 1 |
rowwidths[numrows] = rowwidths[numrows] + widths[numtabs-1] |
rowwidths[numrows-1] = rowwidths[numrows-1] - widths[numtabs-1] |
end |
end |
end |
end |
local tab = tabs[tabno] |
tab:ClearAllPoints() |
if first then |
tab:SetPoint("TOPLEFT",self.frame,"TOPLEFT",0,-7-(row-1)*20 ) |
tab:SetPoint("TOPLEFT", self.frame, "TOPLEFT", 0, -7-(row-1)*20 ) |
first = false |
else |
tab:SetPoint("LEFT",tabs[tabno-1],"RIGHT",-10,0) |
tab:SetPoint("LEFT", tabs[tabno-1], "RIGHT", -10, 0) |
end |
end |
--equal padding for each tab to fill the available width |
local padding = (width - rowwidths[row]) / (endtab - starttab+1) |
-- equal padding for each tab to fill the available width, |
-- if the used space is above 75% already |
local padding = 0 |
if not (numrows == 1 and rowwidths[1] < width*0.75) then |
padding = (width - rowwidths[row]) / (endtab - starttab+1) |
end |
for i = starttab, endtab do |
-- TODO: Remove when 3.0 hits live |
if WotLK then |
PanelTemplates_TabResize(tabs[i], padding) |
else |
PanelTemplates_TabResize(padding, tabs[i]) |
end |
end |
PanelTemplates_TabResize(tabs[i], padding + 4, nil, width) |
end |
starttab = endtab + 1 |
end |
content:SetHeight(contentheight) |
content.height = contentheight |
end |
local function LayoutFinished(self, width, height) |
if self.noAutoHeight then return end |
self:SetHeight((height or 0) + (self.borderoffset + 23)) |
end |
local function Constructor() |
local frame = CreateFrame("Frame",nil,UIParent) |
self.BuildTabs = BuildTabs |
self.SetStatusTable = SetStatusTable |
self.SetTabs = SetTabs |
self.LayoutFinished = LayoutFinished |
self.frame = frame |
self.OnWidthSet = OnWidthSet |
titletext:SetJustifyH("LEFT") |
titletext:SetHeight(18) |
self.titletext = titletext |
self.titletext = titletext |
local border = CreateFrame("Frame",nil,frame) |
self.border = border |
-------------------------- |
-- Keybinding -- |
-------------------------- |
do |
local Type = "Keybinding" |
local Version = 8 |
local Version = 13 |
local ControlBackdrop = { |
bgFile = "Interface\\Tooltips\\UI-Tooltip-Background", |
end |
end |
this:EnableKeyboard(false) |
self.msgframe:Hide() |
this:UnlockHighlight() |
self.waitingForKey = nil |
if not self.disabled then |
self:SetKey(keyPressed) |
self:Fire("OnKeyChanged",keyPressed) |
end |
this:EnableKeyboard(false) |
self.msgframe:Hide() |
this:UnlockHighlight() |
self.waitingForKey = nil |
end |
end |
end |
local function OnAcquire(self) |
self:SetWidth(200) |
self:SetHeight(44) |
self:SetLabel("") |
self:SetKey("") |
end |
local function OnRelease(self) |
self.frame:Hide() |
self.waitingForKey = nil |
self.msgframe:Hide() |
self:SetDisabled(false) |
end |
local function SetDisabled(self, disabled) |
end |
local function SetKey(self, key) |
self.button:SetText(key or "") |
if (key or "") == "" then |
self.button:SetText(NOT_BOUND) |
self.button:SetNormalFontObject("GameFontNormal") |
else |
self.button:SetText(key) |
self.button:SetNormalFontObject("GameFontHighlight") |
end |
end |
local function SetLabel(self, label) |
self.label:SetText(label or "") |
if (label or "") == "" then |
self.alignoffset = nil |
self:SetHeight(24) |
else |
self.alignoffset = 30 |
self:SetHeight(44) |
end |
end |
local function Constructor() |
local num = AceGUI:GetNextWidgetNum(Type) |
local frame = CreateFrame("Frame",nil,UIParent) |
]] |
do |
local Type = "CheckBox" |
local Version = 4 |
local Version = 7 |
local function OnAcquire(self) |
self:SetValue(false) |
self.tristate = nil |
self:SetHeight(24) |
self:SetWidth(200) |
end |
local function OnRelease(self) |
local function CheckBox_OnEnter(this) |
local self = this.obj |
if not self.disabled then |
self.highlight:Show() |
end |
self.highlight:Show() |
self:Fire("OnEnter") |
end |
local function CheckBox_OnLeave(this) |
local self = this.obj |
if not self.down then |
self.highlight:Hide() |
end |
self.highlight:Hide() |
self:Fire("OnLeave") |
end |
local function SetDisabled(self,disabled) |
self.disabled = disabled |
if disabled then |
self.frame:Disable() |
self.text:SetTextColor(0.5,0.5,0.5) |
SetDesaturation(self.check, true) |
else |
self.frame:Enable() |
self.text:SetTextColor(1,1,1) |
if self.tristate and self.checked == nil then |
SetDesaturation(self.check, true) |
--Nil is the unknown tristate value |
if self.tristate and value == nil then |
SetDesaturation(self.check, true) |
check:SetWidth(20) |
check:SetHeight(20) |
check:SetWidth(24) |
check:SetHeight(24) |
self.check:Show() |
else |
SetDesaturation(self.check, false) |
-------------------------- |
do |
local Type = "Icon" |
local Version = 4 |
local Version = 10 |
local function OnAcquire(self) |
self:SetText("") |
self:SetHeight(110) |
self:SetWidth(110) |
self:SetLabel("") |
self:SetImage(nil) |
self:SetImageSize(64, 64) |
end |
local function OnRelease(self) |
self.frame:ClearAllPoints() |
self.frame:Hide() |
self:SetDisabled(false) |
end |
local function SetText(self, text) |
self.label:SetText(text or "") |
local function SetLabel(self, text) |
if text and text ~= "" then |
self.label:Show() |
self.label:SetText(text) |
self.frame:SetHeight(self.image:GetHeight() + 25) |
else |
self.label:Hide() |
self.frame:SetHeight(self.image:GetHeight() + 10) |
end |
end |
local function SetImage(self, path, ...) |
end |
end |
local function OnClick(this) |
this.obj:Fire("OnClick") |
local function SetImageSize(self, width, height) |
self.image:SetWidth(width) |
self.image:SetHeight(height) |
--self.frame:SetWidth(width + 30) |
if self.label:IsShown() then |
self.frame:SetHeight(height + 25) |
else |
self.frame:SetHeight(height + 10) |
end |
end |
local function SetDisabled(self, disabled) |
self.disabled = disabled |
if disabled then |
self.frame:Disable() |
self.label:SetTextColor(0.5,0.5,0.5) |
self.image:SetVertexColor(0.5, 0.5, 0.5, 0.5) |
else |
self.frame:Enable() |
self.label:SetTextColor(1,1,1) |
self.image:SetVertexColor(1, 1, 1) |
end |
end |
local function OnClick(this, button) |
this.obj:Fire("OnClick", button) |
AceGUI:ClearFocus() |
end |
local function OnEnter(this) |
this.obj.highlight:Show() |
this.obj:Fire("OnEnter") |
end |
local function OnLeave(this) |
this.obj.highlight:Hide() |
this.obj:Fire("OnLeave") |
end |
local function Constructor() |
self.OnRelease = OnRelease |
self.OnAcquire = OnAcquire |
self.SetText = SetText |
self.SetLabel = SetLabel |
self.frame = frame |
self.SetImage = SetImage |
self.SetImageSize = SetImageSize |
-- SetText should be deprecated along the way |
self.SetText = SetLabel |
self.SetDisabled = SetDisabled |
frame.obj = self |
frame:SetScript("OnLeave", OnLeave) |
frame:SetScript("OnEnter", OnEnter) |
local label = frame:CreateFontString(nil,"BACKGROUND","GameFontHighlight") |
label:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,10) |
label:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,10) |
label:SetPoint("BOTTOMLEFT",frame,"BOTTOMLEFT",0,0) |
label:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",0,0) |
label:SetJustifyH("CENTER") |
label:SetJustifyV("TOP") |
label:SetHeight(18) |
self.image = image |
image:SetWidth(64) |
image:SetHeight(64) |
image:SetPoint("TOP",frame,"TOP",0,-10) |
image:SetPoint("TOP",frame,"TOP",0,-5) |
local highlight = frame:CreateTexture(nil,"OVERLAY") |
self.highlight = highlight |
]] |
do |
local Type = "Frame" |
local Version = 7 |
local Version = 8 |
local FrameBackdrop = { |
bgFile="Interface\\DialogFrame\\UI-DialogBox-Background", |
closebutton:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT",-27,17) |
closebutton:SetHeight(20) |
closebutton:SetWidth(100) |
closebutton:SetText("Close") |
closebutton:SetText(CLOSE) |
self.closebutton = closebutton |
closebutton.obj = self |
do |
local Type = "InlineGroup" |
local Version = 4 |
local Version = 5 |
local function OnAcquire(self) |
self:SetWidth(300) |
local function LayoutFinished(self, width, height) |
if self.noAutoHeight then return end |
self:SetHeight((height or 0) + 40) |
end |
--[[ $Id: AceGUIWidget-DropDown.lua 81438 2008-09-06 13:44:36Z nevcairiel $ ]]-- |
--[[ $Id: AceGUIWidget-DropDown.lua 815 2009-07-08 20:58:17Z nevcairiel $ ]]-- |
local min, max, floor = math.min, math.max, math.floor |
local AceGUI = LibStub("AceGUI-3.0") |
AceGUI:RegisterWidgetType(widgetType, Constructor, widgetVersion) |
end |
do |
do |
local widgetType = "Dropdown" |
local widgetVersion = 18 |
local widgetVersion = 20 |
--[[ Static data ]]-- |
pullout:SetCallback("OnOpen", OnPulloutOpen) |
self.pullout.frame:SetFrameLevel(self.frame:GetFrameLevel() + 1) |
fixlevels(self.pullout.frame, self.pullout.frame:GetChildren()) |
self:SetHeight(44) |
self:SetWidth(200) |
end |
-- exported, AceGUI callback |
self.pullout:Close() |
end |
AceGUI:Release(self.pullout) |
self.pullout = nil |
self:SetText("") |
self:SetLabel("") |
self:SetMultiselect(false) |
self.value = nil |
self.list = nil |
self.list = nil |
self.open = nil |
self.hasClose = nil |
self.frame:ClearAllPoints() |
self.frame:Hide() |
self.frame:Hide() |
end |
-- exported |
local close = AceGUI:Create("Dropdown-Item-Execute") |
close:SetText(CLOSE) |
self.pullout:AddItem(close) |
self.hasClose = true |
self.hasClose = true |
end |
end |
]] |
do |
local Type = "EditBox" |
local Version = 8 |
local Version = 11 |
local function OnAcquire(self) |
self:SetHeight(26) |
self:SetWidth(200) |
self:SetDisabled(false) |
self:SetLabel() |
self.showbutton = true |
end |
HideButton(self) |
end |
local function SetWidth(self, width) |
self.frame:SetWidth(width) |
end |
local function SetLabel(self, text) |
if text and text ~= "" then |
self.label:SetText(text) |
self.label:Show() |
self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,-18) |
self.frame:SetHeight(44) |
self:SetHeight(44) |
self.alignoffset = 30 |
else |
self.label:SetText("") |
self.label:Hide() |
self.editbox:SetPoint("TOPLEFT",self.frame,"TOPLEFT",7,0) |
self.frame:SetHeight(26) |
self:SetHeight(26) |
self.alignoffset = 12 |
end |
end |
self.SetDisabled = SetDisabled |
self.SetText = SetText |
self.SetWidth = SetWidth |
self.SetLabel = SetLabel |
self.frame = frame |
-------------------------- |
do |
local Type = "Heading" |
local Version = 3 |
local Version = 5 |
local function OnAcquire(self) |
self:SetText("") |
self:SetFullWidth() |
self:SetHeight(18) |
end |
local function OnRelease(self) |
do |
local Type = "SimpleGroup" |
local Version = 4 |
local Version = 5 |
local function OnAcquire(self) |
self:SetWidth(300) |
end |
local function LayoutFinished(self, width, height) |
if self.noAutoHeight then return end |
self:SetHeight(height or 0) |
end |
-------------------------- |
do |
local Type = "ScrollFrame" |
local Version = 3 |
local Version = 4 |
local function OnAcquire(self) |
scrollframe:SetScrollChild(content) |
scrollframe:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0) |
scrollframe:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT",-16,0) |
scrollframe:SetPoint("BOTTOMRIGHT",self.frame,"BOTTOMRIGHT",-20,0) |
scrollframe:EnableMouseWheel(true) |
scrollframe:SetScript("OnMouseWheel", OnMouseWheel) |
scrollframe:SetScript("OnSizeChanged", OnSizeChanged) |
content:SetPoint("TOPRIGHT",scrollframe,"TOPRIGHT",0,0) |
content:SetHeight(400) |
scrollbar:SetPoint("TOPLEFT",scrollframe,"TOPRIGHT",0,-16) |
scrollbar:SetPoint("BOTTOMLEFT",scrollframe,"BOTTOMRIGHT",0,16) |
scrollbar:SetPoint("TOPLEFT",scrollframe,"TOPRIGHT",4,-16) |
scrollbar:SetPoint("BOTTOMLEFT",scrollframe,"BOTTOMRIGHT",4,16) |
scrollbar:SetScript("OnValueChanged", OnScrollValueChanged) |
scrollbar:SetMinMaxValues(0,1000) |
scrollbar:SetValueStep(1) |
]] |
do |
local Type = "DropdownGroup" |
local Version = 9 |
local Version = 11 |
local function OnAcquire(self) |
self.dropdown:SetText("") |
self:SetDropdownWidth(200) |
end |
local function OnRelease(self) |
content.height = contentheight |
end |
local function LayoutFinished(self, width, height) |
self:SetHeight((height or 0) + 63) |
end |
local function SetDropdownWidth(self, width) |
self.dropdown:SetWidth(width) |
end |
local function Constructor() |
local frame = CreateFrame("Frame") |
local self = {} |
self.SetGroupList = SetGroupList |
self.SetGroup = SetGroup |
self.SetStatusTable = SetStatusTable |
self.SetDropdownWidth = SetDropdownWidth |
self.OnWidthSet = OnWidthSet |
self.OnHeightSet = OnHeightSet |
self.LayoutFinished = LayoutFinished |
self.localstatus = {} |
frame:SetFrameStrata("FULLSCREEN_DIALOG") |
local titletext = frame:CreateFontString(nil,"OVERLAY","GameFontNormal") |
titletext:SetPoint("TOPLEFT",frame,"TOPLEFT",14,0) |
titletext:SetPoint("TOPRIGHT",frame,"TOPRIGHT",-14,0) |
titletext:SetPoint("TOPLEFT",frame,"TOPLEFT",4,0) |
titletext:SetPoint("TOPRIGHT",frame,"TOPRIGHT",-4,0) |
titletext:SetJustifyH("LEFT") |
titletext:SetHeight(18) |
self.titletext = titletext |
self.titletext = titletext |
local dropdown = AceGUI:Create("Dropdown") |
self.dropdown = dropdown |
dropdown.parentgroup = self |
dropdown:SetCallback("OnValueChanged",SelectedGroup) |
dropdown.frame:SetPoint("TOPLEFT",titletext,"BOTTOMLEFT",-7,3) |
dropdown.frame:SetPoint("TOPLEFT",titletext,"BOTTOMLEFT",-3,3) |
dropdown.frame:Show() |
dropdown:SetLabel("") |
-------------------------- |
do |
local Type = "Button" |
local Version = 7 |
local Version = 11 |
local function OnAcquire(self) |
-- restore default values |
self:SetHeight(24) |
self:SetWidth(200) |
end |
local function OnRelease(self) |
local function Constructor() |
local num = AceGUI:GetNextWidgetNum(Type) |
local frame = CreateFrame("Button","AceGUI30Button"..num,UIParent,"UIPanelButtonTemplate2") |
local name = "AceGUI30Button"..num |
local frame = CreateFrame("Button",name,UIParent,"UIPanelButtonTemplate2") |
local self = {} |
self.num = num |
self.type = Type |
self.frame = frame |
local left = _G[name .. "Left"] |
local right = _G[name .. "Right"] |
local middle = _G[name .. "Middle"] |
left:SetPoint("TOP", frame, "TOP", 0, 0) |
left:SetPoint("BOTTOM", frame, "BOTTOM", 0, 0) |
right:SetPoint("TOP", frame, "TOP", 0, 0) |
right:SetPoint("BOTTOM", frame, "BOTTOM", 0, 0) |
middle:SetPoint("TOP", frame, "TOP", 0, 0) |
middle:SetPoint("BOTTOM", frame, "BOTTOM", 0, 0) |
local text = frame:GetFontString() |
self.text = text |
text:SetPoint("LEFT",frame,"LEFT",15,0) |
text:SetPoint("RIGHT",frame,"RIGHT",-15,0) |
text:ClearAllPoints() |
text:SetPoint("TOPLEFT",frame,"TOPLEFT", 15, -1) |
text:SetPoint("BOTTOMRIGHT",frame,"BOTTOMRIGHT", -15, 1) |
text:SetJustifyV("MIDDLE") |
frame:SetScript("OnClick",Button_OnClick) |
frame:SetScript("OnEnter",Button_OnEnter) |
end |
AceGUI:RegisterWidgetType(Type,Constructor,Version) |
end |
end |
--[[ $Id: AceGUIWidget-DropDown-Items.lua 76326 2008-06-09 09:29:17Z nevcairiel $ ]]-- |
--[[ $Id: AceGUIWidget-DropDown-Items.lua 808 2009-05-07 14:45:15Z ammo $ ]]-- |
local AceGUI = LibStub("AceGUI-3.0") |
-- Does not close the pullout on click |
do |
local widgetType = "Dropdown-Item-Menu" |
local widgetVersion = 1 |
local widgetVersion = 2 |
local function OnEnter(this) |
local self = this.obj |
end |
-- exported |
function SetMenu(self, menu) |
local function SetMenu(self, menu) |
assert(menu.type == "Dropdown-Pullout") |
self.submenu = menu |
end |
-- exported |
function CloseMenu(self) |
local function CloseMenu(self) |
self.submenu:Close() |
end |
end |
end |
local WotLK = select(4, GetBuildInfo()) >= 30000 |
-------------- |
-- TreeView -- |
-------------- |
do |
local Type = "TreeGroup" |
local Version = 16 |
local Version = 20 |
local DEFAULT_TREE_WIDTH = 175 |
local DEFAULT_TREE_SIZABLE = true |
status[button.uniquevalue] = not status[button.uniquevalue] |
self:RefreshTree() |
end |
local function EnableButtonTooltips(self, enable) |
self.enabletooltips = enable |
end |
local function Button_OnEnter(this) |
local self = this.obj |
self:Fire("OnButtonEnter", this.uniquevalue, this) |
if self.enabletooltips then |
GameTooltip:SetOwner(this, "ANCHOR_NONE") |
GameTooltip:SetPoint("LEFT",this,"RIGHT") |
GameTooltip:SetText(this.text:GetText(), 1, .82, 0, 1) |
local function EnableButtonTooltips(self, enable) |
self.enabletooltips = enable |
end |
local function Button_OnEnter(this) |
local self = this.obj |
self:Fire("OnButtonEnter", this.uniquevalue, this) |
if self.enabletooltips then |
GameTooltip:SetOwner(this, "ANCHOR_NONE") |
GameTooltip:SetPoint("LEFT",this,"RIGHT") |
GameTooltip:SetText(this.text:GetText() or "", 1, .82, 0, 1) |
GameTooltip:Show() |
end |
end |
local buttoncount = 1 |
local function CreateButton(self) |
local button = CreateFrame("Button",("AceGUI30TreeButton%d"):format(buttoncount),self.treeframe, WotLK and "OptionsListButtonTemplate" or "InterfaceOptionsButtonTemplate") |
local button = CreateFrame("Button",("AceGUI30TreeButton%d"):format(buttoncount),self.treeframe, "OptionsListButtonTemplate") |
buttoncount = buttoncount + 1 |
button.obj = self |
local icon = button:CreateTexture(nil, "OVERLAY") |
icon:SetWidth(14) |
icon:SetHeight(14) |
button.icon = icon |
button:SetScript("OnClick",ButtonOnClick) |
button:SetScript("OnDoubleClick", ButtonOnDoubleClick) |
button:SetScript("OnEnter",Button_OnEnter) |
local toggle = button.toggle |
local frame = self.frame |
local text = treeline.text or "" |
local icon = treeline.icon |
local level = treeline.level |
local value = treeline.value |
local uniquevalue = treeline.uniquevalue |
button:UnlockHighlight() |
button.selected = false |
end |
local normalText = button.text |
local normalTexture = button:GetNormalTexture() |
local line = button.line |
button.level = level |
if ( level == 1 ) then |
if WotLK then |
button:SetNormalFontObject("GameFontNormal") |
else |
button:SetTextFontObject("GameFontNormal") |
end |
button:SetNormalFontObject("GameFontNormal") |
button:SetHighlightFontObject("GameFontHighlight") |
button.text:SetPoint("LEFT", 8, 2) |
button.text:SetPoint("LEFT", (icon and 16 or 0) + 8, 2) |
else |
if WotLK then |
button:SetNormalFontObject("GameFontHighlightSmall") |
else |
button:SetTextFontObject("GameFontHighlightSmall") |
end |
button:SetNormalFontObject("GameFontHighlightSmall") |
button:SetHighlightFontObject("GameFontHighlightSmall") |
button.text:SetPoint("LEFT", 8 * level, 2) |
button.text:SetPoint("LEFT", (icon and 16 or 0) + 8 * level, 2) |
end |
if disabled then |
button:EnableMouse(true) |
end |
if icon then |
button.icon:SetTexture(icon) |
button.icon:SetPoint("LEFT", button, "LEFT", 8 * level, (level == 1) and 0 or 1) |
else |
button.icon:SetTexture(nil) |
end |
if canExpand then |
if not isExpanded then |
toggle:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-UP") |
}, |
} |
]] |
local function SetTree(self, tree) |
local function SetTree(self, tree, filter) |
self.filter = filter |
if tree then |
assert(type(tree) == "table") |
end |
self:RefreshTree() |
end |
local function ShouldDisplayLevel(tree) |
local result = false |
for k, v in ipairs(tree) do |
if v.children == nil and v.visible ~= false then |
result = true |
elseif v.children then |
result = result or ShouldDisplayLevel(v.children) |
end |
if result then return result end |
end |
return false |
end |
local function addLine(self, v, tree, level, parent) |
local line = new() |
line.value = v.value |
line.text = v.text |
line.icon = v.icon |
line.disabled = v.disabled |
line.tree = tree |
line.level = level |
line.parent = parent |
line.visible = v.visible |
line.uniquevalue = GetButtonUniqueValue(line) |
if v.children then |
line.hasChildren = true |
else |
line.hasChildren = nil |
end |
self.lines[#self.lines+1] = line |
return line |
end |
local function BuildLevel(self, tree, level, parent) |
local lines = self.lines |
local status = (self.status or self.localstatus) |
local groups = status.groups |
local groups = (self.status or self.localstatus).groups |
local hasChildren = self.hasChildren |
for i, v in ipairs(tree) do |
local line = new() |
lines[#lines+1] = line |
line.value = v.value |
line.text = v.text |
line.disabled = v.disabled |
line.tree = tree |
line.level = level |
line.parent = parent |
line.uniquevalue = GetButtonUniqueValue(line) |
if v.children then |
line.hasChildren = true |
else |
line.hasChildren = nil |
end |
if v.children then |
if groups[line.uniquevalue] then |
self:BuildLevel(v.children, level+1, line) |
if not self.filter or ShouldDisplayLevel(v.children) then |
local line = addLine(self, v, tree, level, parent) |
if groups[line.uniquevalue] then |
self:BuildLevel(v.children, level+1, line) |
end |
end |
elseif v.visible ~= false or not self.filter then |
addLine(self, v, tree, level, parent) |
end |
end |
end |
end |
local function RefreshTree(self) |
local buttons = self.buttons |
local buttons = self.buttons |
local lines = self.lines |
for i, v in ipairs(buttons) do |
end |
local function Select(self, uniquevalue, ...) |
self.filter = false |
local status = self.status or self.localstatus |
local groups = status.groups |
for i = 1, select('#', ...) do |
local status = self.status or self.localstatus |
status.treewidth = treeframe:GetWidth() |
end |
local function LayoutFinished(self, width, height) |
if self.noAutoHeight then return end |
self:SetHeight((height or 0) + 20) |
end |
local createdcount = 0 |
local function Constructor() |
self.hasChildren = {} |
self.localstatus = {} |
self.localstatus.groups = {} |
self.filter = false |
local treeframe = CreateFrame("Frame",nil,frame) |
treeframe.obj = self |
self.OnWidthSet = OnWidthSet |
self.OnHeightSet = OnHeightSet |
self.EnableButtonTooltips = EnableButtonTooltips |
self.Filter = Filter |
self.LayoutFinished = LayoutFinished |
self.frame = frame |
frame.obj = self |
-------------------------- |
do |
local Type = "ColorPicker" |
local Version = 9 |
local Version = 11 |
local function OnAcquire(self) |
self.HasAlpha = false |
self:SetColor(0,0,0,1) |
self:SetHeight(24) |
self:SetWidth(200) |
end |
local function SetLabel(self, text) |
local function SetDisabled(self, disabled) |
self.disabled = disabled |
if self.disabled then |
self.frame:Disable() |
self.text:SetTextColor(0.5,0.5,0.5) |
else |
self.frame:Enable() |
self.text:SetTextColor(1,1,1) |
end |
end |
local AceGUI = LibStub("AceGUI-3.0") |
-------------------------- |
-- Label -- |
-------------------------- |
do |
local Type = "InteractiveLabel" |
local Version = 5 |
local function OnAcquire(self) |
self:SetHeight(18) |
self:SetWidth(200) |
self:SetText("") |
self:SetImage(nil) |
self:SetColor() |
self:SetFontObject() |
self:SetHighlight() |
self:SetHighlightTexCoord() |
end |
local function OnRelease(self) |
self:SetDisabled(false) |
self.frame:ClearAllPoints() |
self.frame:Hide() |
end |
local function UpdateImageAnchor(self) |
local width = self.frame.width or self.frame:GetWidth() or 0 |
local image = self.image |
local label = self.label |
local frame = self.frame |
local height |
label:ClearAllPoints() |
image:ClearAllPoints() |
if self.imageshown then |
local imagewidth = image:GetWidth() |
if (width - imagewidth) < 200 or (label:GetText() or "") == "" then |
--image goes on top centered when less than 200 width for the text, or if there is no text |
image:SetPoint("TOP",frame,"TOP",0,0) |
label:SetPoint("TOP",image,"BOTTOM",0,0) |
label:SetPoint("LEFT",frame,"LEFT",0,0) |
label:SetWidth(width) |
height = image:GetHeight() + label:GetHeight() |
else |
--image on the left |
image:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0) |
label:SetPoint("TOPLEFT",image,"TOPRIGHT",0,0) |
label:SetWidth(width - imagewidth) |
height = math.max(image:GetHeight(), label:GetHeight()) |
end |
else |
--no image shown |
label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0) |
label:SetWidth(width) |
height = self.label:GetHeight() |
end |
self.resizing = true |
self.frame:SetHeight(height) |
self.frame.height = height |
self.resizing = nil |
end |
local function SetText(self, text) |
self.label:SetText(text or "") |
UpdateImageAnchor(self) |
end |
local function SetColor(self, r, g, b) |
if not (r and g and b) then |
r, g, b = 1, 1, 1 |
end |
self.label:SetVertexColor(r, g, b) |
end |
local function OnWidthSet(self, width) |
if self.resizing then return end |
UpdateImageAnchor(self) |
end |
local function SetImage(self, path, ...) |
local image = self.image |
image:SetTexture(path) |
if image:GetTexture() then |
self.imageshown = true |
local n = select('#', ...) |
if n == 4 or n == 8 then |
image:SetTexCoord(...) |
end |
else |
self.imageshown = nil |
end |
UpdateImageAnchor(self) |
end |
local function SetFont(self, font, height, flags) |
self.label:SetFont(font, height, flags) |
end |
local function SetFontObject(self, font) |
self.label:SetFontObject(font or GameFontHighlightSmall) |
end |
local function SetImageSize(self, width, height) |
self.image:SetWidth(width) |
self.image:SetHeight(height) |
UpdateImageAnchor(self) |
end |
local function SetHighlight(self, ...) |
self.highlight:SetTexture(...) |
end |
local function SetHighlightTexCoord(self, ...) |
if select('#', ...) >= 1 then |
self.highlight:SetTexCoord(...) |
else |
self.highlight:SetTexCoord(0, 1, 0, 1) |
end |
end |
local function SetDisabled(self,disabled) |
self.disabled = disabled |
if disabled then |
self.frame:EnableMouse(false) |
self.label:SetTextColor(0.5, 0.5, 0.5) |
else |
self.frame:EnableMouse(true) |
self.label:SetTextColor(1, 1, 1) |
end |
end |
local function OnEnter(this) |
this.obj.highlight:Show() |
this.obj:Fire("OnEnter") |
end |
local function OnLeave(this) |
this.obj.highlight:Hide() |
this.obj:Fire("OnLeave") |
end |
local function OnClick(this, ...) |
this.obj:Fire("OnClick", ...) |
AceGUI:ClearFocus() |
end |
local function Constructor() |
local frame = CreateFrame("Frame",nil,UIParent) |
local self = {} |
self.type = Type |
frame:EnableMouse(true) |
frame:SetScript("OnEnter", OnEnter) |
frame:SetScript("OnLeave", OnLeave) |
frame:SetScript("OnMouseDown", OnClick) |
self.OnRelease = OnRelease |
self.OnAcquire = OnAcquire |
self.SetText = SetText |
self.SetColor = SetColor |
self.frame = frame |
self.OnWidthSet = OnWidthSet |
self.SetImage = SetImage |
self.SetImageSize = SetImageSize |
self.SetFont = SetFont |
self.SetFontObject = SetFontObject |
self.SetHighlight = SetHighlight |
self.SetHighlightTexCoord = SetHighlightTexCoord |
self.SetDisabled = SetDisabled |
frame.obj = self |
frame:SetHeight(18) |
frame:SetWidth(200) |
local label = frame:CreateFontString(nil,"BACKGROUND","GameFontHighlightSmall") |
label:SetPoint("TOPLEFT",frame,"TOPLEFT",0,0) |
label:SetWidth(200) |
label:SetJustifyH("LEFT") |
label:SetJustifyV("TOP") |
self.label = label |
local highlight = frame:CreateTexture(nil, "OVERLAY") |
highlight:SetTexture(nil) |
highlight:SetAllPoints() |
highlight:SetBlendMode("ADD") |
highlight:Hide() |
self.highlight = highlight |
local image = frame:CreateTexture(nil,"BACKGROUND") |
self.image = image |
AceGUI:RegisterAsWidget(self) |
return self |
end |
AceGUI:RegisterWidgetType(Type,Constructor,Version) |
end |
-------------------------- |
do |
local Type = "Label" |
local Version = 8 |
local Version = 10 |
local function OnAcquire(self) |
self:SetHeight(18) |
self:SetWidth(200) |
self:SetText("") |
self:SetImage(nil) |
self:SetColor() |
self:SetFontObject() |
end |
local function OnRelease(self) |
UpdateImageAnchor(self) |
end |
local function SetFont(self, font, height, flags) |
self.label:SetFont(font, height, flags) |
end |
local function SetFontObject(self, font) |
self.label:SetFontObject(font or GameFontHighlightSmall) |
end |
local function SetImageSize(self, width, height) |
self.image:SetWidth(width) |
self.image:SetHeight(height) |
self.OnWidthSet = OnWidthSet |
self.SetImage = SetImage |
self.SetImageSize = SetImageSize |
self.SetFont = SetFont |
self.SetFontObject = SetFontObject |
frame.obj = self |
frame:SetHeight(18) |
<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 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> |
--[[ $Id: AceAddon-3.0.lua 76326 2008-06-09 09:29:17Z nevcairiel $ ]] |
local MAJOR, MINOR = "AceAddon-3.0", 5 |
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 |
local tinsert, tconcat = table.insert, table.concat |
local fmt = string.format |
local pairs, next, type = pairs, next, type |
--[[ |
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 |
-- AceAddon:NewAddon( [object, ]name, [lib, lib, lib, ...] ) |
-- [object] (table) - table to use as the base for the addon |
-- name (string) - unique addon object name |
-- [lib] (string) - optional libs to embed in the addon object |
-- |
-- returns the addon object when succesful |
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.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 |
-- AceAddon:GetAddon( name, [silent]) |
-- name (string) - unique addon object name |
-- silent (boolean) - if true, addon is optional, silently return nil if its not found |
-- |
-- throws an error if the addon object can not be found (except silent is set) |
-- returns the addon object if found |
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 |
-- AceAddon:EmbedLibraries( addon, [lib, lib, lib, ...] ) |
-- addon (object) - addon to embed the libs in |
-- [lib] (string) - optional libs to embed |
function AceAddon:EmbedLibraries(addon, ...) |
for i=1,select("#", ... ) do |
local libname = select(i, ...) |
self:EmbedLibrary(addon, libname, false, 4) |
end |
end |
-- AceAddon:EmbedLibrary( addon, libname, silent, offset ) |
-- addon (object) - addon to embed the libs in |
-- libname (string) - lib to embed |
-- [silent] (boolean) - optional, marks an embed to fail silently if the library doesn't exist. |
-- [offset] (number) - will push the error messages back to said offset defaults to 2 |
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 |
-- addon:GetModule( name, [silent]) |
-- name (string) - unique module object name |
-- silent (boolean) - if true, module is optional, silently return nil if its not found |
-- |
-- throws an error if the addon object can not be found (except silent is set) |
-- returns the module object if found |
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 |
-- addon:NewModule( name, [prototype, [lib, lib, lib, ...] ) |
-- name (string) - unique module object name for this addon |
-- prototype (object) - object to derive this module from, methods and values from this table will be mixed into the module, if a string is passed a lib is assumed |
-- [lib] (string) - optional libs to embed in the addon object |
-- |
-- returns the addon object when succesful |
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 |
return module |
end |
--addon:GetName() |
-- Returns the real name of the addon or module, without any prefix |
function GetName(self) |
return self.moduleName or self.name |
end |
--addon:Enable() |
-- Enables the Addon if possible, return true or false depending on success |
function Enable(self) |
self:SetEnabledState(true) |
return AceAddon:EnableAddon(self) |
end |
--addon:Disable() |
-- Disables the Addon if possible, return true or false depending on success |
function Disable(self) |
self:SetEnabledState(false) |
return AceAddon:DisableAddon(self) |
end |
-- addon:EnableModule( name ) |
-- name (string) - unique module object name |
-- |
-- Enables the Module if possible, return true or false depending on success |
function EnableModule(self, name) |
local module = self:GetModule( name ) |
return module:Enable() |
end |
-- addon:DisableModule( name ) |
-- name (string) - unique module object name |
-- |
-- Disables the Module if possible, return true or false depending on success |
function DisableModule(self, name) |
local module = self:GetModule( name ) |
return module:Disable() |
end |
-- addon:SetDefaultModuleLibraries( [lib, lib, lib, ...] ) |
-- [lib] (string) - libs to embed in every module |
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 |
-- addon:SetDefaultModuleState( state ) |
-- state (boolean) - default state for new modules (enabled=true, disabled=false) |
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 |
-- addon:SetDefaultModulePrototype( prototype ) |
-- prototype (string or table) - the default prototype to use if none is specified on module creation |
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 |
-- addon:SetEnabledState ( state ) |
-- state ( boolean ) - set the state of an addon or module (enabled=true, disabled=false) |
-- |
-- should only be called before any Enabling actually happend, aka in OnInitialize |
function SetEnabledState(self, state) |
self.enabledState = state |
end |
local function IterateModules(self) return pairs(self.modules) end |
local function IterateEmbeds(self) return pairs(AceAddon.embeds[self]) 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) |
for k, v in pairs(mixins) do |
target[k] = v |
end |
for k, v in pairs(pmixins) do |
target[k] = target[k] or v |
end |
end |
-- AceAddon:IntializeAddon( addon ) |
-- addon (object) - addon to intialize |
-- |
-- calls OnInitialize on the addon object if available |
-- calls OnEmbedInitialize on embedded libs in the addon object if available |
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 |
-- AceAddon:EnableAddon( addon ) |
-- addon (object) - addon to enable |
-- |
-- calls OnEnable on the addon object if available |
-- calls OnEmbedEnable on embedded libs in the addon object if available |
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 |
-- TODO: handle 'first'? Or let addons do it on their own? |
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. |
for name, module in pairs(addon.modules) do |
self:EnableAddon(module) |
end |
end |
return self.statuses[addon.name] -- return true if we're disabled |
end |
-- AceAddon:DisableAddon( addon ) |
-- addon (object|string) - addon to disable |
-- |
-- calls OnDisable on the addon object if available |
-- calls OnEmbedDisable on embedded libs in the addon object if available |
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. |
for name, module in pairs(addon.modules) do |
self:DisableAddon(module) |
end |
end |
return not self.statuses[addon.name] -- return true if we're disabled |
end |
--The next few funcs are just because no one should be reaching into the internal registries |
--Thoughts? |
function AceAddon:IterateAddons() return pairs(self.addons) end |
function AceAddon:IterateEmbedsOnAddon(addon) return pairs(self.embeds[addon]) end |
function AceAddon:IterateAddonStatus() return pairs(self.statuses) end |
function AceAddon:IterateModulesOfAddon(addon) return pairs(addon.modules) end |
-- Event Handling |
local function onEvent(this, event, arg1) |
if event == "ADDON_LOADED" 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) |
end |
--- **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 777 2009-04-04 20:16:09Z nevcairiel $ |
local MAJOR, MINOR = "AceAddon-3.0", 5 |
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 |
local tinsert, tconcat = table.insert, table.concat |
local fmt = string.format |
local pairs, next, type = pairs, next, type |
--[[ |
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 |
--- 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.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 |
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) |
return AceAddon:EnableAddon(self) |
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) |
for k, v in pairs(mixins) do |
target[k] = v |
end |
for k, v in pairs(pmixins) do |
target[k] = target[k] or v |
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. |
for name, module in pairs(addon.modules) do |
self:EnableAddon(module) |
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. |
for name, module in pairs(addon.modules) do |
self:DisableAddon(module) |
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) |
if event == "ADDON_LOADED" 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) |
end |
--- 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 801 2009-04-09 20:34:28Z nevcairiel $ |
--[[ |
AceConfigCmd-3.0 |
-- TODO: plugin args |
local MAJOR, MINOR = "AceConfigCmd-3.0", 6 |
local lib = LibStub:NewLibrary(MAJOR, MINOR) |
local MAJOR, MINOR = "AceConfigCmd-3.0", 9 |
local AceConfigCmd = LibStub:NewLibrary(MAJOR, MINOR) |
if not lib then return end |
if not AceConfigCmd then return end |
lib.commands = lib.commands or {} |
local commands = lib.commands |
AceConfigCmd.commands = AceConfigCmd.commands or {} |
local commands = AceConfigCmd.commands |
local cfgreg = LibStub("AceConfigRegistry-3.0") |
local AceConsole -- LoD |
if v.type == "group" and pickfirstset(v.cmdInline, v.inline, false) then |
print(" "..(desc or name)..":") |
showhelp(info, inputpos, v, true) |
else |
print(" |cffffff78"..k.."|r - "..(desc or name or "")) |
elseif v.type ~= "description" and v.type ~= "header" then |
local key = k:gsub(" ", "_") |
print(" |cffffff78"..key.."|r - "..(desc or name or "")) |
end |
end |
end |
return -- done, name was found in inline group |
end |
-- matching name and not a inline group |
elseif strlower(arg)==strlower(k) then |
elseif strlower(arg)==strlower(k:gsub(" ", "_")) then |
info[depth+1] = k |
return handle(info,nextpos,v,depth+1) |
end |
elseif tab.type=="select" then |
------------ select ------------------------------------ |
local str = strtrim(strlower(str)) |
if str == "" then |
--TODO: Show current selection and possible values |
return |
end |
local values = tab.values |
if type(values) == "function" or type(values) == "string" then |
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 |
elseif tab.type=="multiselect" then |
------------ multiselect ------------------------------------------- |
local str = strtrim(strlower(str)) |
if str == "" then |
--TODO: Show current values |
return |
end |
local values = tab.values |
if type(values) == "function" or type(values) == "string" then |
info.values = values |
values = callmethod(info, inputpos, tab, "values") |
info.values = nil |
end |
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 |
end |
end |
----------------------------------------------------------------------- |
-- HandleCommand(slashcmd, appName, input) |
-- |
-- Call this from a chat command handler to parse the command input as operations on an aceoptions table |
--- 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") |
-- |
-- slashcmd (string) - the slash command WITHOUT leading slash (only used for error output) |
-- appName (string) - the application name as given to AceConfigRegistry:RegisterOptionsTable() |
-- input (string) -- the commandline input (as given by the WoW handler, i.e. without the command itself) |
-- -- 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) |
function lib: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) |
handle(info, 1, options, 0) -- (info, inputpos, table, depth) |
end |
----------------------------------------------------------------------- |
-- CreateChatCommand(slashcmd, appName) |
-- |
-- Utility function to create a slash command handler. |
--- Utility function to create a slash command handler. |
-- Also registers tab completion with AceTab |
-- |
-- slashcmd (string) - the slash command WITHOUT leading slash (only used for error output) |
-- appName (string) - the application name as given to AceConfigRegistry:RegisterOptionsTable() |
function lib:CreateChatCommand(slashcmd, appName) |
-- @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) |
lib.HandleCommand(self, slashcmd, appName, input) -- upgradable |
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 |
-- GetChatCommandOptions(slashcmd) |
-- |
-- Utility function that returns the options table that belongs to a slashcommand |
-- mainly used by AceTab |
function lib:GetChatCommandOptions(slashcmd) |
--- 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 |
--[[ |
AceConfigRegistry-3.0: |
--- 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.\\ |
-- These functions receive two arguments: "uiType" and "uiName". \\ |
-- Valid "uiTypes": "cmd", "dropdown", "dialog". This is verified by the library at call time. \\ |
-- The "uiName" field is expected to contain the full name of the calling addon, including version, e.g. "FooBar-1.0". This is verified by the library at call time.\\ |
-- :IterateOptionsTables() and :GetOptionsTable() always return a function reference that the requesting config handling addon must call with the above arguments. |
-- @class file |
-- @name AceConfigRegistry-3.0 |
-- @release $Id: AceConfigRegistry-3.0.lua 785 2009-04-05 14:57:29Z nevcairiel $ |
local MAJOR, MINOR = "AceConfigRegistry-3.0", 9 |
local AceConfigRegistry = LibStub:NewLibrary(MAJOR, MINOR) |
Handle central registration of options tables in use by addons and modules. Do nothing else. |
if not AceConfigRegistry then return end |
Options tables can be registered as raw tables, or as function refs that return a table. |
These functions receive two arguments: "uiType" and "uiName". |
- Valid "uiTypes": "cmd", "dropdown", "dialog". This is verified by the library at call time. |
- The "uiName" field is expected to contain the full name of the calling addon, including version, e.g. "FooBar-1.0". This is verified by the library at call time. |
AceConfigRegistry.tables = AceConfigRegistry.tables or {} |
:IterateOptionsTables() and :GetOptionsTable() always return a function reference that the requesting config handling addon must call with the above arguments. |
]] |
local MAJOR, MINOR = "AceConfigRegistry-3.0", 6 |
local lib = LibStub:NewLibrary(MAJOR, MINOR) |
if not lib then return end |
lib.tables = lib.tables or {} |
local CallbackHandler = LibStub:GetLibrary("CallbackHandler-1.0") |
if not lib.callbacks then |
lib.callbacks = CallbackHandler:New(lib) |
if not AceConfigRegistry.callbacks then |
AceConfigRegistry.callbacks = CallbackHandler:New(AceConfigRegistry) |
end |
----------------------------------------------------------------------- |
-- Validating options table consistency: |
lib.validated = { |
AceConfigRegistry.validated = { |
-- list of options table names ran through :ValidateOptionsTable automatically. |
-- CLEARED ON PURPOSE, since newer versions may have newer validators |
cmd = {}, |
imageCoords=optmethodtable, |
imageHeight=optnumber, |
imageWidth=optnumber, |
fontSize=optstringfunc, |
}, |
group={ |
args=istable, |
childGroups=optstring, |
}, |
execute={ |
-- func={ |
-- ["function"]=true, |
-- ["string"]=true, |
-- _="methodname or funcref" |
-- }, |
image=optstringfunc, |
imageCoords=optmethodtable, |
imageHeight=optnumber, |
imageWidth=optnumber, |
}, |
input={ |
pattern=optstring, |
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 spaces (or control characters)", errlvl,...) |
if strfind(k, "[%c\127]") then |
err("["..tostring(k).."] - key name contained control characters", errlvl,...) |
end |
end |
end |
end |
--------------------------------------------------------------------- |
-- ------------------------------------------------------------------- |
-- :ValidateOptionsTable(options,name,errlvl) |
-- - options - the table |
-- - name - (string) name of table, used in error reports |
-- |
-- 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 |
function lib:ValidateOptionsTable(options,name,errlvl) |
function AceConfigRegistry:ValidateOptionsTable(options,name,errlvl) |
errlvl=(errlvl or 0)+1 |
name = name or "Optionstable" |
if not options.name then |
validate(options,errlvl,name) |
end |
------------------------------ |
-- :NotifyChange(appName) |
-- - appName - string identifying the addon |
-- |
-- Fires a ConfigTableChange callback for those listening in on it, allowing config GUIs to refresh |
------------------------------ |
function lib:NotifyChange(appName) |
if not lib.tables[appName] then return end |
lib.callbacks:Fire("ConfigTableChange", appName) |
--- 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: |
end |
end |
--------------------------------------------------------------------- |
-- :RegisterOptionsTable(appName, options) |
-- - appName - string identifying the addon |
-- - options - table or function reference |
function lib:RegisterOptionsTable(appName, options) |
--- 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. |
function AceConfigRegistry:RegisterOptionsTable(appName, options) |
if type(options)=="table" then |
if options.type~="group" then -- quick sanity checker |
error(MAJOR..": RegisterOptionsTable(appName, options): 'options' - missing type='group' member in root group", 2) |
end |
lib.tables[appName] = function(uiType, uiName, errlvl) |
AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl) |
errlvl=(errlvl or 0)+1 |
validateGetterArgs(uiType, uiName, errlvl) |
if not lib.validated[uiType][appName] then |
lib:ValidateOptionsTable(options, appName, errlvl) -- upgradable |
lib.validated[uiType][appName] = true |
if not AceConfigRegistry.validated[uiType][appName] then |
AceConfigRegistry:ValidateOptionsTable(options, appName, errlvl) -- upgradable |
AceConfigRegistry.validated[uiType][appName] = true |
end |
return options |
end |
elseif type(options)=="function" then |
lib.tables[appName] = function(uiType, uiName, errlvl) |
AceConfigRegistry.tables[appName] = function(uiType, uiName, errlvl) |
errlvl=(errlvl or 0)+1 |
validateGetterArgs(uiType, uiName, errlvl) |
local tab = assert(options(uiType, uiName)) |
if not lib.validated[uiType][appName] then |
lib:ValidateOptionsTable(tab, appName, errlvl) -- upgradable |
lib.validated[uiType][appName] = true |
if not AceConfigRegistry.validated[uiType][appName] then |
AceConfigRegistry:ValidateOptionsTable(tab, appName, errlvl) -- upgradable |
AceConfigRegistry.validated[uiType][appName] = true |
end |
return tab |
end |
end |
end |
--------------------------------------------------------------------- |
-- :IterateOptionsTables() |
-- |
-- Returns an iterator of ["appName"]=funcref pairs |
function lib:IterateOptionsTables() |
return pairs(lib.tables) |
--- Returns an iterator of ["appName"]=funcref pairs |
function AceConfigRegistry:IterateOptionsTables() |
return pairs(AceConfigRegistry.tables) |
end |
-- - uiType - "cmd", "dropdown", "dialog" |
-- - uiName - e.g. "MyLib-1.0" |
-- |
--- 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. |
-- can call with (uiType,uiName) to get the table.\\ |
-- If uiType&uiName are given, the table is returned. |
function lib:GetOptionsTable(appName, uiType, uiName) |
local f = lib.tables[appName] |
-- @param appName The application name as given to `:RegisterOptionsTable()` |
-- @param uiType The type of UI to get the table for. |
-- @param uiName The name of the library/addon querying the table. |
function AceConfigRegistry:GetOptionsTable(appName, uiType, uiName) |
local f = AceConfigRegistry.tables[appName] |
if not f then |
return nil |
end |
--[[ $Id: AceConfig-3.0.lua 60131 2008-02-03 13:03:56Z nevcairiel $ ]] |
--- 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 802 2009-04-11 12:12:37Z nevcairiel $ |
--[[ |
AceConfig-3.0 |
Very light wrapper library that combines all the AceConfig subcomponents into one more easily used whole. |
Also automatically adds "config", "enable" and "disable" commands to options table as appropriate. |
]] |
local MAJOR, MINOR = "AceConfig-3.0", 2 |
local lib = LibStub:NewLibrary(MAJOR, MINOR) |
local AceConfig = LibStub:NewLibrary(MAJOR, MINOR) |
if not lib then return end |
if not AceConfig then return end |
local cfgreg = LibStub("AceConfigRegistry-3.0") |
--TODO: local cfgdrp = LibStub("AceConfigDropdown-3.0") |
--------------------------------------------------------------------- |
-- ------------------------------------------------------------------- |
-- :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 |
function lib:RegisterOptionsTable(appName, options, slashcmd) |
--- Register a option table with the AceConfig registry. |
-- You can supply a slash command (or a table of slash commands) to register with AceConfigCmd directly. |
-- @paramsig appName, options [, slashcmd] |
-- @param appName The application name for the config table. |
-- @param options The option table (or a function to generate one on demand) |
-- @param slashcmd A slash command to register for the option table, or a table of slash commands. |
-- @usage |
-- local AceConfig = LibStub("AceConfig-3.0") |
-- AceConfig:RegisterOptionsTable("MyAddon", myOptions, {"/myslash", "/my"}) |
function AceConfig:RegisterOptionsTable(appName, options, slashcmd) |
local ok,msg = pcall(cfgreg.RegisterOptionsTable, self, appName, options) |
if not ok then error(msg, 2) end |
--[[ |
AceConfigDialog-3.0 |
--- AceConfigDialog-3.0 generates AceGUI-3.0 based windows based on option tables. |
-- @class file |
-- @name AceConfigDialog-3.0 |
-- @release $Id: AceConfigDialog-3.0.lua 796 2009-04-07 15:48:54Z nevcairiel $ |
]] |
local LibStub = LibStub |
local MAJOR, MINOR = "AceConfigDialog-3.0", 25 |
local lib = LibStub:NewLibrary(MAJOR, MINOR) |
local MAJOR, MINOR = "AceConfigDialog-3.0", 34 |
local AceConfigDialog = LibStub:NewLibrary(MAJOR, MINOR) |
if not lib then return end |
if not AceConfigDialog then return end |
lib.OpenFrames = lib.OpenFrames or {} |
lib.Status = lib.Status or {} |
lib.frame = lib.frame or CreateFrame("Frame") |
AceConfigDialog.OpenFrames = AceConfigDialog.OpenFrames or {} |
AceConfigDialog.Status = AceConfigDialog.Status or {} |
AceConfigDialog.frame = AceConfigDialog.frame or CreateFrame("Frame") |
lib.frame.apps = lib.frame.apps or {} |
lib.frame.closing = lib.frame.closing or {} |
AceConfigDialog.frame.apps = AceConfigDialog.frame.apps or {} |
AceConfigDialog.frame.closing = AceConfigDialog.frame.closing or {} |
local gui = LibStub("AceGUI-3.0") |
local reg = LibStub("AceConfigRegistry-3.0") |
usage = true, |
width = true, |
image = true, |
fontSize = true, |
} |
--Is Never a function or method |
end |
end |
--[[ |
Gets a status table for the given appname and options path |
]] |
function lib:GetStatusTable(appName, path) |
-- - Gets a status table for the given appname and options path. |
-- @param appName The application name as given to `:RegisterOptionsTable()` |
-- @param path The path to the options (a table with all group keys) |
-- @return |
function AceConfigDialog:GetStatusTable(appName, path) |
local status = self.Status |
if not status[appName] then |
return status.status |
end |
--[[ |
Sets the given path to be selected |
]] |
function lib:SelectGroup(appName, ...) |
--- Selects the specified path in the options window. |
-- The path specified has to match the keys of the groups in the table. |
-- @param appName The application name as given to `:RegisterOptionsTable()` |
-- @param ... The path to the key that should be selected |
function AceConfigDialog:SelectGroup(appName, ...) |
local path = new() |
if dialog and oldstrata then |
dialog:SetFrameStrata(oldstrata) |
end |
lib:Open(appName, rootframe, basepath and unpack(basepath)) |
AceConfigDialog:Open(appName, rootframe, basepath and unpack(basepath)) |
del(info) |
end |
t.OnCancel = function() |
if dialog and oldstrata then |
dialog:SetFrameStrata(oldstrata) |
end |
AceConfigDialog:Open(appName, rootframe, basepath and unpack(basepath)) |
del(info) |
end |
for i = 1, select('#', ...) do |
if event == "OnValueConfirmed" then |
if iscustom then |
lib:Open(user.appName, user.rootframe, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, user.rootframe, basepath and unpack(basepath)) |
else |
lib:Open(user.appName, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, basepath and unpack(basepath)) |
end |
end |
elseif option.type == "range" then |
if event == "OnMouseUp" then |
if iscustom then |
lib:Open(user.appName, user.rootframe, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, user.rootframe, basepath and unpack(basepath)) |
else |
lib:Open(user.appName, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, basepath and unpack(basepath)) |
end |
end |
--multiselects don't cause a refresh on 'OnValueChanged' only 'OnClosed' |
user.valuechanged = true |
else |
if iscustom then |
lib:Open(user.appName, user.rootframe, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, user.rootframe, basepath and unpack(basepath)) |
else |
lib:Open(user.appName, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, basepath and unpack(basepath)) |
end |
end |
local iscustom = user.rootframe:GetUserData('iscustom') |
local basepath = user.rootframe:GetUserData('basepath') |
if iscustom then |
lib:Open(user.appName, user.rootframe, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, user.rootframe, basepath and unpack(basepath)) |
else |
lib:Open(user.appName, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, basepath and unpack(basepath)) |
end |
end |
local iscustom = user.rootframe:GetUserData('iscustom') |
local basepath = user.rootframe:GetUserData('basepath') |
if iscustom then |
lib:Open(user.appName, user.rootframe, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, user.rootframe, basepath and unpack(basepath)) |
else |
lib:Open(user.appName, basepath and unpack(basepath)) |
AceConfigDialog:Open(user.appName, basepath and unpack(basepath)) |
end |
end |
end |
local function FrameOnClose(widget, event) |
local appName = widget:GetUserData('appName') |
lib.OpenFrames[appName] = nil |
AceConfigDialog.OpenFrames[appName] = nil |
gui:Release(widget) |
end |
local entry = new() |
entry.value = k |
entry.text = GetOptionsMemberValue("name", v, options, path, appName) |
entry.icon = GetOptionsMemberValue("icon", v, options, path, appName) |
entry.disabled = CheckOptionDisabled(v, options, path, appName) |
if not tree.children then tree.children = new() end |
tinsert(tree.children,entry) |
local entry = new() |
entry.value = k |
entry.text = GetOptionsMemberValue("name", v, options, path, appName) |
entry.icon = GetOptionsMemberValue("icon", v, options, path, appName) |
entry.disabled = CheckOptionDisabled(v, options, path, appName) |
tinsert(tree,entry) |
if recurse and (v.childGroups or "tree") == "tree" then |
local name = GetOptionsMemberValue("name", v, options, path, appName) |
if v.type == "execute" then |
control = gui:Create("Button") |
control:SetText(name) |
local imageCoords = GetOptionsMemberValue("imageCoords",v, options, path, appName) |
local image, width, height = GetOptionsMemberValue("image",v, options, path, appName) |
if type(image) == 'string' then |
control = gui:Create("Icon") |
if not width then |
width = GetOptionsMemberValue("imageWidth",v, options, path, appName) |
end |
if not height then |
height = GetOptionsMemberValue("imageHeight",v, options, path, appName) |
end |
if type(imageCoords) == 'table' then |
control:SetImage(image, unpack(imageCoords)) |
else |
control:SetImage(image) |
end |
if type(width) ~= "number" then |
width = 32 |
end |
if type(height) ~= "number" then |
height = 32 |
end |
control:SetImageSize(width, height) |
control:SetLabel(name) |
else |
control = gui:Create("Button") |
control:SetText(name) |
end |
control:SetCallback("OnClick",ActivateControl) |
elseif v.type == "input" then |
elseif v.type == "description" then |
control = gui:Create("Label") |
control:SetText(name) |
local fontSize = GetOptionsMemberValue("fontSize",v, options, path, appName) |
if fontSize == "medium" then |
control:SetFontObject(GameFontHighlight) |
elseif fontSize == "large" then |
control:SetFontObject(GameFontHighlightLarge) |
else -- small or invalid |
control:SetFontObject(GameFontHighlightSmall) |
end |
local imageCoords = GetOptionsMemberValue("imageCoords",v, options, path, appName) |
local image, width, height = GetOptionsMemberValue("image",v, options, path, appName) |
group = GetSubOption(group, feedpath[i]) |
end |
widget:ReleaseChildren() |
lib:FeedGroup(user.appName,options,widget,rootframe,feedpath) |
AceConfigDialog:FeedGroup(user.appName,options,widget,rootframe,feedpath) |
del(feedpath) |
end |
--[[ |
-- INTERNAL -- |
This function will feed one group, and any inline child groups into the given container |
Select Groups will only have the selection control (tree, tabs, dropdown) fed in |
and have a group selected, this event will trigger the feeding of child groups |
if its parent is a tree group, its already a node on a tree |
--]] |
function lib:FeedGroup(appName,options,container,rootframe,path, isRoot) |
function AceConfigDialog:FeedGroup(appName,options,container,rootframe,path, isRoot) |
local group = options |
--follow the path to get to the curent group |
local inline |
--check if the group has child groups |
local hasChildGroups |
for k, v in pairs(group.args) do |
if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) then |
if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) and not CheckOptionHidden(v, options, path, appName) then |
hasChildGroups = true |
end |
end |
if group.plugins then |
for plugin, t in pairs(group.plugins) do |
for k, v in pairs(t) do |
if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) then |
if v.type == "group" and not pickfirstset(v.dialogInline,v.guiInline,v.inline, false) and not CheckOptionHidden(v, options, path, appName) then |
hasChildGroups = true |
end |
end |
tab:SetCallback("OnTabEnter", TreeOnButtonEnter) |
tab:SetCallback("OnTabLeave", TreeOnButtonLeave) |
local status = lib:GetStatusTable(appName, path) |
local status = AceConfigDialog:GetStatusTable(appName, path) |
if not status.groups then |
status.groups = {} |
end |
local select = gui:Create("DropdownGroup") |
InjectInfo(select, options, group, path, rootframe, appName) |
select:SetCallback("OnGroupSelected", GroupSelected) |
local status = lib:GetStatusTable(appName, path) |
local status = AceConfigDialog:GetStatusTable(appName, path) |
if not status.groups then |
status.groups = {} |
end |
tree:SetCallback("OnButtonEnter", TreeOnButtonEnter) |
tree:SetCallback("OnButtonLeave", TreeOnButtonLeave) |
local status = lib:GetStatusTable(appName, path) |
local status = AceConfigDialog:GetStatusTable(appName, path) |
if not status.groups then |
status.groups = {} |
end |
local function RefreshOnUpdate(this) |
for appName in pairs(this.closing) do |
if lib.OpenFrames[appName] then |
lib.OpenFrames[appName]:Hide() |
if AceConfigDialog.OpenFrames[appName] then |
AceConfigDialog.OpenFrames[appName]:Hide() |
end |
if AceConfigDialog.BlizOptions and AceConfigDialog.BlizOptions[appName] then |
local widget = AceConfigDialog.BlizOptions[appName] |
if not widget:IsVisible() then |
widget:ReleaseChildren() |
end |
end |
this.closing[appName] = nil |
end |
if this.closeAll then |
for k, v in pairs(lib.OpenFrames) do |
for k, v in pairs(AceConfigDialog.OpenFrames) do |
v:Hide() |
end |
this.closeAll = nil |
end |
for appName in pairs(this.apps) do |
if lib.OpenFrames[appName] then |
local user = lib.OpenFrames[appName]:GetUserDataTable() |
lib:Open(appName, user.basepath and unpack(user.basepath)) |
if AceConfigDialog.OpenFrames[appName] then |
local user = AceConfigDialog.OpenFrames[appName]:GetUserDataTable() |
AceConfigDialog:Open(appName, user.basepath and unpack(user.basepath)) |
end |
if lib.BlizOptions and lib.BlizOptions[appName] then |
local widget = lib.BlizOptions[appName] |
if AceConfigDialog.BlizOptions and AceConfigDialog.BlizOptions[appName] then |
local widget = AceConfigDialog.BlizOptions[appName] |
local user = widget:GetUserDataTable() |
if widget:IsVisible() then |
lib:Open(widget:GetUserData('appName'), widget, user.basepath and unpack(user.basepath)) |
AceConfigDialog:Open(widget:GetUserData('appName'), widget, user.basepath and unpack(user.basepath)) |
end |
end |
this.apps[appName] = nil |
this:SetScript("OnUpdate", nil) |
end |
function lib:CloseAll() |
lib.frame.closeAll = true |
lib.frame:SetScript("OnUpdate", RefreshOnUpdate) |
--- Close all open options windows |
function AceConfigDialog:CloseAll() |
AceConfigDialog.frame.closeAll = true |
AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate) |
if next(self.OpenFrames) then |
return true |
end |
end |
function lib:Close(appName) |
--- Close a specific options window. |
-- @param appName The application name as given to `:RegisterOptionsTable()` |
function AceConfigDialog:Close(appName) |
if self.OpenFrames[appName] then |
lib.frame.closing[appName] = true |
lib.frame:SetScript("OnUpdate", RefreshOnUpdate) |
AceConfigDialog.frame.closing[appName] = true |
AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate) |
return true |
end |
end |
function lib:ConfigTableChanged(event, appName) |
lib.frame.apps[appName] = true |
lib.frame:SetScript("OnUpdate", RefreshOnUpdate) |
-- Internal -- Called by AceConfigRegistry |
function AceConfigDialog:ConfigTableChanged(event, appName) |
AceConfigDialog.frame.apps[appName] = true |
AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate) |
end |
reg.RegisterCallback(lib, "ConfigTableChange", "ConfigTableChanged") |
reg.RegisterCallback(AceConfigDialog, "ConfigTableChange", "ConfigTableChanged") |
function lib:SetDefaultSize(appName, width, height) |
local status = lib:GetStatusTable(appName) |
--- Sets the default size of the options window for a specific application. |
-- @param appName The application name as given to `:RegisterOptionsTable()` |
-- @param width The default width |
-- @param height The default height |
function AceConfigDialog:SetDefaultSize(appName, width, height) |
local status = AceConfigDialog:GetStatusTable(appName) |
if type(width) == "number" and type(height) == "number" then |
status.width = width |
status.height = height |
end |
end |
-- :Open(appName, [container], [path ...]) |
function lib:Open(appName, container, ...) |
--- Open an option window at the specified path (if any). |
-- This function can optionally feed the group into a pre-created container |
-- instead of creating a new container frame. |
-- @paramsig appName [, container][, ...] |
-- @param appName The application name as given to `:RegisterOptionsTable()` |
-- @param container An optional container frame to feed the options into |
-- @param ... The path to open after creating the options window (see `:SelectGroup` for details) |
function AceConfigDialog:Open(appName, container, ...) |
if not old_CloseSpecialWindows then |
old_CloseSpecialWindows = CloseSpecialWindows |
CloseSpecialWindows = function() |
if #path > 0 then |
f:SetUserData('basepath', copy(path)) |
end |
local status = lib:GetStatusTable(appName) |
local status = AceConfigDialog:GetStatusTable(appName) |
if not status.width then |
status.width = 700 |
end |
f:SetUserData('basepath', copy(path)) |
end |
f:SetTitle(name or "") |
local status = lib:GetStatusTable(appName) |
local status = AceConfigDialog:GetStatusTable(appName) |
f:SetStatusTable(status) |
end |
del(path) |
end |
lib.BlizOptions = lib.BlizOptions or {} |
AceConfigDialog.BlizOptions = AceConfigDialog.BlizOptions or {} |
local function FeedToBlizPanel(widget, event) |
local path = widget:GetUserData('path') |
lib:Open(widget:GetUserData('appName'), widget, path and unpack(path)) |
AceConfigDialog:Open(widget:GetUserData('appName'), widget, path and unpack(path)) |
end |
local function ClearBlizPanel(widget, event) |
widget:ReleaseChildren() |
local appName = widget:GetUserData('appName') |
AceConfigDialog.frame.closing[appName] = true |
AceConfigDialog.frame:SetScript("OnUpdate", RefreshOnUpdate) |
end |
function lib:AddToBlizOptions(appName, name, parent, ...) |
local BlizOptions = lib.BlizOptions |
--- Add an option table into the Blizzard Interface Options panel. |
-- You can optionally supply a descriptive name to use and a parent frame to use, |
-- as well as a path in the options table.\\ |
-- If no name is specified, the appName will be used instead. |
-- |
-- If you specify a proper `parent` (by name), the interface options will generate a |
-- tree layout. Note that only one level of children is supported, so the parent always |
-- has to be a head-level note. |
-- |
-- This function returns a reference to the container frame registered with the Interface |
-- Options. You can use this reference to open the options with the API function |
-- `InterfaceOptionsFrame_OpenToCategory`. |
-- @param appName The application name as given to `:RegisterOptionsTable()` |
-- @param name A descriptive name to display in the options tree (defaults to appName) |
-- @param parent The parent to use in the interface options tree. |
-- @param ... The path in the options table to feed into the interface options panel. |
-- @return The reference to the frame registered into the Interface Options. |
function AceConfigDialog:AddToBlizOptions(appName, name, parent, ...) |
local BlizOptions = AceConfigDialog.BlizOptions |
local key = appName |
for n = 1, select('#', ...) do |
--[[ $Id: AceDB-3.0.lua 81438 2008-09-06 13:44:36Z nevcairiel $ ]] |
local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 8 |
--- **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. |
-- * **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 813 2009-07-06 21:36:37Z kaelten $ |
local ACEDB_MAJOR, ACEDB_MINOR = "AceDB-3.0", 15 |
local AceDB, oldminor = LibStub:NewLibrary(ACEDB_MAJOR, ACEDB_MINOR) |
if not AceDB then return end -- No upgrade needed |
local _G = getfenv(0) |
local type = type |
local pairs, next = pairs, next |
local rawget, rawset = rawget, rawset |
if defaults[key] == nil and (not blocker or blocker[key] == nil) then |
removeDefaults(value, v) |
-- if the table is empty afterwards, remove it |
if not next(value) then |
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 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 not next(db[k]) then |
if next(db[k]) == nil then |
db[k] = nil |
end |
else |
-- Make a container for profile keys |
if not sv.profileKeys then sv.profileKeys = {} end |
-- map "true" to our "Default" profile |
if defaultProfile == true then defaultProfile = "Default" end |
-- Try to get the profile selected from the char db |
local profileKey = sv.profileKeys[charKey] or defaultProfile or charKey |
sv.profileKeys[charKey] = profileKey |
AceDB Object Method Definitions |
---------------------------------------------------------------------------]] |
-- DBObject:RegisterDefaults(defaults) |
-- defaults (table) - A table of defaults for this database |
-- |
-- Sets the defaults table for the given database object by clearing any |
--- 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 |
end |
-- DBObject:SetProfile(name) |
-- name (string) - The name of the profile to set as the current profile |
-- |
-- Changes the profile of the database and all of it's namespaces to the |
--- 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) |
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) |
self.callbacks:Fire("OnProfileChanged", self, name) |
end |
-- DBObject:GetProfiles(tbl) |
-- tbl (table) - A table to store the profile names in (optional) |
-- |
-- Returns a table with the names of the existing profiles in the database. |
--- 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) |
return tbl, i |
end |
-- DBObject:GetCurrentProfile() |
-- |
-- Returns the current profile name used by the database |
--- Returns the current profile name used by the database |
function DBObjectLib:GetCurrentProfile() |
return self.keys.profile |
end |
-- DBObject:DeleteProfile(name) |
-- name (string) - The name of the profile to be deleted |
-- |
-- Deletes a named profile. This profile must not be the active profile. |
--- 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) |
self.callbacks:Fire("OnProfileDeleted", self, name) |
end |
-- DBObject:CopyProfile(name) |
-- name (string) - The name of the profile to be copied into the current profile |
-- |
-- Copies a named profile into the current profile, overwriting any conflicting |
--- 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) |
self.callbacks:Fire("OnProfileCopied", self, name) |
end |
-- DBObject:ResetProfile() |
-- noChildren (boolean) - if set to true, the reset will not be populated to the child namespaces of this DB object |
-- |
-- Resets the current profile |
--- 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 |
function DBObjectLib:ResetProfile(noChildren) |
local profile = self.profile |
self.callbacks:Fire("OnProfileReset", self) |
end |
-- DBObject:ResetDB(defaultProfile) |
-- defaultProfile (string) - The profile name to use as the default |
-- |
-- Resets the entire database, using the string defaultProfile as the default |
--- 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) |
return self |
end |
-- DBObject:RegisterNamespace(name [, defaults]) |
-- name (string) - The name of the new namespace |
-- defaults (table) - A table of values to use as defaults |
-- |
-- Creates a new database namespace, directly tied to the database. This |
--- 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) |
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 |
---------------------------------------------------------------------------]] |
-- AceDB:New(name, defaults, defaultProfile) |
-- name (table or string) - The name of variable, or table to use for the database |
-- defaults (table) - A table of database defaults |
-- defaultProfile (string) - The name of the default profile |
--- 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. |
-- |
-- Creates a new database object that can be used to handle database settings |
-- and profiles. |
-- 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 = getglobal(name) |
tbl = _G[name] |
if not tbl then |
tbl = {} |
setglobal(name, tbl) |
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaults' - table expected.", 2) |
end |
if defaultProfile and type(defaultProfile) ~= "string" then |
error("Usage: AceDB:New(tbl, defaults, defaultProfile): 'defaultProfile' - string expected.", 2) |
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 |
else |
db.RegisterDefaults = DBObjectLib.RegisterDefaults |
db.ResetProfile = DBObjectLib.ResetProfile |
end |
end |
local MYTHREAT_VERSION = '1.5.1'; |
local MYTHREAT_VERSION = '1.5.2'; |
local MYTHREAT_ADJUST_VALUE = -410065408; |
local options = { |