diff lib/AceAddon-2.0/AceAddon-2.0.lua @ 22:1b9323256a1b

Merging in 1.0 dev tree
author Flick <flickerstreak@gmail.com>
date Fri, 07 Mar 2008 22:10:55 +0000
parents libs/AceAddon-2.0/AceAddon-2.0.lua@c11ca1d8ed91
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/lib/AceAddon-2.0/AceAddon-2.0.lua	Fri Mar 07 22:10:55 2008 +0000
@@ -0,0 +1,1394 @@
+--[[
+Name: AceAddon-2.0
+Revision: $Rev: 46764 $
+Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
+Inspired By: Ace 1.x by Turan (turan@gryphon.com)
+Website: http://www.wowace.com/
+Documentation: http://www.wowace.com/wiki/AceAddon-2.0
+SVN: http://svn.wowace.com/wowace/trunk/Ace2/AceAddon-2.0
+Description: Base for all Ace addons to inherit from.
+Dependencies: AceLibrary, AceOO-2.0, AceEvent-2.0, (optional) AceConsole-2.0
+License: LGPL v2.1
+]]
+
+local MAJOR_VERSION = "AceAddon-2.0"
+local MINOR_VERSION = "$Revision: 46764 $"
+
+-- This ensures the code is only executed if the libary doesn't already exist, or is a newer version
+if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary.") end
+if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
+
+if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0.") end
+
+local function safecall(func,...)
+	local success, err = pcall(func,...)
+	if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("\n(.-: )in.-\n") or "") .. err) end
+end
+-- Localization
+local STANDBY, TITLE, NOTES, VERSION, AUTHOR, DATE, CATEGORY, EMAIL, CREDITS, WEBSITE, CATEGORIES, ABOUT, LICENSE, PRINT_ADDON_INFO, DONATE, DONATE_DESC, HOWTO_DONATE_WINDOWS, HOWTO_DONATE_MAC
+if GetLocale() == "deDE" then
+	STANDBY = "|cffff5050(Standby)|r" -- capitalized
+
+	TITLE = "Titel"
+	NOTES = "Anmerkung"
+	VERSION = "Version"
+	AUTHOR = "Autor"
+	DATE = "Datum"
+	CATEGORY = "Kategorie"
+	EMAIL = "E-Mail"
+	WEBSITE = "Webseite"
+	CREDITS = "Credits" -- fix
+	LICENSE = "License" -- fix
+
+	ABOUT = "Über"
+	PRINT_ADDON_INFO = "Gibt Addondaten aus"
+	DONATE = "Donate" -- fix
+	DONATE_DESC = "Give a much-needed donation to the author of this addon." -- fix
+	HOWTO_DONATE_WINDOWS = "Press Ctrl-A to select the link, then Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix
+	HOWTO_DONATE_MAC = "Press Cmd-A to select the link, then Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix
+
+	CATEGORIES = {
+		["Action Bars"] = "Aktionsleisten",
+		["Auction"] = "Auktion",
+		["Audio"] = "Audio",
+		["Battlegrounds/PvP"] = "Schlachtfeld/PvP",
+		["Buffs"] = "Stärkungszauber",
+		["Chat/Communication"] = "Chat/Kommunikation",
+		["Druid"] = "Druide",
+		["Hunter"] = "Jäger",
+		["Mage"] = "Magier",
+		["Paladin"] = "Paladin",
+		["Priest"] = "Priester",
+		["Rogue"] = "Schurke",
+		["Shaman"] = "Schamane",
+		["Warlock"] = "Hexenmeister",
+		["Warrior"] = "Krieger",
+		["Healer"] = "Heiler",
+		["Tank"] = "Tank",
+		["Caster"] = "Zauberer",
+		["Combat"] = "Kampf",
+		["Compilations"] = "Zusammenstellungen",
+		["Data Export"] = "Datenexport",
+		["Development Tools"] = "Entwicklungs Tools",
+		["Guild"] = "Gilde",
+		["Frame Modification"] = "Frame Veränderungen",
+		["Interface Enhancements"] = "Interface Verbesserungen",
+		["Inventory"] = "Inventar",
+		["Library"] = "Bibliotheken",
+		["Map"] = "Karte",
+		["Mail"] = "Post",
+		["Miscellaneous"] = "Diverses",
+		["Quest"] = "Quest",
+		["Raid"] = "Schlachtzug",
+		["Tradeskill"] = "Beruf",
+		["UnitFrame"] = "Einheiten-Fenster",
+	}
+elseif GetLocale() == "frFR" then
+	STANDBY = "|cffff5050(attente)|r"
+
+	TITLE = "Titre"
+	NOTES = "Notes"
+	VERSION = "Version"
+	AUTHOR = "Auteur"
+	DATE = "Date"
+	CATEGORY = "Catégorie"
+	EMAIL = "E-mail"
+	WEBSITE = "Site web"
+	CREDITS = "Credits" -- fix
+	LICENSE = "License" -- fix
+
+	ABOUT = "A propos"
+	PRINT_ADDON_INFO = "Afficher les informations sur l'addon"
+	DONATE = "Donate" -- fix
+	DONATE_DESC = "Give a much-needed donation to the author of this addon." -- fix
+	HOWTO_DONATE_WINDOWS = "Press Ctrl-A to select the link, then Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix
+	HOWTO_DONATE_MAC = "Press Cmd-A to select the link, then Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix
+
+	CATEGORIES = {
+		["Action Bars"] = "Barres d'action",
+		["Auction"] = "Hôtel des ventes",
+		["Audio"] = "Audio",
+		["Battlegrounds/PvP"] = "Champs de bataille/JcJ",
+		["Buffs"] = "Buffs",
+		["Chat/Communication"] = "Chat/Communication",
+		["Druid"] = "Druide",
+		["Hunter"] = "Chasseur",
+		["Mage"] = "Mage",
+		["Paladin"] = "Paladin",
+		["Priest"] = "Prêtre",
+		["Rogue"] = "Voleur",
+		["Shaman"] = "Chaman",
+		["Warlock"] = "Démoniste",
+		["Warrior"] = "Guerrier",
+		["Healer"] = "Soigneur",
+		["Tank"] = "Tank",
+		["Caster"] = "Casteur",
+		["Combat"] = "Combat",
+		["Compilations"] = "Compilations",
+		["Data Export"] = "Exportation de données",
+		["Development Tools"] = "Outils de développement",
+		["Guild"] = "Guilde",
+		["Frame Modification"] = "Modification des fenêtres",
+		["Interface Enhancements"] = "Améliorations de l'interface",
+		["Inventory"] = "Inventaire",
+		["Library"] = "Bibliothèques",
+		["Map"] = "Carte",
+		["Mail"] = "Courrier",
+		["Miscellaneous"] = "Divers",
+		["Quest"] = "Quêtes",
+		["Raid"] = "Raid",
+		["Tradeskill"] = "Métiers",
+		["UnitFrame"] = "Fenêtres d'unité",
+	}
+elseif GetLocale() == "koKR" then
+	STANDBY = "|cffff5050(사용가능)|r"
+
+	TITLE = "제목"
+	NOTES = "노트"
+	VERSION = "버전"
+	AUTHOR = "저작자"
+	DATE = "날짜"
+	CATEGORY = "분류"
+	EMAIL = "전자 우편"
+	WEBSITE = "웹 사이트"
+	CREDITS = "공로자"
+	LICENSE = "라이센스"
+
+	ABOUT = "정보"
+	PRINT_ADDON_INFO = "애드온에 대한 정보를 출력합니다."
+	DONATE = "기부"
+	DONATE_DESC = "이 애드온의 저작자에게 기부를 합니다."
+	HOWTO_DONATE_WINDOWS = "Ctrl-A를 눌려 링크를 선택후, Ctrl-C로 복사합니다. Alt-Tab 눌려 게임으로 부터 나간후 웹 브라우저를 엽니다. 복사된 링크를 주소 창에 붙여넣기 합니다."
+	HOWTO_DONATE_MAC = "Cmd-A를 눌려 링크를 선택후, Cmd-C로 복사합니다. Cmd-Tab 눌려 게임으로 부터 나간후 웹 브라우저를 엽니다. 복사된 링크를 주소 창에 붙여넣기 합니다."
+
+	CATEGORIES = {
+		["Action Bars"] = "액션바",
+		["Auction"] = "경매",
+		["Audio"] = "음향",
+		["Battlegrounds/PvP"] = "전장/PvP",
+		["Buffs"] = "버프",
+		["Chat/Communication"] = "대화/의사소통",
+		["Druid"] = "드루이드",
+		["Hunter"] = "사냥꾼",
+		["Mage"] = "마법사",
+		["Paladin"] = "성기사",
+		["Priest"] = "사제",
+		["Rogue"] = "도적",
+		["Shaman"] = "주술사",
+		["Warlock"] = "흑마법사",
+		["Warrior"] = "전사",
+		["Healer"] = "힐러",
+		["Tank"] = "탱커",
+		["Caster"] = "캐스터",
+		["Combat"] = "전투",
+		["Compilations"] = "복합",
+		["Data Export"] = "자료 출력",
+		["Development Tools"] = "개발 도구",
+		["Guild"] = "길드",
+		["Frame Modification"] = "구조 변경",
+		["Interface Enhancements"] = "인터페이스 강화",
+		["Inventory"] = "인벤토리",
+		["Library"] = "라이브러리",
+		["Map"] = "지도",
+		["Mail"] = "우편",
+		["Miscellaneous"] = "기타",
+		["Quest"] = "퀘스트",
+		["Raid"] = "공격대",
+		["Tradeskill"] = "전문기술",
+		["UnitFrame"] = "유닛 프레임",
+	}
+elseif GetLocale() == "zhTW" then
+	STANDBY = "|cffff5050(待命)|r"
+
+	TITLE = "標題"
+	NOTES = "註記"
+	VERSION = "版本"
+	AUTHOR = "作者"
+	DATE = "日期"
+	CATEGORY = "類別"
+	EMAIL = "電子郵件"
+	WEBSITE = "網站"
+	CREDITS = "特別感謝"
+	LICENSE = "版權"
+
+	ABOUT = "關於"
+	PRINT_ADDON_INFO = "顯示插件資訊。"
+	DONATE = "捐贈"
+	DONATE_DESC = "捐贈金錢給插件作者。"
+	HOWTO_DONATE_WINDOWS = "請按Ctrl-A選擇網站連結,Ctrl-C複製網址,Alt-Tab切換到電腦桌面,打開瀏覽器,在網址列貼上網址。"
+	HOWTO_DONATE_MAC = "請按Cmd-A選擇網站連結,Cmd-C複製網址,Cmd-Tab切換到電腦桌面,打開瀏覽器,在網址列貼上網址。"
+
+	CATEGORIES = {
+		["Action Bars"] = "動作條",
+		["Auction"] = "拍賣",
+		["Audio"] = "音效",
+		["Battlegrounds/PvP"] = "戰場/PvP",
+		["Buffs"] = "增益",
+		["Chat/Communication"] = "聊天/通訊",
+		["Druid"] = "德魯伊",
+		["Hunter"] = "獵人",
+		["Mage"] = "法師",
+		["Paladin"] = "聖騎士",
+		["Priest"] = "牧師",
+		["Rogue"] = "盜賊",
+		["Shaman"] = "薩滿",
+		["Warlock"] = "術士",
+		["Warrior"] = "戰士",
+		["Healer"] = "治療者",
+		["Tank"] = "坦克",
+		["Caster"] = "施法者",
+		["Combat"] = "戰鬥",
+		["Compilations"] = "整合",
+		["Data Export"] = "資料匯出",
+		["Development Tools"] = "開發工具",
+		["Guild"] = "公會",
+		["Frame Modification"] = "框架修改",
+		["Interface Enhancements"] = "介面增強",
+		["Inventory"] = "庫存",
+		["Library"] = "程式庫",
+		["Map"] = "地圖",
+		["Mail"] = "郵件",
+		["Miscellaneous"] = "雜項",
+		["Quest"] = "任務",
+		["Raid"] = "團隊",
+		["Tradeskill"] = "交易技能",
+		["UnitFrame"] = "單位框架",
+	}
+elseif GetLocale() == "zhCN" then
+	STANDBY = "|cffff5050(暂挂)|r"
+
+	TITLE = "标题"
+	NOTES = "附注"
+	VERSION = "版本"
+	AUTHOR = "作者"
+	DATE = "日期"
+	CATEGORY = "分类"
+	EMAIL = "电子邮件"
+	WEBSITE = "网站"
+	CREDITS = "Credits" -- fix
+	LICENSE = "License" -- fix
+
+	ABOUT = "关于"
+	PRINT_ADDON_INFO = "印列出插件信息"
+	DONATE = "Donate" -- fix
+	DONATE_DESC = "Give a much-needed donation to the author of this addon." -- fix
+	HOWTO_DONATE_WINDOWS = "Press Ctrl-A to select the link, then Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix
+	HOWTO_DONATE_MAC = "Press Cmd-A to select the link, then Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix
+
+	CATEGORIES = {
+		["Action Bars"] = "动作条",
+		["Auction"] = "拍卖",
+		["Audio"] = "音频",
+		["Battlegrounds/PvP"] = "战场/PvP",
+		["Buffs"] = "增益魔法",
+		["Chat/Communication"] = "聊天/交流",
+		["Druid"] = "德鲁伊",
+		["Hunter"] = "猎人",
+		["Mage"] = "法师",
+		["Paladin"] = "圣骑士",
+		["Priest"] = "牧师",
+		["Rogue"] = "盗贼",
+		["Shaman"] = "萨满祭司",
+		["Warlock"] = "术士",
+		["Warrior"] = "战士",
+--		["Healer"] = "治疗保障",
+--		["Tank"] = "近战控制",
+--		["Caster"] = "远程输出",
+		["Combat"] = "战斗",
+		["Compilations"] = "编译",
+		["Data Export"] = "数据导出",
+		["Development Tools"] = "开发工具",
+		["Guild"] = "公会",
+		["Frame Modification"] = "框架修改",
+		["Interface Enhancements"] = "界面增强",
+		["Inventory"] = "背包",
+		["Library"] = "库",
+		["Map"] = "地图",
+		["Mail"] = "邮件",
+		["Miscellaneous"] = "杂项",
+		["Quest"] = "任务",
+		["Raid"] = "团队",
+		["Tradeskill"] = "商业技能",
+		["UnitFrame"] = "头像框架",
+	}
+elseif GetLocale() == "esES" then
+	STANDBY = "|cffff5050(espera)|r"
+
+	TITLE = "Título"
+	NOTES = "Notas"
+	VERSION = "Versión"
+	AUTHOR = "Autor"
+	DATE = "Fecha"
+	CATEGORY = "Categoría"
+	EMAIL = "E-mail"
+	WEBSITE = "Web"
+	CREDITS = "Créditos"
+	LICENSE = "License" -- fix
+
+	ABOUT = "Acerca de"
+	PRINT_ADDON_INFO = "Muestra información acerca del accesorio."
+	DONATE = "Donate" -- fix
+	DONATE_DESC = "Give a much-needed donation to the author of this addon." -- fix
+	HOWTO_DONATE_WINDOWS = "Press Ctrl-A to select the link, then Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix
+	HOWTO_DONATE_MAC = "Press Cmd-A to select the link, then Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar." -- fix
+
+	CATEGORIES = {
+		["Action Bars"] = "Barras de Acción",
+		["Auction"] = "Subasta",
+		["Audio"] = "Audio",
+		["Battlegrounds/PvP"] = "Campos de Batalla/JcJ",
+		["Buffs"] = "Buffs",
+		["Chat/Communication"] = "Chat/Comunicación",
+		["Druid"] = "Druida",
+		["Hunter"] = "Cazador",
+		["Mage"] = "Mago",
+		["Paladin"] = "Paladín",
+		["Priest"] = "Sacerdote",
+		["Rogue"] = "Pícaro",
+		["Shaman"] = "Chamán",
+		["Warlock"] = "Brujo",
+		["Warrior"] = "Guerrero",
+		["Healer"] = "Sanador",
+		["Tank"] = "Tanque",
+		["Caster"] = "Conjurador",
+		["Combat"] = "Combate",
+		["Compilations"] = "Compilaciones",
+		["Data Export"] = "Exportar Datos",
+		["Development Tools"] = "Herramientas de Desarrollo",
+		["Guild"] = "Hermandad",
+		["Frame Modification"] = "Modificación de Marcos",
+		["Interface Enhancements"] = "Mejoras de la Interfaz",
+		["Inventory"] = "Inventario",
+		["Library"] = "Biblioteca",
+		["Map"] = "Mapa",
+		["Mail"] = "Correo",
+		["Miscellaneous"] = "Misceláneo",
+		["Quest"] = "Misión",
+		["Raid"] = "Banda",
+		["Tradeskill"] = "Habilidad de Comercio",
+		["UnitFrame"] = "Marco de Unidades",
+	}
+else -- enUS
+	STANDBY = "|cffff5050(standby)|r"
+
+	TITLE = "Title"
+	NOTES = "Notes"
+	VERSION = "Version"
+	AUTHOR = "Author"
+	DATE = "Date"
+	CATEGORY = "Category"
+	EMAIL = "E-mail"
+	WEBSITE = "Website"
+	CREDITS = "Credits"
+	LICENSE = "License"
+
+	ABOUT = "About"
+	PRINT_ADDON_INFO = "Show information about the addon."
+	DONATE = "Donate"
+	DONATE_DESC = "Give a much-needed donation to the author of this addon."
+	HOWTO_DONATE_WINDOWS = "Press Ctrl-A to select the link, then Ctrl-C to copy, then Alt-Tab out of the game, open your favorite web browser, and paste the link into the address bar."
+	HOWTO_DONATE_MAC = "Press Cmd-A to select the link, then Cmd-C to copy, then Cmd-Tab out of the game, open your favorite web browser, and paste the link into the address bar."
+
+	CATEGORIES = {
+		["Action Bars"] = "Action Bars",
+		["Auction"] = "Auction",
+		["Audio"] = "Audio",
+		["Battlegrounds/PvP"] = "Battlegrounds/PvP",
+		["Buffs"] = "Buffs",
+		["Chat/Communication"] = "Chat/Communication",
+		["Druid"] = "Druid",
+		["Hunter"] = "Hunter",
+		["Mage"] = "Mage",
+		["Paladin"] = "Paladin",
+		["Priest"] = "Priest",
+		["Rogue"] = "Rogue",
+		["Shaman"] = "Shaman",
+		["Warlock"] = "Warlock",
+		["Warrior"] = "Warrior",
+		["Healer"] = "Healer",
+		["Tank"] = "Tank",
+		["Caster"] = "Caster",
+		["Combat"] = "Combat",
+		["Compilations"] = "Compilations",
+		["Data Export"] = "Data Export",
+		["Development Tools"] = "Development Tools",
+		["Guild"] = "Guild",
+		["Frame Modification"] = "Frame Modification",
+		["Interface Enhancements"] = "Interface Enhancements",
+		["Inventory"] = "Inventory",
+		["Library"] = "Library",
+		["Map"] = "Map",
+		["Mail"] = "Mail",
+		["Miscellaneous"] = "Miscellaneous",
+		["Quest"] = "Quest",
+		["Raid"] = "Raid",
+		["Tradeskill"] = "Tradeskill",
+		["UnitFrame"] = "UnitFrame",
+	}
+end
+
+setmetatable(CATEGORIES, { __index = function(self, key) -- case-insensitive
+	local lowerKey = key:lower()
+	for k,v in pairs(CATEGORIES) do
+		if k:lower() == lowerKey then
+			return v
+		end
+	end
+end })
+
+-- Create the library object
+
+local AceOO = AceLibrary("AceOO-2.0")
+local AceAddon = AceOO.Class()
+local AceEvent
+local AceConsole
+local AceModuleCore
+
+function AceAddon:GetLocalizedCategory(name)
+	self:argCheck(name, 2, "string")
+	return CATEGORIES[name] or UNKNOWN
+end
+
+function AceAddon:ToString()
+	return "AceAddon"
+end
+
+local function print(text)
+	DEFAULT_CHAT_FRAME:AddMessage(text)
+end
+
+function AceAddon:ADDON_LOADED(name)
+	local unregister = true
+	local initAddon = {}
+	while #self.nextAddon > 0 do
+		local addon = table.remove(self.nextAddon, 1)
+		if addon.possibleNames[name] then
+			table.insert(initAddon, addon)
+		else
+			unregister = nil
+			table.insert(self.skipAddon, addon)
+		end
+	end
+	self.nextAddon, self.skipAddon = self.skipAddon, self.nextAddon
+	if unregister then
+		AceAddon:UnregisterEvent("ADDON_LOADED")
+	end
+	while #initAddon > 0 do
+		local addon = table.remove(initAddon, 1)
+		table.insert(self.addons, addon)
+		if not self.addons[name] then
+			self.addons[name] = addon
+		end
+		addon.possibleNames = nil
+		self:InitializeAddon(addon, name)
+	end
+end
+
+local function RegisterOnEnable(self)
+	if DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.defaultLanguage then -- HACK
+		AceAddon.playerLoginFired = true
+	end
+	if AceAddon.playerLoginFired then
+		AceAddon.addonsStarted[self] = true
+		if (type(self.IsActive) ~= "function" or self:IsActive()) and (not AceModuleCore or not AceModuleCore:IsModule(self) or AceModuleCore:IsModuleActive(self)) then
+			AceAddon:ManualEnable(self)
+		end
+	else
+		if not AceAddon.addonsToOnEnable then
+			AceAddon.addonsToOnEnable = {}
+		end
+		table.insert(AceAddon.addonsToOnEnable, self)
+	end
+end
+
+function AceAddon:InitializeAddon(addon, name)
+	if addon.name == nil then
+		addon.name = name
+	end
+	if GetAddOnMetadata then
+		-- TOC checks
+		if addon.title == nil then
+			addon.title = GetAddOnMetadata(name, "Title")
+		end
+		if type(addon.title) == "string" then
+			local num = addon.title:find(" |cff7fff7f %-Ace2%-|r$")
+			if num then
+				addon.title = addon.title:sub(1, num - 1)
+			end
+			addon.title = addon.title:trim()
+		end
+		if addon.notes == nil then
+			addon.notes = GetAddOnMetadata(name, "Notes")
+		end
+		if type(addon.notes) == "string" then
+			addon.notes = addon.notes:trim()
+		end
+		if addon.version == nil then
+			addon.version = GetAddOnMetadata(name, "Version")
+		end
+		if type(addon.version) == "string" then
+			if addon.version:find("%$Revision: (%d+) %$") then
+				addon.version = addon.version:gsub("%$Revision: (%d+) %$", "%1")
+			elseif addon.version:find("%$Rev: (%d+) %$") then
+				addon.version = addon.version:gsub("%$Rev: (%d+) %$", "%1")
+			elseif addon.version:find("%$LastChangedRevision: (%d+) %$") then
+				addon.version = addon.version:gsub("%$LastChangedRevision: (%d+) %$", "%1")
+			end
+			addon.version = addon.version:trim()
+		end
+		if addon.author == nil then
+			addon.author = GetAddOnMetadata(name, "Author")
+		end
+		if type(addon.author) == "string" then
+			addon.author = addon.author:trim()
+		end
+		if addon.credits == nil then
+			addon.credits = GetAddOnMetadata(name, "X-Credits")
+		end
+		if type(addon.credits) == "string" then
+			addon.credits = addon.credits:trim()
+		end
+		if addon.donate == nil then
+			addon.donate = GetAddOnMetadata(name, "X-Donate")
+		end
+		if type(addon.donate) == "string" then
+			addon.donate = addon.donate:trim()
+		end
+		if addon.date == nil then
+			addon.date = GetAddOnMetadata(name, "X-Date") or GetAddOnMetadata(name, "X-ReleaseDate")
+		end
+		if type(addon.date) == "string" then
+			if addon.date:find("%$Date: (.-) %$") then
+				addon.date = addon.date:gsub("%$Date: (.-) %$", "%1")
+			elseif addon.date:find("%$LastChangedDate: (.-) %$") then
+				addon.date = addon.date:gsub("%$LastChangedDate: (.-) %$", "%1")
+			end
+			addon.date = addon.date:trim()
+		end
+
+		if addon.category == nil then
+			addon.category = GetAddOnMetadata(name, "X-Category")
+		end
+		if type(addon.category) == "string" then
+			addon.category = addon.category:trim()
+		end
+		if addon.email == nil then
+			addon.email = GetAddOnMetadata(name, "X-eMail") or GetAddOnMetadata(name, "X-Email")
+		end
+		if type(addon.email) == "string" then
+			addon.email = addon.email:trim()
+		end
+		if addon.license == nil then
+			addon.license = GetAddOnMetadata(name, "X-License")
+		end
+		if type(addon.license) == "string" then
+			addon.license = addon.license:trim()
+		end
+		if addon.website == nil then
+			addon.website = GetAddOnMetadata(name, "X-Website")
+		end
+		if type(addon.website) == "string" then
+			addon.website = addon.website:trim()
+		end
+	end
+	local current = addon.class
+	while true do
+		if current == AceOO.Class or not current then
+			break
+		end
+		if current.mixins then
+			for mixin in pairs(current.mixins) do
+				if type(mixin.OnEmbedInitialize) == "function" then
+					mixin:OnEmbedInitialize(addon, name)
+				end
+			end
+		end
+		current = current.super
+	end
+	local n = AceAddon.addonsToOnEnable and #AceAddon.addonsToOnEnable or 0
+
+	if type(addon.OnInitialize) == "function" then
+		safecall(addon.OnInitialize, addon, name)
+	end
+	if AceEvent then
+		AceEvent:TriggerEvent("Ace2_AddonInitialized", addon)
+	end
+	RegisterOnEnable(addon)
+	local n2 = AceAddon.addonsToOnEnable and #AceAddon.addonsToOnEnable or 0
+	if n2 - n > 1 then
+		local mine = table.remove(AceAddon.addonsToOnEnable)
+		table.insert(AceAddon.addonsToOnEnable, n+1, mine)
+	end
+end
+
+local aboutFrame
+local function createAboutFrame()
+	aboutFrame = CreateFrame("Frame", "AceAddon20AboutFrame", UIParent, "DialogBoxFrame")
+	aboutFrame:SetWidth(500)
+	aboutFrame:SetHeight(400)
+	aboutFrame:SetPoint("CENTER")
+	aboutFrame:SetBackdrop({
+		bgFile = [[Interface\DialogFrame\UI-DialogBox-Background]],
+	    edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]],
+	    tile = true, tileSize = 16, edgeSize = 16,
+	    insets = { left = 5, right = 5, top = 5, bottom = 5 }
+	})
+	aboutFrame:SetBackdropColor(0,0,0,1)
+
+	local donateButton = CreateFrame("Button", "AceAddon20AboutFrameDonateButton", aboutFrame, "UIPanelButtonTemplate2")
+	aboutFrame.donateButton = donateButton
+	donateButton:SetPoint("BOTTOMRIGHT", -20, 20)
+	_G.AceAddon20AboutFrameDonateButtonText:SetText(DONATE)
+	donateButton:SetWidth(_G.AceAddon20AboutFrameDonateButtonText:GetWidth()+20)
+	donateButton:SetScript("OnClick", function()
+		aboutFrame.currentAddon:OpenDonationFrame()
+	end)
+
+	local text = aboutFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge")
+	aboutFrame.title = text
+	text:SetPoint("TOP", 0, -5)
+
+	aboutFrame:Hide()
+
+	aboutFrame.lefts = {}
+	aboutFrame.rights = {}
+	aboutFrame.textLefts = {}
+	aboutFrame.textRights = {}
+	function aboutFrame:Clear()
+		self.title:SetText("")
+		for i = 1, #self.lefts do
+			self.lefts[i] = nil
+			self.rights[i] = nil
+		end
+	end
+
+	function aboutFrame:AddLine(left, right)
+		aboutFrame.lefts[#aboutFrame.lefts+1] = left
+		aboutFrame.rights[#aboutFrame.rights+1] = right
+	end
+
+	local aboutFrame_Show = aboutFrame.Show
+	function aboutFrame:Show(...)
+		local maxLeftWidth = 0
+		local maxRightWidth = 0
+		local textHeight = 0
+		for i = 1, #self.lefts do
+			if not self.textLefts[i] then
+				local left = aboutFrame:CreateFontString(nil, "OVERLAY", "GameFontNormal")
+				self.textLefts[i] = left
+				local right = aboutFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
+				self.textRights[i] = right
+				if i == 1 then
+					left:SetPoint("TOPRIGHT", aboutFrame, "TOPLEFT", 75, -35)
+				else
+					left:SetPoint("TOPRIGHT", self.textLefts[i-1], "BOTTOMRIGHT", 0, -5)
+				end
+				right:SetPoint("LEFT", left, "RIGHT", 5, 0)
+			end
+			self.textLefts[i]:SetText(self.lefts[i] .. ":")
+			self.textRights[i]:SetText(self.rights[i])
+			local leftWidth = self.textLefts[i]:GetWidth()
+			local rightWidth = self.textRights[i]:GetWidth()
+			textHeight = self.textLefts[i]:GetHeight()
+			if maxLeftWidth < leftWidth then
+				maxLeftWidth = leftWidth
+			end
+			if maxRightWidth < rightWidth then
+				maxRightWidth = rightWidth
+			end
+		end
+		for i = #self.lefts+1, #self.textLefts do
+			self.textLefts[i]:SetText('')
+			self.textRights[i]:SetText('')
+		end
+		aboutFrame:SetWidth(75 + maxRightWidth + 20)
+		aboutFrame:SetHeight(#self.lefts * (textHeight + 5) + 100)
+
+		aboutFrame_Show(self, ...)
+	end
+	aboutFrame:Hide()
+
+	createAboutFrame = nil
+end
+local donateFrame
+
+local function unobfuscateEmail(email)
+	return email:gsub(" AT ", "@"):gsub(" DOT ", ".")
+end
+
+local function isGoodVariable(var)
+	return type(var) == "string" or type(var) == "number"
+end
+function AceAddon.prototype:PrintAddonInfo()
+	if createAboutFrame then
+		createAboutFrame()
+	end
+	aboutFrame:Clear()
+	local x
+	if isGoodVariable(self.title) then
+		x = tostring(self.title)
+	elseif isGoodVariable(self.name) then
+		x = tostring(self.name)
+	else
+		x = "<" .. tostring(self.class) .. " instance>"
+	end
+	if type(self.IsActive) == "function" then
+		if not self:IsActive() then
+			x = x .. " " .. STANDBY
+		end
+	end
+	aboutFrame.title:SetText(x)
+
+	if isGoodVariable(self.version) then
+		aboutFrame:AddLine(VERSION, tostring(self.version))
+	end
+	if isGoodVariable(self.notes) then
+		aboutFrame:AddLine(NOTES, tostring(self.notes))
+	end
+	if isGoodVariable(self.author) then
+		aboutFrame:AddLine(AUTHOR, tostring(self.author))
+	end
+	if isGoodVariable(self.credits) then
+		aboutFrame:AddLine(CREDITS, tostring(self.credits))
+	end
+	if isGoodVariable(self.date) then
+		aboutFrame:AddLine(DATE, tostring(self.date))
+	end
+	if self.category then
+		local category = CATEGORIES[self.category]
+		if category then
+			aboutFrame:AddLine(CATEGORY, tostring(self.category))
+		end
+	end
+	if isGoodVariable(self.email) then
+		aboutFrame:AddLine(EMAIL, unobfuscateEmail(tostring(self.email)))
+	end
+	if isGoodVariable(self.website) then
+		aboutFrame:AddLine(WEBSITE, tostring(self.website))
+	end
+	if isGoodVariable(self.license) then
+		aboutFrame:AddLine(LICENSE, tostring(self.license))
+	end
+
+	if donateFrame and donateFrame:IsShown() then
+		donateFrame:Hide()
+	end
+
+	aboutFrame.currentAddon = self
+
+	aboutFrame:Show()
+
+	if self.donate then
+		aboutFrame.donateButton:Show()
+	else
+		aboutFrame.donateButton:Hide()
+	end
+end
+
+local function createDonateFrame()
+	donateFrame = CreateFrame("Frame", "AceAddon20Frame", UIParent, "DialogBoxFrame")
+
+	donateFrame:SetWidth(500)
+	donateFrame:SetHeight(200)
+	donateFrame:SetPoint("CENTER")
+	donateFrame:SetBackdrop({
+		bgFile = [[Interface\DialogFrame\UI-DialogBox-Background]],
+		edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]],
+		tile = true, tileSize = 16, edgeSize = 16,
+		insets = { left = 5, right = 5, top = 5, bottom = 5 }
+	})
+	donateFrame:SetBackdropColor(0,0,0,1)
+
+	local text = donateFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlightLarge")
+	text:SetPoint("TOP", 0, -5)
+	text:SetText(DONATE)
+
+	local howto = donateFrame:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
+	howto:SetPoint("TOP", text, "BOTTOM", 0, -5)
+	howto:SetPoint("LEFT", 16, 0)
+	howto:SetPoint("RIGHT", -16, 0)
+	if not IsMacClient() then
+		-- Windows or Linux
+		howto:SetText(HOWTO_DONATE_WINDOWS)
+	else
+		howto:SetText(HOWTO_DONATE_MAC)
+	end
+
+	local scrollFrame = CreateFrame("ScrollFrame", "AceAddon20FrameScrollFrame", donateFrame, "UIPanelScrollFrameTemplate")
+	scrollFrame:SetToplevel(true)
+	scrollFrame:SetPoint("TOP", -10, -76)
+	scrollFrame:SetWidth(455)
+	scrollFrame:SetHeight(70)
+	howto:SetPoint("BOTTOM", scrollFrame, "TOP")
+
+	local editBox = CreateFrame("EditBox", nil, scrollFrame)
+	donateFrame.editBox = editBox
+	scrollFrame:SetScrollChild(editBox)
+	editBox:SetFontObject(ChatFontNormal)
+	editBox:SetMultiLine(true)
+	editBox:SetMaxLetters(99999)
+	editBox:SetWidth(450)
+	editBox:SetHeight(54)
+	editBox:SetPoint("BOTTOM", 5, 0)
+	editBox:SetJustifyH("LEFT")
+	editBox:SetJustifyV("TOP")
+	editBox:SetAutoFocus(false)
+	editBox:SetScript("OnTextChanged", function(this)
+		if this:GetText() ~= this.text then
+			this:SetText(this.text)
+		end
+	end)
+	editBox:SetScript("OnEscapePressed", function(this)
+		this:ClearFocus()
+	end)
+	createDonateFrame = nil
+end
+
+local function fix(char)
+	return ("%%%02x"):format(char:byte())
+end
+
+local function urlencode(text)
+	return text:gsub("[^0-9A-Za-z]", fix)
+end
+
+function AceAddon.prototype:OpenDonationFrame()
+	if createDonateFrame then
+		createDonateFrame()
+	end
+	local donate = self.donate
+	if type(donate) ~= "string" then
+		donate = "Wowace"
+	end
+	local style, data = (":"):split(donate, 2)
+	style = style:lower()
+	if style ~= "website" and style ~= "paypal" then
+		style = "wowace"
+	end
+	if style == "wowace" then
+		donateFrame.editBox.text = "http://www.wowace.com/wiki/Donations"
+	elseif style == "website" then
+		donateFrame.editBox.text = data
+	else -- PayPal
+		local text = "https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=" .. urlencode(unobfuscateEmail(data))
+		local name
+		if type(self.title) == "string" then
+			name = self.title
+		elseif type(self.name) == "string" then
+			name = self.name
+		end
+		if name then
+			name = name:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", "")
+			text = text .. "&item_name=" .. urlencode(name)
+		end
+		donateFrame.editBox.text = text
+	end
+	donateFrame.editBox:SetText(donateFrame.editBox.text)
+
+	if aboutFrame and aboutFrame:IsShown() then
+		aboutFrame:Hide()
+	end
+
+	donateFrame:Show()
+
+	donateFrame.editBox:SetFocus()
+end
+
+local options
+function AceAddon:GetAceOptionsDataTable(target)
+	return {
+		about = {
+			name = ABOUT,
+			desc = PRINT_ADDON_INFO,
+			type = "execute",
+			func = "PrintAddonInfo",
+			order = -1,
+		},
+		donate = {
+			name = DONATE,
+			desc = DONATE_DESC,
+			type = "execute",
+			func = "OpenDonationFrame",
+			order = -1,
+			hidden = function()
+				return not target.donate
+			end
+		}
+	}
+end
+
+function AceAddon:PLAYER_LOGIN()
+	self.playerLoginFired = true
+	if self.addonsToOnEnable then
+		while #self.addonsToOnEnable > 0 do
+			local addon = table.remove(self.addonsToOnEnable, 1)
+			self.addonsStarted[addon] = true
+			if (type(addon.IsActive) ~= "function" or addon:IsActive()) and (not AceModuleCore or not AceModuleCore:IsModule(addon) or AceModuleCore:IsModuleActive(addon)) then
+				AceAddon:ManualEnable(addon)
+			end
+		end
+		self.addonsToOnEnable = nil
+	end
+end
+
+function AceAddon.prototype:Inject(t)
+	AceAddon:argCheck(t, 2, "table")
+	for k,v in pairs(t) do
+		self[k] = v
+	end
+end
+
+function AceAddon.prototype:init()
+	if not AceEvent then
+		error(MAJOR_VERSION .. " requires AceEvent-2.0", 4)
+	end
+	AceAddon.super.prototype.init(self)
+
+	self.super = self.class.prototype
+
+	AceAddon:RegisterEvent("ADDON_LOADED", "ADDON_LOADED")
+	local names = {}
+	for i = 1, GetNumAddOns() do
+		if IsAddOnLoaded(i) then names[GetAddOnInfo(i)] = true end
+	end
+	self.possibleNames = names
+	table.insert(AceAddon.nextAddon, self)
+end
+
+function AceAddon.prototype:ToString()
+	local x
+	if type(self.title) == "string" then
+		x = self.title
+	elseif type(self.name) == "string" then
+		x = self.name
+	else
+		x = "<" .. tostring(self.class) .. " instance>"
+	end
+	if (type(self.IsActive) == "function" and not self:IsActive()) or (AceModuleCore and AceModuleCore:IsModule(addon) and AceModuleCore:IsModuleActive(addon)) then
+		x = x .. " " .. STANDBY
+	end
+	return x
+end
+
+AceAddon.new = function(self, ...)
+	local class = AceAddon:pcall(AceOO.Classpool, self, ...)
+	return class:new()
+end
+
+function AceAddon:ManualEnable(addon)
+	AceAddon:argCheck(addon, 2, "table")
+	local first = nil
+	if AceOO.inherits(addon, "AceAddon-2.0") then
+		if AceAddon.addonsEnabled and not AceAddon.addonsEnabled[addon] then
+			first = true
+			AceAddon.addonsEnabled[addon] = true
+		end
+	end
+	local current = addon.class
+	while current and current ~= AceOO.Class do
+		if current.mixins then
+			for mixin in pairs(current.mixins) do
+				if type(mixin.OnEmbedEnable) == "function" then
+					safecall(mixin.OnEmbedEnable, mixin, addon, first)
+				end
+			end
+		end
+		current = current.super
+	end
+	if type(addon.OnEnable) == "function" then
+		safecall(addon.OnEnable, addon, first)
+	end
+	if AceEvent then
+		AceEvent:TriggerEvent("Ace2_AddonEnabled", addon, first)
+	end
+end
+
+function AceAddon:ManualDisable(addon)
+	AceAddon:argCheck(addon, 2, "table")
+	local current = addon.class
+	while current and current ~= AceOO.Class do
+		if current.mixins then
+			for mixin in pairs(current.mixins) do
+				if type(mixin.OnEmbedDisable) == "function" then
+					safecall(mixin.OnEmbedDisable, mixin, addon)
+				end
+			end
+		end
+		current = current.super
+	end
+	if type(module.OnDisable) == "function" then
+		safecall(module.OnDisable, addon)
+	end
+	if AceEvent then
+		AceEvent:TriggerEvent("Ace2_AddonDisabled", addon)
+	end
+end
+
+local function external(self, major, instance)
+	if major == "AceEvent-2.0" then
+		AceEvent = instance
+
+		AceEvent:embed(self)
+
+		self:RegisterEvent("PLAYER_LOGIN", "PLAYER_LOGIN", true)
+	elseif major == "AceConsole-2.0" then
+		AceConsole = instance
+
+		local slashCommands = { "/ace2" }
+		local _,_,_,enabled,loadable = GetAddOnInfo("Ace")
+		if not enabled or not loadable then
+			table.insert(slashCommands, "/ace")
+		end
+		local function listAddon(addon, depth)
+			if not depth then
+				depth = 0
+			end
+
+			local s = ("  "):rep(depth) .. " - " .. tostring(addon)
+			if rawget(addon, 'version') then
+				s = s .. " - |cffffff7f" .. tostring(addon.version) .. "|r"
+			end
+			if rawget(addon, 'slashCommand') then
+				s = s .. " |cffffff7f(" .. tostring(addon.slashCommand) .. ")|r"
+			end
+			print(s)
+			if type(rawget(addon, 'modules')) == "table" then
+				local i = 0
+				for k,v in pairs(addon.modules) do
+					i = i + 1
+					if i == 6 then
+						print(("  "):rep(depth + 1) .. " - more...")
+						break
+					else
+						listAddon(v, depth + 1)
+					end
+				end
+			end
+		end
+		local function listNormalAddon(i)
+			local name,_,_,enabled,loadable = GetAddOnInfo(i)
+			if not loadable then
+				enabled = false
+			end
+			if self.addons[name] then
+				listAddon(self.addons[name])
+			else
+				local s = " - " .. tostring(GetAddOnMetadata(i, "Title") or name)
+				local version = GetAddOnMetadata(i, "Version")
+				if version then
+					if version:find("%$Revision: (%d+) %$") then
+						version = version:gsub("%$Revision: (%d+) %$", "%1")
+					elseif version:find("%$Rev: (%d+) %$") then
+						version = version:gsub("%$Rev: (%d+) %$", "%1")
+					elseif version:find("%$LastChangedRevision: (%d+) %$") then
+						version = version:gsub("%$LastChangedRevision: (%d+) %$", "%1")
+					end
+					s = s .. " - |cffffff7f" .. version .. "|r"
+				end
+				if not enabled then
+					s = s .. " |cffff0000(disabled)|r"
+				end
+				if IsAddOnLoadOnDemand(i) then
+					s = s .. " |cff00ff00[LoD]|r"
+				end
+				print(s)
+			end
+		end
+		local function mySort(alpha, bravo)
+			return tostring(alpha) < tostring(bravo)
+		end
+		AceConsole.RegisterChatCommand(self, slashCommands, {
+			desc = "AddOn development framework",
+			name = "Ace2",
+			type = "group",
+			args = {
+				about = {
+					desc = "Get information about Ace2",
+					name = "About",
+					type = "execute",
+					func = function()
+						print("|cffffff7fAce2|r - |cffffff7f2.0." .. MINOR_VERSION:gsub("%$Revision: (%d+) %$", "%1") .. "|r - AddOn development framework")
+						print(" - |cffffff7f" .. AUTHOR .. ":|r Ace Development Team")
+						print(" - |cffffff7f" .. WEBSITE .. ":|r http://www.wowace.com/")
+					end
+				},
+				list = {
+					desc = "List addons",
+					name = "List",
+					type = "group",
+					args = {
+						ace2 = {
+							desc = "List addons using Ace2",
+							name = "Ace2",
+							type = "execute",
+							func = function()
+								print("|cffffff7fAddon list:|r")
+								table.sort(self.addons, mySort)
+								for _,v in ipairs(self.addons) do
+									listAddon(v)
+								end
+							end
+						},
+						all = {
+							desc = "List all addons",
+							name = "All",
+							type = "execute",
+							func = function()
+								print("|cffffff7fAddon list:|r")
+								local count = GetNumAddOns()
+								for i = 1, count do
+									listNormalAddon(i)
+								end
+							end
+						},
+						enabled = {
+							desc = "List all enabled addons",
+							name = "Enabled",
+							type = "execute",
+							func = function()
+								print("|cffffff7fAddon list:|r")
+								local count = GetNumAddOns()
+								for i = 1, count do
+									local _,_,_,enabled,loadable = GetAddOnInfo(i)
+									if enabled and loadable then
+										listNormalAddon(i)
+									end
+								end
+							end
+						},
+						disabled = {
+							desc = "List all disabled addons",
+							name = "Disabled",
+							type = "execute",
+							func = function()
+								print("|cffffff7fAddon list:|r")
+								local count = GetNumAddOns()
+								for i = 1, count do
+									local _,_,_,enabled,loadable = GetAddOnInfo(i)
+									if not enabled or not loadable then
+										listNormalAddon(i)
+									end
+								end
+							end
+						},
+						lod = {
+							desc = "List all LoadOnDemand addons",
+							name = "LoadOnDemand",
+							type = "execute",
+							func = function()
+								print("|cffffff7fAddon list:|r")
+								local count = GetNumAddOns()
+								for i = 1, count do
+									if IsAddOnLoadOnDemand(i) then
+										listNormalAddon(i)
+									end
+								end
+							end
+						},
+						ace1 = {
+							desc = "List all addons using Ace1",
+							name = "Ace 1.x",
+							type = "execute",
+							func = function()
+								print("|cffffff7fAddon list:|r")
+								local count = GetNumAddOns()
+								for i = 1, count do
+									local dep1, dep2, dep3, dep4 = GetAddOnDependencies(i)
+									if dep1 == "Ace" or dep2 == "Ace" or dep3 == "Ace" or dep4 == "Ace" then
+										listNormalAddon(i)
+									end
+								end
+							end
+						},
+						libs = {
+							desc = "List all libraries using AceLibrary",
+							name = "Libraries",
+							type = "execute",
+							func = function()
+								if type(AceLibrary) == "table" and type(AceLibrary.libs) == "table" then
+									print("|cffffff7fLibrary list:|r")
+									for name, data in pairs(AceLibrary.libs) do
+										local s
+										if data.minor then
+											s = " - " .. tostring(name) .. "." .. tostring(data.minor)
+										else
+											s = " - " .. tostring(name)
+										end
+										if rawget(AceLibrary(name), 'slashCommand') then
+											s = s .. " |cffffff7f(" .. tostring(AceLibrary(name).slashCommand) .. "|cffffff7f)"
+										end
+										print(s)
+									end
+								end
+							end
+						},
+						search = {
+							desc = "Search by name",
+							name = "Search",
+							type = "text",
+							usage = "<keyword>",
+							input = true,
+							get = false,
+							set = function(...)
+								local arg = { ... }
+								for i,v in ipairs(arg) do
+									arg[i] = v:gsub('%*', '.*'):gsub('%%', '%%%%'):lower()
+								end
+								local count = GetNumAddOns()
+								for i = 1, count do
+									local name = GetAddOnInfo(i)
+									local good = true
+									for _,v in ipairs(arg) do
+										if not name:lower():find(v) then
+											good = false
+											break
+										end
+									end
+									if good then
+										listNormalAddon(i)
+									end
+								end
+							end
+						}
+					},
+				},
+				enable = {
+					desc = "Enable addon(s).",
+					name = "Enable",
+					type = "text",
+					usage = "<addon 1> <addon 2> ...",
+					get = false,
+					input = true,
+					set = function(...)
+						for i = 1, select("#", ...) do
+							local addon = select(i, ...)
+							local name, title, _, enabled, _, reason = GetAddOnInfo(addon)
+							if reason == "MISSING" then
+								print(("|cffffff7fAce2:|r AddOn %q does not exist."):format(addon))
+							elseif not enabled then
+								EnableAddOn(addon)
+								print(("|cffffff7fAce2:|r %s is now enabled."):format(addon or name))
+							else
+								print(("|cffffff7fAce2:|r %s is already enabled."):format(addon or name))
+							end
+						end
+					end,
+				},
+				disable = {
+					desc = "Disable addon(s).",
+					name = "Disable",
+					type = "text",
+					usage = "<addon 1> <addon 2> ...",
+					get = false,
+					input = true,
+					set = function(...)
+						for i = 1, select("#", ...) do
+							local addon = select(i, ...)
+							local name, title, _, enabled, _, reason = GetAddOnInfo(addon)
+							if reason == "MISSING" then
+							print(("|cffffff7fAce2:|r AddOn %q does not exist."):format(addon))
+							elseif enabled then
+								DisableAddOn(addon)
+								print(("|cffffff7fAce2:|r %s is now disabled."):format(addon or name))
+							else
+								print(("|cffffff7fAce2:|r %s is already disabled."):format(addon or name))
+							end
+						end
+					end,
+				},
+				load = {
+					desc = "Load addon(s).",
+					name = "Load",
+					type = "text",
+					usage = "<addon 1> <addon 2> ...",
+					get = false,
+					input = true,
+					set = function(...)
+						for i = 1, select("#", ...) do
+							local addon = select(i, ...)
+							local name, title, _, _, loadable, reason = GetAddOnInfo(addon)
+							if reason == "MISSING" then
+								print(("|cffffff7fAce2:|r AddOn %q does not exist."):format(addon))
+							elseif not loadable then
+								print(("|cffffff7fAce2:|r AddOn %q is not loadable. Reason: %s."):format(addon, reason))
+							else
+								LoadAddOn(addon)
+								print(("|cffffff7fAce2:|r %s is now loaded."):format(addon or name))
+							end
+						end
+					end
+				},
+				info = {
+					desc = "Display information",
+					name = "Information",
+					type = "execute",
+					func = function()
+						local mem, threshold = gcinfo()
+						print((" - |cffffff7fMemory usage [|r%.3f MiB|cffffff7f]|r"):format(mem / 1024))
+						if threshold then
+							print((" - |cffffff7fThreshold [|r%.3f MiB|cffffff7f]|r"):format(threshold / 1024))
+						end
+						print((" - |cffffff7fFramerate [|r%.0f fps|cffffff7f]|r"):format(GetFramerate()))
+						local bandwidthIn, bandwidthOut, latency = GetNetStats()
+						bandwidthIn, bandwidthOut = floor(bandwidthIn * 1024), floor(bandwidthOut * 1024)
+						print((" - |cffffff7fLatency [|r%.0f ms|cffffff7f]|r"):format(latency))
+						print((" - |cffffff7fBandwidth in [|r%.0f B/s|cffffff7f]|r"):format(bandwidthIn))
+						print((" - |cffffff7fBandwidth out [|r%.0f B/s|cffffff7f]|r"):format(bandwidthOut))
+						print((" - |cffffff7fTotal addons [|r%d|cffffff7f]|r"):format(GetNumAddOns()))
+						print((" - |cffffff7fAce2 addons [|r%d|cffffff7f]|r"):format(#self.addons))
+						local ace = 0
+						local enabled = 0
+						local disabled = 0
+						local lod = 0
+						for i = 1, GetNumAddOns() do
+							local dep1, dep2, dep3, dep4 = GetAddOnDependencies(i)
+							if dep1 == "Ace" or dep2 == "Ace" or dep3 == "Ace" or dep4 == "Ace" then
+								ace = ace + 1
+							end
+							if IsAddOnLoadOnDemand(i) then
+								lod = lod + 1
+							end
+							local isActive, loadable = select(4, GetAddOnInfo(i))
+							if not isActive or not loadable then
+								disabled = disabled + 1
+							else
+								enabled = enabled + 1
+							end
+						end
+						print((" - |cffffff7fAce 1.x addons [|r%d|cffffff7f]|r"):format(ace))
+						print((" - |cffffff7fLoadOnDemand addons [|r%d|cffffff7f]|r"):format(lod))
+						print((" - |cffffff7fenabled addons [|r%d|cffffff7f]|r"):format(enabled))
+						print((" - |cffffff7fdisabled addons [|r%d|cffffff7f]|r"):format(disabled))
+						local libs = 0
+						if type(AceLibrary) == "table" and type(AceLibrary.libs) == "table" then
+							for _ in pairs(AceLibrary.libs) do
+								libs = libs + 1
+							end
+						end
+						print((" - |cffffff7fAceLibrary instances [|r%d|cffffff7f]|r"):format(libs))
+					end
+				}
+			}
+		})
+	elseif major == "AceModuleCore-2.0" then
+		AceModuleCore = instance
+	end
+end
+
+local function activate(self, oldLib, oldDeactivate)
+	AceAddon = self
+
+	self.playerLoginFired = oldLib and oldLib.playerLoginFired or DEFAULT_CHAT_FRAME and DEFAULT_CHAT_FRAME.defaultLanguage
+	self.addonsToOnEnable = oldLib and oldLib.addonsToOnEnable
+	self.addons = oldLib and oldLib.addons or {}
+	self.nextAddon = oldLib and oldLib.nextAddon or {}
+	self.skipAddon = oldLib and oldLib.skipAddon or {}
+	self.addonsStarted = oldLib and oldLib.addonsStarted or {}
+	self.addonsEnabled = oldLib and oldLib.addonsEnabled or {}
+
+	if oldDeactivate then
+		oldDeactivate(oldLib)
+	end
+end
+
+AceLibrary:Register(AceAddon, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)