annotate Libs/AceAddon-3.0/AceAddon-3.0.lua @ 3:c6f0976069c7

Default value for the welcome / bye notification is now set to false The mailframe checkbox now primarily toggles the mail opening, however if you hold shift you can still disable the entire addon Now properly removes QuickAuction?s mail count Now tracks when a mail lost all attachments rather than it being deleted in order to continue processing the next item (mail sent by players containing text should now work properly). This should also be good for a nice speed increase. Added a variable called ?busy? to the MailOpener object indicating whether or not Mail Opener is currently working. Other addons (or macros) can retrieve it with ?LibStub("AceAddon-3.0"):GetAddon("MailOpener").busy? A mail refresh from the Postal service should no longer occur while mail is being opened but will happen instantly afterwards. Postal?s module toggling will now be handled by Postal itself. Added a short summary to the top of all modules for other developers. The time remaining until next mail box refresh should be displayed for as long as Mail Opener can be sure.
author Zerotorescue
date Tue, 07 Sep 2010 17:46:27 +0200
parents 823e33465b6e
children
rev   line source
Zerotorescue@0 1 --- **AceAddon-3.0** provides a template for creating addon objects.
Zerotorescue@0 2 -- It'll provide you with a set of callback functions that allow you to simplify the loading
Zerotorescue@0 3 -- process of your addon.\\
Zerotorescue@0 4 -- Callbacks provided are:\\
Zerotorescue@0 5 -- * **OnInitialize**, which is called directly after the addon is fully loaded.
Zerotorescue@0 6 -- * **OnEnable** which gets called during the PLAYER_LOGIN event, when most of the data provided by the game is already present.
Zerotorescue@0 7 -- * **OnDisable**, which is only called when your addon is manually being disabled.
Zerotorescue@0 8 -- @usage
Zerotorescue@0 9 -- -- A small (but complete) addon, that doesn't do anything,
Zerotorescue@0 10 -- -- but shows usage of the callbacks.
Zerotorescue@0 11 -- local MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
Zerotorescue@0 12 --
Zerotorescue@0 13 -- function MyAddon:OnInitialize()
Zerotorescue@0 14 -- -- do init tasks here, like loading the Saved Variables,
Zerotorescue@0 15 -- -- or setting up slash commands.
Zerotorescue@0 16 -- end
Zerotorescue@0 17 --
Zerotorescue@0 18 -- function MyAddon:OnEnable()
Zerotorescue@0 19 -- -- Do more initialization here, that really enables the use of your addon.
Zerotorescue@0 20 -- -- Register Events, Hook functions, Create Frames, Get information from
Zerotorescue@0 21 -- -- the game that wasn't available in OnInitialize
Zerotorescue@0 22 -- end
Zerotorescue@0 23 --
Zerotorescue@0 24 -- function MyAddon:OnDisable()
Zerotorescue@0 25 -- -- Unhook, Unregister Events, Hide frames that you created.
Zerotorescue@0 26 -- -- You would probably only use an OnDisable if you want to
Zerotorescue@0 27 -- -- build a "standby" mode, or be able to toggle modules on/off.
Zerotorescue@0 28 -- end
Zerotorescue@0 29 -- @class file
Zerotorescue@0 30 -- @name AceAddon-3.0.lua
Zerotorescue@0 31 -- @release $Id: AceAddon-3.0.lua 895 2009-12-06 16:28:55Z nevcairiel $
Zerotorescue@0 32
Zerotorescue@0 33 local MAJOR, MINOR = "AceAddon-3.0", 5
Zerotorescue@0 34 local AceAddon, oldminor = LibStub:NewLibrary(MAJOR, MINOR)
Zerotorescue@0 35
Zerotorescue@0 36 if not AceAddon then return end -- No Upgrade needed.
Zerotorescue@0 37
Zerotorescue@0 38 AceAddon.frame = AceAddon.frame or CreateFrame("Frame", "AceAddon30Frame") -- Our very own frame
Zerotorescue@0 39 AceAddon.addons = AceAddon.addons or {} -- addons in general
Zerotorescue@0 40 AceAddon.statuses = AceAddon.statuses or {} -- statuses of addon.
Zerotorescue@0 41 AceAddon.initializequeue = AceAddon.initializequeue or {} -- addons that are new and not initialized
Zerotorescue@0 42 AceAddon.enablequeue = AceAddon.enablequeue or {} -- addons that are initialized and waiting to be enabled
Zerotorescue@0 43 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
Zerotorescue@0 44
Zerotorescue@0 45 -- Lua APIs
Zerotorescue@0 46 local tinsert, tconcat, tremove = table.insert, table.concat, table.remove
Zerotorescue@0 47 local fmt, tostring = string.format, tostring
Zerotorescue@0 48 local select, pairs, next, type, unpack = select, pairs, next, type, unpack
Zerotorescue@0 49 local loadstring, assert, error = loadstring, assert, error
Zerotorescue@0 50 local setmetatable, getmetatable, rawset, rawget = setmetatable, getmetatable, rawset, rawget
Zerotorescue@0 51
Zerotorescue@0 52 -- Global vars/functions that we don't upvalue since they might get hooked, or upgraded
Zerotorescue@0 53 -- List them here for Mikk's FindGlobals script
Zerotorescue@0 54 -- GLOBALS: LibStub, IsLoggedIn, geterrorhandler
Zerotorescue@0 55
Zerotorescue@0 56 --[[
Zerotorescue@0 57 xpcall safecall implementation
Zerotorescue@0 58 ]]
Zerotorescue@0 59 local xpcall = xpcall
Zerotorescue@0 60
Zerotorescue@0 61 local function errorhandler(err)
Zerotorescue@0 62 return geterrorhandler()(err)
Zerotorescue@0 63 end
Zerotorescue@0 64
Zerotorescue@0 65 local function CreateDispatcher(argCount)
Zerotorescue@0 66 local code = [[
Zerotorescue@0 67 local xpcall, eh = ...
Zerotorescue@0 68 local method, ARGS
Zerotorescue@0 69 local function call() return method(ARGS) end
Zerotorescue@0 70
Zerotorescue@0 71 local function dispatch(func, ...)
Zerotorescue@0 72 method = func
Zerotorescue@0 73 if not method then return end
Zerotorescue@0 74 ARGS = ...
Zerotorescue@0 75 return xpcall(call, eh)
Zerotorescue@0 76 end
Zerotorescue@0 77
Zerotorescue@0 78 return dispatch
Zerotorescue@0 79 ]]
Zerotorescue@0 80
Zerotorescue@0 81 local ARGS = {}
Zerotorescue@0 82 for i = 1, argCount do ARGS[i] = "arg"..i end
Zerotorescue@0 83 code = code:gsub("ARGS", tconcat(ARGS, ", "))
Zerotorescue@0 84 return assert(loadstring(code, "safecall Dispatcher["..argCount.."]"))(xpcall, errorhandler)
Zerotorescue@0 85 end
Zerotorescue@0 86
Zerotorescue@0 87 local Dispatchers = setmetatable({}, {__index=function(self, argCount)
Zerotorescue@0 88 local dispatcher = CreateDispatcher(argCount)
Zerotorescue@0 89 rawset(self, argCount, dispatcher)
Zerotorescue@0 90 return dispatcher
Zerotorescue@0 91 end})
Zerotorescue@0 92 Dispatchers[0] = function(func)
Zerotorescue@0 93 return xpcall(func, errorhandler)
Zerotorescue@0 94 end
Zerotorescue@0 95
Zerotorescue@0 96 local function safecall(func, ...)
Zerotorescue@0 97 -- we check to see if the func is passed is actually a function here and don't error when it isn't
Zerotorescue@0 98 -- this safecall is used for optional functions like OnInitialize OnEnable etc. When they are not
Zerotorescue@0 99 -- present execution should continue without hinderance
Zerotorescue@0 100 if type(func) == "function" then
Zerotorescue@0 101 return Dispatchers[select('#', ...)](func, ...)
Zerotorescue@0 102 end
Zerotorescue@0 103 end
Zerotorescue@0 104
Zerotorescue@0 105 -- local functions that will be implemented further down
Zerotorescue@0 106 local Enable, Disable, EnableModule, DisableModule, Embed, NewModule, GetModule, GetName, SetDefaultModuleState, SetDefaultModuleLibraries, SetEnabledState, SetDefaultModulePrototype
Zerotorescue@0 107
Zerotorescue@0 108 -- used in the addon metatable
Zerotorescue@0 109 local function addontostring( self ) return self.name end
Zerotorescue@0 110
Zerotorescue@0 111 --- Create a new AceAddon-3.0 addon.
Zerotorescue@0 112 -- Any libraries you specified will be embeded, and the addon will be scheduled for
Zerotorescue@0 113 -- its OnInitialize and OnEnable callbacks.
Zerotorescue@0 114 -- The final addon object, with all libraries embeded, will be returned.
Zerotorescue@0 115 -- @paramsig [object ,]name[, lib, ...]
Zerotorescue@0 116 -- @param object Table to use as a base for the addon (optional)
Zerotorescue@0 117 -- @param name Name of the addon object to create
Zerotorescue@0 118 -- @param lib List of libraries to embed into the addon
Zerotorescue@0 119 -- @usage
Zerotorescue@0 120 -- -- Create a simple addon object
Zerotorescue@0 121 -- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon", "AceEvent-3.0")
Zerotorescue@0 122 --
Zerotorescue@0 123 -- -- Create a Addon object based on the table of a frame
Zerotorescue@0 124 -- local MyFrame = CreateFrame("Frame")
Zerotorescue@0 125 -- MyAddon = LibStub("AceAddon-3.0"):NewAddon(MyFrame, "MyAddon", "AceEvent-3.0")
Zerotorescue@0 126 function AceAddon:NewAddon(objectorname, ...)
Zerotorescue@0 127 local object,name
Zerotorescue@0 128 local i=1
Zerotorescue@0 129 if type(objectorname)=="table" then
Zerotorescue@0 130 object=objectorname
Zerotorescue@0 131 name=...
Zerotorescue@0 132 i=2
Zerotorescue@0 133 else
Zerotorescue@0 134 name=objectorname
Zerotorescue@0 135 end
Zerotorescue@0 136 if type(name)~="string" then
Zerotorescue@0 137 error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2)
Zerotorescue@0 138 end
Zerotorescue@0 139 if self.addons[name] then
Zerotorescue@0 140 error(("Usage: NewAddon([object,] name, [lib, lib, lib, ...]): 'name' - Addon '%s' already exists."):format(name), 2)
Zerotorescue@0 141 end
Zerotorescue@0 142
Zerotorescue@0 143 object = object or {}
Zerotorescue@0 144 object.name = name
Zerotorescue@0 145
Zerotorescue@0 146 local addonmeta = {}
Zerotorescue@0 147 local oldmeta = getmetatable(object)
Zerotorescue@0 148 if oldmeta then
Zerotorescue@0 149 for k, v in pairs(oldmeta) do addonmeta[k] = v end
Zerotorescue@0 150 end
Zerotorescue@0 151 addonmeta.__tostring = addontostring
Zerotorescue@0 152
Zerotorescue@0 153 setmetatable( object, addonmeta )
Zerotorescue@0 154 self.addons[name] = object
Zerotorescue@0 155 object.modules = {}
Zerotorescue@0 156 object.defaultModuleLibraries = {}
Zerotorescue@0 157 Embed( object ) -- embed NewModule, GetModule methods
Zerotorescue@0 158 self:EmbedLibraries(object, select(i,...))
Zerotorescue@0 159
Zerotorescue@0 160 -- add to queue of addons to be initialized upon ADDON_LOADED
Zerotorescue@0 161 tinsert(self.initializequeue, object)
Zerotorescue@0 162 return object
Zerotorescue@0 163 end
Zerotorescue@0 164
Zerotorescue@0 165
Zerotorescue@0 166 --- Get the addon object by its name from the internal AceAddon registry.
Zerotorescue@0 167 -- Throws an error if the addon object cannot be found (except if silent is set).
Zerotorescue@0 168 -- @param name unique name of the addon object
Zerotorescue@0 169 -- @param silent if true, the addon is optional, silently return nil if its not found
Zerotorescue@0 170 -- @usage
Zerotorescue@0 171 -- -- Get the Addon
Zerotorescue@0 172 -- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
Zerotorescue@0 173 function AceAddon:GetAddon(name, silent)
Zerotorescue@0 174 if not silent and not self.addons[name] then
Zerotorescue@0 175 error(("Usage: GetAddon(name): 'name' - Cannot find an AceAddon '%s'."):format(tostring(name)), 2)
Zerotorescue@0 176 end
Zerotorescue@0 177 return self.addons[name]
Zerotorescue@0 178 end
Zerotorescue@0 179
Zerotorescue@0 180 -- - Embed a list of libraries into the specified addon.
Zerotorescue@0 181 -- This function will try to embed all of the listed libraries into the addon
Zerotorescue@0 182 -- and error if a single one fails.
Zerotorescue@0 183 --
Zerotorescue@0 184 -- **Note:** This function is for internal use by :NewAddon/:NewModule
Zerotorescue@0 185 -- @paramsig addon, [lib, ...]
Zerotorescue@0 186 -- @param addon addon object to embed the libs in
Zerotorescue@0 187 -- @param lib List of libraries to embed into the addon
Zerotorescue@0 188 function AceAddon:EmbedLibraries(addon, ...)
Zerotorescue@0 189 for i=1,select("#", ... ) do
Zerotorescue@0 190 local libname = select(i, ...)
Zerotorescue@0 191 self:EmbedLibrary(addon, libname, false, 4)
Zerotorescue@0 192 end
Zerotorescue@0 193 end
Zerotorescue@0 194
Zerotorescue@0 195 -- - Embed a library into the addon object.
Zerotorescue@0 196 -- This function will check if the specified library is registered with LibStub
Zerotorescue@0 197 -- and if it has a :Embed function to call. It'll error if any of those conditions
Zerotorescue@0 198 -- fails.
Zerotorescue@0 199 --
Zerotorescue@0 200 -- **Note:** This function is for internal use by :EmbedLibraries
Zerotorescue@0 201 -- @paramsig addon, libname[, silent[, offset]]
Zerotorescue@0 202 -- @param addon addon object to embed the library in
Zerotorescue@0 203 -- @param libname name of the library to embed
Zerotorescue@0 204 -- @param silent marks an embed to fail silently if the library doesn't exist (optional)
Zerotorescue@0 205 -- @param offset will push the error messages back to said offset, defaults to 2 (optional)
Zerotorescue@0 206 function AceAddon:EmbedLibrary(addon, libname, silent, offset)
Zerotorescue@0 207 local lib = LibStub:GetLibrary(libname, true)
Zerotorescue@0 208 if not lib and not silent then
Zerotorescue@0 209 error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Cannot find a library instance of %q."):format(tostring(libname)), offset or 2)
Zerotorescue@0 210 elseif lib and type(lib.Embed) == "function" then
Zerotorescue@0 211 lib:Embed(addon)
Zerotorescue@0 212 tinsert(self.embeds[addon], libname)
Zerotorescue@0 213 return true
Zerotorescue@0 214 elseif lib then
Zerotorescue@0 215 error(("Usage: EmbedLibrary(addon, libname, silent, offset): 'libname' - Library '%s' is not Embed capable"):format(libname), offset or 2)
Zerotorescue@0 216 end
Zerotorescue@0 217 end
Zerotorescue@0 218
Zerotorescue@0 219 --- Return the specified module from an addon object.
Zerotorescue@0 220 -- Throws an error if the addon object cannot be found (except if silent is set)
Zerotorescue@0 221 -- @name //addon//:GetModule
Zerotorescue@0 222 -- @paramsig name[, silent]
Zerotorescue@0 223 -- @param name unique name of the module
Zerotorescue@0 224 -- @param silent if true, the module is optional, silently return nil if its not found (optional)
Zerotorescue@0 225 -- @usage
Zerotorescue@0 226 -- -- Get the Addon
Zerotorescue@0 227 -- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
Zerotorescue@0 228 -- -- Get the Module
Zerotorescue@0 229 -- MyModule = MyAddon:GetModule("MyModule")
Zerotorescue@0 230 function GetModule(self, name, silent)
Zerotorescue@0 231 if not self.modules[name] and not silent then
Zerotorescue@0 232 error(("Usage: GetModule(name, silent): 'name' - Cannot find module '%s'."):format(tostring(name)), 2)
Zerotorescue@0 233 end
Zerotorescue@0 234 return self.modules[name]
Zerotorescue@0 235 end
Zerotorescue@0 236
Zerotorescue@0 237 local function IsModuleTrue(self) return true end
Zerotorescue@0 238
Zerotorescue@0 239 --- Create a new module for the addon.
Zerotorescue@0 240 -- The new module can have its own embeded libraries and/or use a module prototype to be mixed into the module.\\
Zerotorescue@0 241 -- A module has the same functionality as a real addon, it can have modules of its own, and has the same API as
Zerotorescue@0 242 -- an addon object.
Zerotorescue@0 243 -- @name //addon//:NewModule
Zerotorescue@0 244 -- @paramsig name[, prototype|lib[, lib, ...]]
Zerotorescue@0 245 -- @param name unique name of the module
Zerotorescue@0 246 -- @param prototype object to derive this module from, methods and values from this table will be mixed into the module (optional)
Zerotorescue@0 247 -- @param lib List of libraries to embed into the addon
Zerotorescue@0 248 -- @usage
Zerotorescue@0 249 -- -- Create a module with some embeded libraries
Zerotorescue@0 250 -- MyModule = MyAddon:NewModule("MyModule", "AceEvent-3.0", "AceHook-3.0")
Zerotorescue@0 251 --
Zerotorescue@0 252 -- -- Create a module with a prototype
Zerotorescue@0 253 -- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
Zerotorescue@0 254 -- MyModule = MyAddon:NewModule("MyModule", prototype, "AceEvent-3.0", "AceHook-3.0")
Zerotorescue@0 255 function NewModule(self, name, prototype, ...)
Zerotorescue@0 256 if type(name) ~= "string" then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - string expected got '%s'."):format(type(name)), 2) end
Zerotorescue@0 257 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
Zerotorescue@0 258
Zerotorescue@0 259 if self.modules[name] then error(("Usage: NewModule(name, [prototype, [lib, lib, lib, ...]): 'name' - Module '%s' already exists."):format(name), 2) end
Zerotorescue@0 260
Zerotorescue@0 261 -- modules are basically addons. We treat them as such. They will be added to the initializequeue properly as well.
Zerotorescue@0 262 -- NewModule can only be called after the parent addon is present thus the modules will be initialized after their parent is.
Zerotorescue@0 263 local module = AceAddon:NewAddon(fmt("%s_%s", self.name or tostring(self), name))
Zerotorescue@0 264
Zerotorescue@0 265 module.IsModule = IsModuleTrue
Zerotorescue@0 266 module:SetEnabledState(self.defaultModuleState)
Zerotorescue@0 267 module.moduleName = name
Zerotorescue@0 268
Zerotorescue@0 269 if type(prototype) == "string" then
Zerotorescue@0 270 AceAddon:EmbedLibraries(module, prototype, ...)
Zerotorescue@0 271 else
Zerotorescue@0 272 AceAddon:EmbedLibraries(module, ...)
Zerotorescue@0 273 end
Zerotorescue@0 274 AceAddon:EmbedLibraries(module, unpack(self.defaultModuleLibraries))
Zerotorescue@0 275
Zerotorescue@0 276 if not prototype or type(prototype) == "string" then
Zerotorescue@0 277 prototype = self.defaultModulePrototype or nil
Zerotorescue@0 278 end
Zerotorescue@0 279
Zerotorescue@0 280 if type(prototype) == "table" then
Zerotorescue@0 281 local mt = getmetatable(module)
Zerotorescue@0 282 mt.__index = prototype
Zerotorescue@0 283 setmetatable(module, mt) -- More of a Base class type feel.
Zerotorescue@0 284 end
Zerotorescue@0 285
Zerotorescue@0 286 safecall(self.OnModuleCreated, self, module) -- Was in Ace2 and I think it could be a cool thing to have handy.
Zerotorescue@0 287 self.modules[name] = module
Zerotorescue@0 288
Zerotorescue@0 289 return module
Zerotorescue@0 290 end
Zerotorescue@0 291
Zerotorescue@0 292 --- Returns the real name of the addon or module, without any prefix.
Zerotorescue@0 293 -- @name //addon//:GetName
Zerotorescue@0 294 -- @paramsig
Zerotorescue@0 295 -- @usage
Zerotorescue@0 296 -- print(MyAddon:GetName())
Zerotorescue@0 297 -- -- prints "MyAddon"
Zerotorescue@0 298 function GetName(self)
Zerotorescue@0 299 return self.moduleName or self.name
Zerotorescue@0 300 end
Zerotorescue@0 301
Zerotorescue@0 302 --- Enables the Addon, if possible, return true or false depending on success.
Zerotorescue@0 303 -- This internally calls AceAddon:EnableAddon(), thus dispatching a OnEnable callback
Zerotorescue@0 304 -- and enabling all modules of the addon (unless explicitly disabled).\\
Zerotorescue@0 305 -- :Enable() also sets the internal `enableState` variable to true
Zerotorescue@0 306 -- @name //addon//:Enable
Zerotorescue@0 307 -- @paramsig
Zerotorescue@0 308 -- @usage
Zerotorescue@0 309 -- -- Enable MyModule
Zerotorescue@0 310 -- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
Zerotorescue@0 311 -- MyModule = MyAddon:GetModule("MyModule")
Zerotorescue@0 312 -- MyModule:Enable()
Zerotorescue@0 313 function Enable(self)
Zerotorescue@0 314 self:SetEnabledState(true)
Zerotorescue@0 315 return AceAddon:EnableAddon(self)
Zerotorescue@0 316 end
Zerotorescue@0 317
Zerotorescue@0 318 --- Disables the Addon, if possible, return true or false depending on success.
Zerotorescue@0 319 -- This internally calls AceAddon:DisableAddon(), thus dispatching a OnDisable callback
Zerotorescue@0 320 -- and disabling all modules of the addon.\\
Zerotorescue@0 321 -- :Disable() also sets the internal `enableState` variable to false
Zerotorescue@0 322 -- @name //addon//:Disable
Zerotorescue@0 323 -- @paramsig
Zerotorescue@0 324 -- @usage
Zerotorescue@0 325 -- -- Disable MyAddon
Zerotorescue@0 326 -- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
Zerotorescue@0 327 -- MyAddon:Disable()
Zerotorescue@0 328 function Disable(self)
Zerotorescue@0 329 self:SetEnabledState(false)
Zerotorescue@0 330 return AceAddon:DisableAddon(self)
Zerotorescue@0 331 end
Zerotorescue@0 332
Zerotorescue@0 333 --- Enables the Module, if possible, return true or false depending on success.
Zerotorescue@0 334 -- Short-hand function that retrieves the module via `:GetModule` and calls `:Enable` on the module object.
Zerotorescue@0 335 -- @name //addon//:EnableModule
Zerotorescue@0 336 -- @paramsig name
Zerotorescue@0 337 -- @usage
Zerotorescue@0 338 -- -- Enable MyModule using :GetModule
Zerotorescue@0 339 -- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
Zerotorescue@0 340 -- MyModule = MyAddon:GetModule("MyModule")
Zerotorescue@0 341 -- MyModule:Enable()
Zerotorescue@0 342 --
Zerotorescue@0 343 -- -- Enable MyModule using the short-hand
Zerotorescue@0 344 -- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
Zerotorescue@0 345 -- MyAddon:EnableModule("MyModule")
Zerotorescue@0 346 function EnableModule(self, name)
Zerotorescue@0 347 local module = self:GetModule( name )
Zerotorescue@0 348 return module:Enable()
Zerotorescue@0 349 end
Zerotorescue@0 350
Zerotorescue@0 351 --- Disables the Module, if possible, return true or false depending on success.
Zerotorescue@0 352 -- Short-hand function that retrieves the module via `:GetModule` and calls `:Disable` on the module object.
Zerotorescue@0 353 -- @name //addon//:DisableModule
Zerotorescue@0 354 -- @paramsig name
Zerotorescue@0 355 -- @usage
Zerotorescue@0 356 -- -- Disable MyModule using :GetModule
Zerotorescue@0 357 -- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
Zerotorescue@0 358 -- MyModule = MyAddon:GetModule("MyModule")
Zerotorescue@0 359 -- MyModule:Disable()
Zerotorescue@0 360 --
Zerotorescue@0 361 -- -- Disable MyModule using the short-hand
Zerotorescue@0 362 -- MyAddon = LibStub("AceAddon-3.0"):GetAddon("MyAddon")
Zerotorescue@0 363 -- MyAddon:DisableModule("MyModule")
Zerotorescue@0 364 function DisableModule(self, name)
Zerotorescue@0 365 local module = self:GetModule( name )
Zerotorescue@0 366 return module:Disable()
Zerotorescue@0 367 end
Zerotorescue@0 368
Zerotorescue@0 369 --- Set the default libraries to be mixed into all modules created by this object.
Zerotorescue@0 370 -- Note that you can only change the default module libraries before any module is created.
Zerotorescue@0 371 -- @name //addon//:SetDefaultModuleLibraries
Zerotorescue@0 372 -- @paramsig lib[, lib, ...]
Zerotorescue@0 373 -- @param lib List of libraries to embed into the addon
Zerotorescue@0 374 -- @usage
Zerotorescue@0 375 -- -- Create the addon object
Zerotorescue@0 376 -- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
Zerotorescue@0 377 -- -- Configure default libraries for modules (all modules need AceEvent-3.0)
Zerotorescue@0 378 -- MyAddon:SetDefaultModuleLibraries("AceEvent-3.0")
Zerotorescue@0 379 -- -- Create a module
Zerotorescue@0 380 -- MyModule = MyAddon:NewModule("MyModule")
Zerotorescue@0 381 function SetDefaultModuleLibraries(self, ...)
Zerotorescue@0 382 if next(self.modules) then
Zerotorescue@0 383 error("Usage: SetDefaultModuleLibraries(...): cannot change the module defaults after a module has been registered.", 2)
Zerotorescue@0 384 end
Zerotorescue@0 385 self.defaultModuleLibraries = {...}
Zerotorescue@0 386 end
Zerotorescue@0 387
Zerotorescue@0 388 --- Set the default state in which new modules are being created.
Zerotorescue@0 389 -- Note that you can only change the default state before any module is created.
Zerotorescue@0 390 -- @name //addon//:SetDefaultModuleState
Zerotorescue@0 391 -- @paramsig state
Zerotorescue@0 392 -- @param state Default state for new modules, true for enabled, false for disabled
Zerotorescue@0 393 -- @usage
Zerotorescue@0 394 -- -- Create the addon object
Zerotorescue@0 395 -- MyAddon = LibStub("AceAddon-3.0"):NewAddon("MyAddon")
Zerotorescue@0 396 -- -- Set the default state to "disabled"
Zerotorescue@0 397 -- MyAddon:SetDefaultModuleState(false)
Zerotorescue@0 398 -- -- Create a module and explicilty enable it
Zerotorescue@0 399 -- MyModule = MyAddon:NewModule("MyModule")
Zerotorescue@0 400 -- MyModule:Enable()
Zerotorescue@0 401 function SetDefaultModuleState(self, state)
Zerotorescue@0 402 if next(self.modules) then
Zerotorescue@0 403 error("Usage: SetDefaultModuleState(state): cannot change the module defaults after a module has been registered.", 2)
Zerotorescue@0 404 end
Zerotorescue@0 405 self.defaultModuleState = state
Zerotorescue@0 406 end
Zerotorescue@0 407
Zerotorescue@0 408 --- Set the default prototype to use for new modules on creation.
Zerotorescue@0 409 -- Note that you can only change the default prototype before any module is created.
Zerotorescue@0 410 -- @name //addon//:SetDefaultModulePrototype
Zerotorescue@0 411 -- @paramsig prototype
Zerotorescue@0 412 -- @param prototype Default prototype for the new modules (table)
Zerotorescue@0 413 -- @usage
Zerotorescue@0 414 -- -- Define a prototype
Zerotorescue@0 415 -- local prototype = { OnEnable = function(self) print("OnEnable called!") end }
Zerotorescue@0 416 -- -- Set the default prototype
Zerotorescue@0 417 -- MyAddon:SetDefaultModulePrototype(prototype)
Zerotorescue@0 418 -- -- Create a module and explicitly Enable it
Zerotorescue@0 419 -- MyModule = MyAddon:NewModule("MyModule")
Zerotorescue@0 420 -- MyModule:Enable()
Zerotorescue@0 421 -- -- should print "OnEnable called!" now
Zerotorescue@0 422 -- @see NewModule
Zerotorescue@0 423 function SetDefaultModulePrototype(self, prototype)
Zerotorescue@0 424 if next(self.modules) then
Zerotorescue@0 425 error("Usage: SetDefaultModulePrototype(prototype): cannot change the module defaults after a module has been registered.", 2)
Zerotorescue@0 426 end
Zerotorescue@0 427 if type(prototype) ~= "table" then
Zerotorescue@0 428 error(("Usage: SetDefaultModulePrototype(prototype): 'prototype' - table expected got '%s'."):format(type(prototype)), 2)
Zerotorescue@0 429 end
Zerotorescue@0 430 self.defaultModulePrototype = prototype
Zerotorescue@0 431 end
Zerotorescue@0 432
Zerotorescue@0 433 --- Set the state of an addon or module
Zerotorescue@0 434 -- This should only be called before any enabling actually happend, e.g. in/before OnInitialize.
Zerotorescue@0 435 -- @name //addon//:SetEnabledState
Zerotorescue@0 436 -- @paramsig state
Zerotorescue@0 437 -- @param state the state of an addon or module (enabled=true, disabled=false)
Zerotorescue@0 438 function SetEnabledState(self, state)
Zerotorescue@0 439 self.enabledState = state
Zerotorescue@0 440 end
Zerotorescue@0 441
Zerotorescue@0 442
Zerotorescue@0 443 --- Return an iterator of all modules associated to the addon.
Zerotorescue@0 444 -- @name //addon//:IterateModules
Zerotorescue@0 445 -- @paramsig
Zerotorescue@0 446 -- @usage
Zerotorescue@0 447 -- -- Enable all modules
Zerotorescue@0 448 -- for name, module in MyAddon:IterateModules() do
Zerotorescue@0 449 -- module:Enable()
Zerotorescue@0 450 -- end
Zerotorescue@0 451 local function IterateModules(self) return pairs(self.modules) end
Zerotorescue@0 452
Zerotorescue@0 453 -- Returns an iterator of all embeds in the addon
Zerotorescue@0 454 -- @name //addon//:IterateEmbeds
Zerotorescue@0 455 -- @paramsig
Zerotorescue@0 456 local function IterateEmbeds(self) return pairs(AceAddon.embeds[self]) end
Zerotorescue@0 457
Zerotorescue@0 458 --- Query the enabledState of an addon.
Zerotorescue@0 459 -- @name //addon//:IsEnabled
Zerotorescue@0 460 -- @paramsig
Zerotorescue@0 461 -- @usage
Zerotorescue@0 462 -- if MyAddon:IsEnabled() then
Zerotorescue@0 463 -- MyAddon:Disable()
Zerotorescue@0 464 -- end
Zerotorescue@0 465 local function IsEnabled(self) return self.enabledState end
Zerotorescue@0 466 local mixins = {
Zerotorescue@0 467 NewModule = NewModule,
Zerotorescue@0 468 GetModule = GetModule,
Zerotorescue@0 469 Enable = Enable,
Zerotorescue@0 470 Disable = Disable,
Zerotorescue@0 471 EnableModule = EnableModule,
Zerotorescue@0 472 DisableModule = DisableModule,
Zerotorescue@0 473 IsEnabled = IsEnabled,
Zerotorescue@0 474 SetDefaultModuleLibraries = SetDefaultModuleLibraries,
Zerotorescue@0 475 SetDefaultModuleState = SetDefaultModuleState,
Zerotorescue@0 476 SetDefaultModulePrototype = SetDefaultModulePrototype,
Zerotorescue@0 477 SetEnabledState = SetEnabledState,
Zerotorescue@0 478 IterateModules = IterateModules,
Zerotorescue@0 479 IterateEmbeds = IterateEmbeds,
Zerotorescue@0 480 GetName = GetName,
Zerotorescue@0 481 }
Zerotorescue@0 482 local function IsModule(self) return false end
Zerotorescue@0 483 local pmixins = {
Zerotorescue@0 484 defaultModuleState = true,
Zerotorescue@0 485 enabledState = true,
Zerotorescue@0 486 IsModule = IsModule,
Zerotorescue@0 487 }
Zerotorescue@0 488 -- Embed( target )
Zerotorescue@0 489 -- target (object) - target object to embed aceaddon in
Zerotorescue@0 490 --
Zerotorescue@0 491 -- this is a local function specifically since it's meant to be only called internally
Zerotorescue@0 492 function Embed(target)
Zerotorescue@0 493 for k, v in pairs(mixins) do
Zerotorescue@0 494 target[k] = v
Zerotorescue@0 495 end
Zerotorescue@0 496 for k, v in pairs(pmixins) do
Zerotorescue@0 497 target[k] = target[k] or v
Zerotorescue@0 498 end
Zerotorescue@0 499 end
Zerotorescue@0 500
Zerotorescue@0 501
Zerotorescue@0 502 -- - Initialize the addon after creation.
Zerotorescue@0 503 -- This function is only used internally during the ADDON_LOADED event
Zerotorescue@0 504 -- It will call the **OnInitialize** function on the addon object (if present),
Zerotorescue@0 505 -- and the **OnEmbedInitialize** function on all embeded libraries.
Zerotorescue@0 506 --
Zerotorescue@0 507 -- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
Zerotorescue@0 508 -- @param addon addon object to intialize
Zerotorescue@0 509 function AceAddon:InitializeAddon(addon)
Zerotorescue@0 510 safecall(addon.OnInitialize, addon)
Zerotorescue@0 511
Zerotorescue@0 512 local embeds = self.embeds[addon]
Zerotorescue@0 513 for i = 1, #embeds do
Zerotorescue@0 514 local lib = LibStub:GetLibrary(embeds[i], true)
Zerotorescue@0 515 if lib then safecall(lib.OnEmbedInitialize, lib, addon) end
Zerotorescue@0 516 end
Zerotorescue@0 517
Zerotorescue@0 518 -- we don't call InitializeAddon on modules specifically, this is handled
Zerotorescue@0 519 -- from the event handler and only done _once_
Zerotorescue@0 520 end
Zerotorescue@0 521
Zerotorescue@0 522 -- - Enable the addon after creation.
Zerotorescue@0 523 -- Note: This function is only used internally during the PLAYER_LOGIN event, or during ADDON_LOADED,
Zerotorescue@0 524 -- if IsLoggedIn() already returns true at that point, e.g. for LoD Addons.
Zerotorescue@0 525 -- It will call the **OnEnable** function on the addon object (if present),
Zerotorescue@0 526 -- and the **OnEmbedEnable** function on all embeded libraries.\\
Zerotorescue@0 527 -- This function does not toggle the enable state of the addon itself, and will return early if the addon is disabled.
Zerotorescue@0 528 --
Zerotorescue@0 529 -- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
Zerotorescue@0 530 -- Use :Enable on the addon itself instead.
Zerotorescue@0 531 -- @param addon addon object to enable
Zerotorescue@0 532 function AceAddon:EnableAddon(addon)
Zerotorescue@0 533 if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
Zerotorescue@0 534 if self.statuses[addon.name] or not addon.enabledState then return false end
Zerotorescue@0 535
Zerotorescue@0 536 -- set the statuses first, before calling the OnEnable. this allows for Disabling of the addon in OnEnable.
Zerotorescue@0 537 self.statuses[addon.name] = true
Zerotorescue@0 538
Zerotorescue@0 539 safecall(addon.OnEnable, addon)
Zerotorescue@0 540
Zerotorescue@0 541 -- make sure we're still enabled before continueing
Zerotorescue@0 542 if self.statuses[addon.name] then
Zerotorescue@0 543 local embeds = self.embeds[addon]
Zerotorescue@0 544 for i = 1, #embeds do
Zerotorescue@0 545 local lib = LibStub:GetLibrary(embeds[i], true)
Zerotorescue@0 546 if lib then safecall(lib.OnEmbedEnable, lib, addon) end
Zerotorescue@0 547 end
Zerotorescue@0 548
Zerotorescue@0 549 -- enable possible modules.
Zerotorescue@0 550 for name, module in pairs(addon.modules) do
Zerotorescue@0 551 self:EnableAddon(module)
Zerotorescue@0 552 end
Zerotorescue@0 553 end
Zerotorescue@0 554 return self.statuses[addon.name] -- return true if we're disabled
Zerotorescue@0 555 end
Zerotorescue@0 556
Zerotorescue@0 557 -- - Disable the addon
Zerotorescue@0 558 -- Note: This function is only used internally.
Zerotorescue@0 559 -- It will call the **OnDisable** function on the addon object (if present),
Zerotorescue@0 560 -- and the **OnEmbedDisable** function on all embeded libraries.\\
Zerotorescue@0 561 -- This function does not toggle the enable state of the addon itself, and will return early if the addon is still enabled.
Zerotorescue@0 562 --
Zerotorescue@0 563 -- **Note:** Do not call this function manually, unless you're absolutely sure that you know what you are doing.
Zerotorescue@0 564 -- Use :Disable on the addon itself instead.
Zerotorescue@0 565 -- @param addon addon object to enable
Zerotorescue@0 566 function AceAddon:DisableAddon(addon)
Zerotorescue@0 567 if type(addon) == "string" then addon = AceAddon:GetAddon(addon) end
Zerotorescue@0 568 if not self.statuses[addon.name] then return false end
Zerotorescue@0 569
Zerotorescue@0 570 -- set statuses first before calling OnDisable, this allows for aborting the disable in OnDisable.
Zerotorescue@0 571 self.statuses[addon.name] = false
Zerotorescue@0 572
Zerotorescue@0 573 safecall( addon.OnDisable, addon )
Zerotorescue@0 574
Zerotorescue@0 575 -- make sure we're still disabling...
Zerotorescue@0 576 if not self.statuses[addon.name] then
Zerotorescue@0 577 local embeds = self.embeds[addon]
Zerotorescue@0 578 for i = 1, #embeds do
Zerotorescue@0 579 local lib = LibStub:GetLibrary(embeds[i], true)
Zerotorescue@0 580 if lib then safecall(lib.OnEmbedDisable, lib, addon) end
Zerotorescue@0 581 end
Zerotorescue@0 582 -- disable possible modules.
Zerotorescue@0 583 for name, module in pairs(addon.modules) do
Zerotorescue@0 584 self:DisableAddon(module)
Zerotorescue@0 585 end
Zerotorescue@0 586 end
Zerotorescue@0 587
Zerotorescue@0 588 return not self.statuses[addon.name] -- return true if we're disabled
Zerotorescue@0 589 end
Zerotorescue@0 590
Zerotorescue@0 591 --- Get an iterator over all registered addons.
Zerotorescue@0 592 -- @usage
Zerotorescue@0 593 -- -- Print a list of all installed AceAddon's
Zerotorescue@0 594 -- for name, addon in AceAddon:IterateAddons() do
Zerotorescue@0 595 -- print("Addon: " .. name)
Zerotorescue@0 596 -- end
Zerotorescue@0 597 function AceAddon:IterateAddons() return pairs(self.addons) end
Zerotorescue@0 598
Zerotorescue@0 599 --- Get an iterator over the internal status registry.
Zerotorescue@0 600 -- @usage
Zerotorescue@0 601 -- -- Print a list of all enabled addons
Zerotorescue@0 602 -- for name, status in AceAddon:IterateAddonStatus() do
Zerotorescue@0 603 -- if status then
Zerotorescue@0 604 -- print("EnabledAddon: " .. name)
Zerotorescue@0 605 -- end
Zerotorescue@0 606 -- end
Zerotorescue@0 607 function AceAddon:IterateAddonStatus() return pairs(self.statuses) end
Zerotorescue@0 608
Zerotorescue@0 609 -- Following Iterators are deprecated, and their addon specific versions should be used
Zerotorescue@0 610 -- e.g. addon:IterateEmbeds() instead of :IterateEmbedsOnAddon(addon)
Zerotorescue@0 611 function AceAddon:IterateEmbedsOnAddon(addon) return pairs(self.embeds[addon]) end
Zerotorescue@0 612 function AceAddon:IterateModulesOfAddon(addon) return pairs(addon.modules) end
Zerotorescue@0 613
Zerotorescue@0 614 -- Event Handling
Zerotorescue@0 615 local function onEvent(this, event, arg1)
Zerotorescue@0 616 if event == "ADDON_LOADED" or event == "PLAYER_LOGIN" then
Zerotorescue@0 617 -- if a addon loads another addon, recursion could happen here, so we need to validate the table on every iteration
Zerotorescue@0 618 while(#AceAddon.initializequeue > 0) do
Zerotorescue@0 619 local addon = tremove(AceAddon.initializequeue, 1)
Zerotorescue@0 620 -- this might be an issue with recursion - TODO: validate
Zerotorescue@0 621 if event == "ADDON_LOADED" then addon.baseName = arg1 end
Zerotorescue@0 622 AceAddon:InitializeAddon(addon)
Zerotorescue@0 623 tinsert(AceAddon.enablequeue, addon)
Zerotorescue@0 624 end
Zerotorescue@0 625
Zerotorescue@0 626 if IsLoggedIn() then
Zerotorescue@0 627 while(#AceAddon.enablequeue > 0) do
Zerotorescue@0 628 local addon = tremove(AceAddon.enablequeue, 1)
Zerotorescue@0 629 AceAddon:EnableAddon(addon)
Zerotorescue@0 630 end
Zerotorescue@0 631 end
Zerotorescue@0 632 end
Zerotorescue@0 633 end
Zerotorescue@0 634
Zerotorescue@0 635 AceAddon.frame:RegisterEvent("ADDON_LOADED")
Zerotorescue@0 636 AceAddon.frame:RegisterEvent("PLAYER_LOGIN")
Zerotorescue@0 637 AceAddon.frame:SetScript("OnEvent", onEvent)
Zerotorescue@0 638
Zerotorescue@0 639 -- upgrade embeded
Zerotorescue@0 640 for name, addon in pairs(AceAddon.addons) do
Zerotorescue@0 641 Embed(addon)
Zerotorescue@0 642 end