flickerstreak@23
|
1 --[[
|
flickerstreak@23
|
2 Name: AceModuleCore-2.0
|
flickerstreak@23
|
3 Revision: $Rev: 43318 $
|
flickerstreak@23
|
4 Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
|
flickerstreak@23
|
5 Inspired By: Ace 1.x by Turan (turan@gryphon.com)
|
flickerstreak@23
|
6 Website: http://www.wowace.com/
|
flickerstreak@23
|
7 Documentation: http://www.wowace.com/index.php/AceModuleCore-2.0
|
flickerstreak@23
|
8 SVN: http://svn.wowace.com/root/trunk/Ace2/AceModuleCore-2.0
|
flickerstreak@23
|
9 Description: Mixin to provide a module system so that modules or plugins can
|
flickerstreak@23
|
10 use an addon as its core.
|
flickerstreak@23
|
11 Dependencies: AceLibrary, AceOO-2.0, AceAddon-2.0, AceEvent-2.0 (optional)
|
flickerstreak@23
|
12 License: LGPL v2.1
|
flickerstreak@23
|
13 ]]
|
flickerstreak@23
|
14
|
flickerstreak@23
|
15 local MAJOR_VERSION = "AceModuleCore-2.0"
|
flickerstreak@23
|
16 local MINOR_VERSION = "$Revision: 43318 $"
|
flickerstreak@23
|
17
|
flickerstreak@23
|
18 if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
|
flickerstreak@23
|
19 if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
flickerstreak@23
|
20
|
flickerstreak@23
|
21 if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end
|
flickerstreak@23
|
22
|
flickerstreak@23
|
23 local function safecall(func, ...)
|
flickerstreak@23
|
24 local success, err = pcall(func, ...)
|
flickerstreak@23
|
25 if not success then geterrorhandler()(err:find("%.lua:%d+:") and err or (debugstack():match("\n(.-: )in.-\n") or "") .. err) end
|
flickerstreak@23
|
26 end
|
flickerstreak@23
|
27
|
flickerstreak@23
|
28 local AceEvent
|
flickerstreak@23
|
29 local AceOO = AceLibrary:GetInstance("AceOO-2.0")
|
flickerstreak@23
|
30 local AceModuleCore = AceOO.Mixin {
|
flickerstreak@23
|
31 "NewModule",
|
flickerstreak@23
|
32 "HasModule",
|
flickerstreak@23
|
33 "GetModule",
|
flickerstreak@23
|
34 "IsModule",
|
flickerstreak@23
|
35 "IterateModules",
|
flickerstreak@23
|
36 "IterateModulesWithMethod",
|
flickerstreak@23
|
37 "CallMethodOnAllModules",
|
flickerstreak@23
|
38 "SetModuleMixins",
|
flickerstreak@23
|
39 "SetModuleClass",
|
flickerstreak@23
|
40 "IsModuleActive",
|
flickerstreak@23
|
41 "ToggleModuleActive",
|
flickerstreak@23
|
42 "SetModuleDefaultState",
|
flickerstreak@23
|
43 }
|
flickerstreak@23
|
44 local AceAddon
|
flickerstreak@23
|
45
|
flickerstreak@23
|
46 local function getlibrary(lib)
|
flickerstreak@23
|
47 if type(lib) == "string" then
|
flickerstreak@23
|
48 return AceLibrary(lib)
|
flickerstreak@23
|
49 else
|
flickerstreak@23
|
50 return lib
|
flickerstreak@23
|
51 end
|
flickerstreak@23
|
52 end
|
flickerstreak@23
|
53
|
flickerstreak@23
|
54 local new, del
|
flickerstreak@23
|
55 do
|
flickerstreak@23
|
56 local list = setmetatable({}, {__mode='k'})
|
flickerstreak@23
|
57 function new()
|
flickerstreak@23
|
58 local t = next(list)
|
flickerstreak@23
|
59 if t then
|
flickerstreak@23
|
60 list[t] = nil
|
flickerstreak@23
|
61 return t
|
flickerstreak@23
|
62 else
|
flickerstreak@23
|
63 return {}
|
flickerstreak@23
|
64 end
|
flickerstreak@23
|
65 end
|
flickerstreak@23
|
66 function del(t)
|
flickerstreak@23
|
67 for k in pairs(t) do
|
flickerstreak@23
|
68 t[k] = nil
|
flickerstreak@23
|
69 end
|
flickerstreak@23
|
70 list[t] = true
|
flickerstreak@23
|
71 return nil
|
flickerstreak@23
|
72 end
|
flickerstreak@23
|
73 end
|
flickerstreak@23
|
74
|
flickerstreak@23
|
75 local iterList = setmetatable({}, {__mode='v'})
|
flickerstreak@23
|
76 local modulesWithMethod = setmetatable({}, {__mode='kv'})
|
flickerstreak@23
|
77 do
|
flickerstreak@23
|
78 local function func(t)
|
flickerstreak@23
|
79 local i = t.i + 1
|
flickerstreak@23
|
80 local l = t.l
|
flickerstreak@23
|
81 local k = l[i]
|
flickerstreak@23
|
82 if k then
|
flickerstreak@23
|
83 t.i = i
|
flickerstreak@23
|
84 return k, l.m[k]
|
flickerstreak@23
|
85 else
|
flickerstreak@23
|
86 t = del(t)
|
flickerstreak@23
|
87 end
|
flickerstreak@23
|
88 end
|
flickerstreak@23
|
89 function AceModuleCore:IterateModules()
|
flickerstreak@23
|
90 local list = iterList[self]
|
flickerstreak@23
|
91 if not list then
|
flickerstreak@23
|
92 list = new()
|
flickerstreak@23
|
93 for k in pairs(self.modules) do
|
flickerstreak@23
|
94 list[#list+1] = k
|
flickerstreak@23
|
95 end
|
flickerstreak@23
|
96 table.sort(list)
|
flickerstreak@23
|
97 list.m = self.modules
|
flickerstreak@23
|
98 iterList[self] = list
|
flickerstreak@23
|
99 end
|
flickerstreak@23
|
100 local t = new()
|
flickerstreak@23
|
101 t.i = 0
|
flickerstreak@23
|
102 t.l = list
|
flickerstreak@23
|
103 return func, t, nil
|
flickerstreak@23
|
104 end
|
flickerstreak@23
|
105
|
flickerstreak@23
|
106 function AceModuleCore:IterateModulesWithMethod(method)
|
flickerstreak@23
|
107 local masterList = modulesWithMethod[self]
|
flickerstreak@23
|
108 if not masterList then
|
flickerstreak@23
|
109 masterList = new()
|
flickerstreak@23
|
110 modulesWithMethod[self] = masterList
|
flickerstreak@23
|
111 end
|
flickerstreak@23
|
112 local list = masterList[method]
|
flickerstreak@23
|
113 if not list then
|
flickerstreak@23
|
114 list = new()
|
flickerstreak@23
|
115 for k, v in pairs(self.modules) do
|
flickerstreak@23
|
116 if self:IsModuleActive(k) and type(v[method]) == "function" then
|
flickerstreak@23
|
117 list[#list+1] = k
|
flickerstreak@23
|
118 end
|
flickerstreak@23
|
119 end
|
flickerstreak@23
|
120 table.sort(list)
|
flickerstreak@23
|
121 list.m = self.modules
|
flickerstreak@23
|
122 masterList[method] = list
|
flickerstreak@23
|
123 end
|
flickerstreak@23
|
124 local t = new()
|
flickerstreak@23
|
125 t.i = 0
|
flickerstreak@23
|
126 t.l = list
|
flickerstreak@23
|
127 return func, t, nil
|
flickerstreak@23
|
128 end
|
flickerstreak@23
|
129
|
flickerstreak@23
|
130 --[[----------------------------------------------------------------------------------
|
flickerstreak@23
|
131 Notes:
|
flickerstreak@23
|
132 Safely calls the given method on all active modules if it exists on said modules. This will automatically subvert any errors that occur in the modules.
|
flickerstreak@23
|
133 Arguments:
|
flickerstreak@23
|
134 string - the name of the method.
|
flickerstreak@23
|
135 tuple - the list of arguments to call the method with.
|
flickerstreak@23
|
136 Example:
|
flickerstreak@23
|
137 core:CallMethodOnAllModules("OnSomething")
|
flickerstreak@23
|
138 core:CallMethodOnAllModules("OnSomethingElse", 1, 2, 3, 4)
|
flickerstreak@23
|
139 ------------------------------------------------------------------------------------]]
|
flickerstreak@23
|
140 function AceModuleCore:CallMethodOnAllModules(method, ...)
|
flickerstreak@23
|
141 for name, module in self:IterateModulesWithMethod(method) do
|
flickerstreak@23
|
142 local success, ret = pcall(module[method], module, ...)
|
flickerstreak@23
|
143 if not success then
|
flickerstreak@23
|
144 geterrorhandler()(ret)
|
flickerstreak@23
|
145 end
|
flickerstreak@23
|
146 end
|
flickerstreak@23
|
147 end
|
flickerstreak@23
|
148 end
|
flickerstreak@23
|
149
|
flickerstreak@23
|
150 --[[----------------------------------------------------------------------------
|
flickerstreak@23
|
151 Notes:
|
flickerstreak@23
|
152 Create a new module, parented to self.
|
flickerstreak@23
|
153 The module created does, in fact, inherit from AceAddon-2.0.
|
flickerstreak@23
|
154 Arguments:
|
flickerstreak@23
|
155 string - name/title of the Module.
|
flickerstreak@23
|
156 list of mixins the module is to inherit from.
|
flickerstreak@23
|
157 Example:
|
flickerstreak@23
|
158 MyModule = core:NewModule('MyModule', "AceEvent-2.0", "AceHook-2.1")
|
flickerstreak@23
|
159 ------------------------------------------------------------------------------]]
|
flickerstreak@23
|
160 local tmp = {}
|
flickerstreak@23
|
161 function AceModuleCore:NewModule(name, ...)
|
flickerstreak@23
|
162 if not self.modules then
|
flickerstreak@23
|
163 AceModuleCore:error("CreatePrototype() must be called before attempting to create a new module.", 2)
|
flickerstreak@23
|
164 end
|
flickerstreak@23
|
165 AceModuleCore:argCheck(name, 2, "string")
|
flickerstreak@23
|
166 if name:len() == 0 then
|
flickerstreak@23
|
167 AceModuleCore:error("Bad argument #2 to `NewModule`, string must not be empty")
|
flickerstreak@23
|
168 end
|
flickerstreak@23
|
169 if self.modules[name] then
|
flickerstreak@23
|
170 AceModuleCore:error("The module %q has already been registered", name)
|
flickerstreak@23
|
171 end
|
flickerstreak@23
|
172
|
flickerstreak@23
|
173 if iterList[self] then
|
flickerstreak@23
|
174 iterList[self] = del(iterList[self])
|
flickerstreak@23
|
175 end
|
flickerstreak@23
|
176
|
flickerstreak@23
|
177 for i = 1, select('#', ...) do
|
flickerstreak@23
|
178 tmp[i] = getlibrary((select(i, ...)))
|
flickerstreak@23
|
179 end
|
flickerstreak@23
|
180
|
flickerstreak@23
|
181 if self.moduleMixins then
|
flickerstreak@23
|
182 for _,mixin in ipairs(self.moduleMixins) do
|
flickerstreak@23
|
183 local exists = false
|
flickerstreak@23
|
184 for _,v in ipairs(tmp) do
|
flickerstreak@23
|
185 if mixin == v then
|
flickerstreak@23
|
186 exists = true
|
flickerstreak@23
|
187 break
|
flickerstreak@23
|
188 end
|
flickerstreak@23
|
189 end
|
flickerstreak@23
|
190 if not exists then
|
flickerstreak@23
|
191 tmp[#tmp+1] = mixin
|
flickerstreak@23
|
192 end
|
flickerstreak@23
|
193 end
|
flickerstreak@23
|
194 end
|
flickerstreak@23
|
195
|
flickerstreak@23
|
196 local module = AceOO.Classpool(self.moduleClass, unpack(tmp)):new(name)
|
flickerstreak@23
|
197 self.modules[name] = module
|
flickerstreak@23
|
198 module.name = name
|
flickerstreak@23
|
199 module.title = name
|
flickerstreak@23
|
200
|
flickerstreak@23
|
201 AceModuleCore.totalModules[module] = self
|
flickerstreak@23
|
202
|
flickerstreak@23
|
203 if modulesWithMethod[self] then
|
flickerstreak@23
|
204 for k,v in pairs(modulesWithMethod[self]) do
|
flickerstreak@23
|
205 modulesWithMethod[self] = del(v)
|
flickerstreak@23
|
206 end
|
flickerstreak@23
|
207 end
|
flickerstreak@23
|
208
|
flickerstreak@23
|
209 if type(self.OnModuleCreated) == "function" then
|
flickerstreak@23
|
210 safecall(self.OnModuleCreated, self, name, module)
|
flickerstreak@23
|
211 end
|
flickerstreak@23
|
212 if AceEvent then
|
flickerstreak@23
|
213 AceEvent:TriggerEvent("Ace2_ModuleCreated", module)
|
flickerstreak@23
|
214 end
|
flickerstreak@23
|
215
|
flickerstreak@23
|
216 local num = #tmp
|
flickerstreak@23
|
217 for i = 1, num do
|
flickerstreak@23
|
218 tmp[i] = nil
|
flickerstreak@23
|
219 end
|
flickerstreak@23
|
220 return module
|
flickerstreak@23
|
221 end
|
flickerstreak@23
|
222 --[[----------------------------------------------------------------------------------
|
flickerstreak@23
|
223 Notes:
|
flickerstreak@23
|
224 Return whether the module names given are all available in the core.
|
flickerstreak@23
|
225 Arguments:
|
flickerstreak@23
|
226 list of strings that are the names of the modules. (typically you'd only check for one)
|
flickerstreak@23
|
227 Returns:
|
flickerstreak@23
|
228 * boolean - Whether all the modules are available in the core.
|
flickerstreak@23
|
229 Example:
|
flickerstreak@23
|
230 if core:HasModule('Bank') then
|
flickerstreak@23
|
231 -- do banking
|
flickerstreak@23
|
232 end
|
flickerstreak@23
|
233 ------------------------------------------------------------------------------------]]
|
flickerstreak@23
|
234 function AceModuleCore:HasModule(...)
|
flickerstreak@23
|
235 for i = 1, select('#', ...) do
|
flickerstreak@23
|
236 if not self.modules[select(i, ...)] then
|
flickerstreak@23
|
237 return false
|
flickerstreak@23
|
238 end
|
flickerstreak@23
|
239 end
|
flickerstreak@23
|
240
|
flickerstreak@23
|
241 return true
|
flickerstreak@23
|
242 end
|
flickerstreak@23
|
243
|
flickerstreak@23
|
244 --[[------------------------------------------------------------------------------------
|
flickerstreak@23
|
245 Notes:
|
flickerstreak@23
|
246 Return the module "name" if it exists.
|
flickerstreak@23
|
247 If the module doesnot exist, an error is thrown.
|
flickerstreak@23
|
248 Arguments:
|
flickerstreak@23
|
249 string - the name of the module.
|
flickerstreak@23
|
250 Returns:
|
flickerstreak@23
|
251 The module requested, if it exists.
|
flickerstreak@23
|
252 Example:
|
flickerstreak@23
|
253 local bank = core:GetModule('Bank')
|
flickerstreak@23
|
254 ------------------------------------------------------------------------------------]]
|
flickerstreak@23
|
255 function AceModuleCore:GetModule(name)
|
flickerstreak@23
|
256 if not self.modules then
|
flickerstreak@23
|
257 AceModuleCore:error("Error initializing class. Please report error.")
|
flickerstreak@23
|
258 end
|
flickerstreak@23
|
259 if not self.modules[name] then
|
flickerstreak@23
|
260 AceModuleCore:error("Cannot find module %q.", name)
|
flickerstreak@23
|
261 end
|
flickerstreak@23
|
262 return self.modules[name]
|
flickerstreak@23
|
263 end
|
flickerstreak@23
|
264
|
flickerstreak@23
|
265 --[[----------------------------------------------------------------------------------
|
flickerstreak@23
|
266 Notes:
|
flickerstreak@23
|
267 Return whether the given module is actually a module.
|
flickerstreak@23
|
268 Arguments:
|
flickerstreak@23
|
269 reference to the module
|
flickerstreak@23
|
270 Returns:
|
flickerstreak@23
|
271 * boolean - whether the given module is actually a module.
|
flickerstreak@23
|
272 Example:
|
flickerstreak@23
|
273 if core:IsModule(module) then
|
flickerstreak@23
|
274 -- do something
|
flickerstreak@23
|
275 end
|
flickerstreak@23
|
276 -- alternatively
|
flickerstreak@23
|
277 if AceModuleCore:IsModule(module) then
|
flickerstreak@23
|
278 -- checks all modules, no matter the parent
|
flickerstreak@23
|
279 end
|
flickerstreak@23
|
280 ------------------------------------------------------------------------------------]]
|
flickerstreak@23
|
281 function AceModuleCore:IsModule(module)
|
flickerstreak@23
|
282 if self == AceModuleCore then
|
flickerstreak@23
|
283 return AceModuleCore.totalModules[module]
|
flickerstreak@23
|
284 elseif type(module) == "table" then
|
flickerstreak@23
|
285 if module.name and self.modules[module.name] and self.modules[module.name].name == module.name then
|
flickerstreak@23
|
286 return true
|
flickerstreak@23
|
287 end
|
flickerstreak@23
|
288 for k,v in pairs(self.modules) do
|
flickerstreak@23
|
289 if v == module then
|
flickerstreak@23
|
290 return true
|
flickerstreak@23
|
291 end
|
flickerstreak@23
|
292 end
|
flickerstreak@23
|
293 return false
|
flickerstreak@23
|
294 end
|
flickerstreak@23
|
295 end
|
flickerstreak@23
|
296
|
flickerstreak@23
|
297 --[[----------------------------------------------------------------------------------
|
flickerstreak@23
|
298 Notes:
|
flickerstreak@23
|
299 * Sets the default mixins for a given module.
|
flickerstreak@23
|
300 * This cannot be called after :NewModule() has been called.
|
flickerstreak@23
|
301 * This should really only be called if you use the mixins in your prototype.
|
flickerstreak@23
|
302 Arguments:
|
flickerstreak@23
|
303 list of mixins (up to 20)
|
flickerstreak@23
|
304 Example:
|
flickerstreak@23
|
305 core:SetModuleMixins("AceEvent-2.0", "AceHook-2.0")
|
flickerstreak@23
|
306 ------------------------------------------------------------------------------------]]
|
flickerstreak@23
|
307 function AceModuleCore:SetModuleMixins(...)
|
flickerstreak@23
|
308 if self.moduleMixins then
|
flickerstreak@23
|
309 AceModuleCore:error('Cannot call "SetModuleMixins" twice')
|
flickerstreak@23
|
310 elseif not self.modules then
|
flickerstreak@23
|
311 AceModuleCore:error("Error initializing class. Please report error.")
|
flickerstreak@23
|
312 elseif next(self.modules) then
|
flickerstreak@23
|
313 AceModuleCore:error('Cannot call "SetModuleMixins" after "NewModule" has been called.')
|
flickerstreak@23
|
314 end
|
flickerstreak@23
|
315
|
flickerstreak@23
|
316 self.moduleMixins = { ... }
|
flickerstreak@23
|
317 for i,v in ipairs(self.moduleMixins) do
|
flickerstreak@23
|
318 self.moduleMixins[i] = getlibrary(v)
|
flickerstreak@23
|
319 end
|
flickerstreak@23
|
320 end
|
flickerstreak@23
|
321
|
flickerstreak@23
|
322 -- #NODOC
|
flickerstreak@23
|
323 function AceModuleCore:SetModuleClass(class)
|
flickerstreak@23
|
324 class = getlibrary(class)
|
flickerstreak@23
|
325 if not AceOO.inherits(class, AceOO.Class) then
|
flickerstreak@23
|
326 AceModuleCore:error("Bad argument #2 to `SetModuleClass' (Class expected)")
|
flickerstreak@23
|
327 end
|
flickerstreak@23
|
328 if not self.modules then
|
flickerstreak@23
|
329 AceModuleCore:error("Error initializing class. Please report error.")
|
flickerstreak@23
|
330 end
|
flickerstreak@23
|
331 if self.customModuleClass then
|
flickerstreak@23
|
332 AceModuleCore:error("Cannot call `SetModuleClass' twice.")
|
flickerstreak@23
|
333 end
|
flickerstreak@23
|
334 self.customModuleClass = true
|
flickerstreak@23
|
335 self.moduleClass = class
|
flickerstreak@23
|
336 self.modulePrototype = class.prototype
|
flickerstreak@23
|
337 end
|
flickerstreak@23
|
338
|
flickerstreak@23
|
339 local mt = {__index=function(self, key)
|
flickerstreak@23
|
340 self[key] = false
|
flickerstreak@23
|
341 return false
|
flickerstreak@23
|
342 end}
|
flickerstreak@23
|
343 local defaultState = setmetatable({}, {__index=function(self, key)
|
flickerstreak@23
|
344 local t = setmetatable({}, mt)
|
flickerstreak@23
|
345 self[key] = t
|
flickerstreak@23
|
346 return t
|
flickerstreak@23
|
347 end})
|
flickerstreak@23
|
348
|
flickerstreak@23
|
349 local function isDisabled(core, module)
|
flickerstreak@23
|
350 local moduleName
|
flickerstreak@23
|
351 if type(module) == "table" then
|
flickerstreak@23
|
352 moduleName = module.name
|
flickerstreak@23
|
353 else
|
flickerstreak@23
|
354 moduleName = module
|
flickerstreak@23
|
355 end
|
flickerstreak@23
|
356 local disabled
|
flickerstreak@23
|
357 if type(module) == "table" and type(module.IsActive) == "function" then
|
flickerstreak@23
|
358 return not module:IsActive()
|
flickerstreak@23
|
359 elseif AceOO.inherits(core, "AceDB-2.0") then
|
flickerstreak@23
|
360 local _,profile = core:GetProfile()
|
flickerstreak@23
|
361 disabled = core.db and core.db.raw and core.db.raw.disabledModules and core.db.raw.disabledModules[profile] and core.db.raw.disabledModules[profile][moduleName]
|
flickerstreak@23
|
362 else
|
flickerstreak@23
|
363 disabled = core.disabledModules and core.disabledModules[moduleName]
|
flickerstreak@23
|
364 end
|
flickerstreak@23
|
365 if disabled == nil then
|
flickerstreak@23
|
366 return defaultState[core][moduleName]
|
flickerstreak@23
|
367 else
|
flickerstreak@23
|
368 return disabled
|
flickerstreak@23
|
369 end
|
flickerstreak@23
|
370 end
|
flickerstreak@23
|
371
|
flickerstreak@23
|
372 --[[----------------------------------------------------------------------------------
|
flickerstreak@23
|
373 Notes:
|
flickerstreak@23
|
374 Sets the default active state of a module. This should be called before the ADDON_LOADED of the module.
|
flickerstreak@23
|
375 Arguments:
|
flickerstreak@23
|
376 string - name of the module.
|
flickerstreak@23
|
377 table - reference to the module.
|
flickerstreak@23
|
378 boolean - new state. false means disabled by default, true means enabled by default (true is the default).
|
flickerstreak@23
|
379 Example:
|
flickerstreak@23
|
380 self:SetModuleDefaultState('bank', false)
|
flickerstreak@23
|
381 ------------------------------------------------------------------------------------]]
|
flickerstreak@23
|
382 function AceModuleCore:SetModuleDefaultState(module, state)
|
flickerstreak@23
|
383 AceModuleCore:argCheck(module, 2, "table", "string")
|
flickerstreak@23
|
384 AceModuleCore:argCheck(state, 3, "boolean")
|
flickerstreak@23
|
385
|
flickerstreak@23
|
386 if type(module) == "table" then
|
flickerstreak@23
|
387 if not self:IsModule(module) then
|
flickerstreak@23
|
388 AceModuleCore:error("%q is not a module", module)
|
flickerstreak@23
|
389 end
|
flickerstreak@23
|
390 module = module.name
|
flickerstreak@23
|
391 end
|
flickerstreak@23
|
392
|
flickerstreak@23
|
393 defaultState[self][module] = not state
|
flickerstreak@23
|
394 end
|
flickerstreak@23
|
395
|
flickerstreak@23
|
396 --[[----------------------------------------------------------------------------------
|
flickerstreak@23
|
397 Notes:
|
flickerstreak@23
|
398 Toggles the active state of a module.
|
flickerstreak@23
|
399
|
flickerstreak@23
|
400 This calls module:ToggleActive([state]) if available.
|
flickerstreak@23
|
401
|
flickerstreak@23
|
402 If suspending, This will call :OnDisable() on the module if it is available. Also, it will iterate through the addon's mixins and call :OnEmbedDisable(module) if available. - this in turn will, through AceEvent and others, unregister events/hooks/etc. depending on the mixin. Also, it will call :OnModuleDisable(module) on the core if it is available.
|
flickerstreak@23
|
403
|
flickerstreak@23
|
404 If resuming, This will call :OnEnable(first) on the module if it is available. Also, it will iterate through the addon's mixins and call :OnEmbedEnable(module) if available. - this in turn will, through AceEvent and others, unregister events/hooks/etc. depending on the mixin. Also, it will call :OnModuleEnable(module) on the core if it is available.
|
flickerstreak@23
|
405
|
flickerstreak@23
|
406 If you call :ToggleModuleActive("name or module, true) and it is already active, it silently returns, same if you pass false and it is inactive.
|
flickerstreak@23
|
407
|
flickerstreak@23
|
408 Arguments:
|
flickerstreak@23
|
409 string/table - name of the module or a reference to the module
|
flickerstreak@23
|
410 [optional] boolean - new state. (default not :IsModuleActive("name" or module))
|
flickerstreak@23
|
411 Returns:
|
flickerstreak@23
|
412 * boolean - Whether the module is now in an active (enabled) state.
|
flickerstreak@23
|
413 Example:
|
flickerstreak@23
|
414 self:ToggleModuleActive('bank')
|
flickerstreak@23
|
415 ------------------------------------------------------------------------------------]]
|
flickerstreak@23
|
416 function AceModuleCore:ToggleModuleActive(module, state)
|
flickerstreak@23
|
417 AceModuleCore:argCheck(module, 2, "table", "string")
|
flickerstreak@23
|
418 AceModuleCore:argCheck(state, 3, "nil", "boolean")
|
flickerstreak@23
|
419
|
flickerstreak@23
|
420 if type(module) == "string" then
|
flickerstreak@23
|
421 if not self:HasModule(module) then
|
flickerstreak@23
|
422 AceModuleCore:error("Cannot find module %q", module)
|
flickerstreak@23
|
423 end
|
flickerstreak@23
|
424 module = self:GetModule(module)
|
flickerstreak@23
|
425 elseif not self:IsModule(module) then
|
flickerstreak@23
|
426 AceModuleCore:error("%q is not a module", module)
|
flickerstreak@23
|
427 end
|
flickerstreak@23
|
428
|
flickerstreak@23
|
429 local disable
|
flickerstreak@23
|
430 if state == nil then
|
flickerstreak@23
|
431 disable = self:IsModuleActive(module)
|
flickerstreak@23
|
432 else
|
flickerstreak@23
|
433 disable = not state
|
flickerstreak@23
|
434 if disable ~= self:IsModuleActive(module) then
|
flickerstreak@23
|
435 return
|
flickerstreak@23
|
436 end
|
flickerstreak@23
|
437 end
|
flickerstreak@23
|
438
|
flickerstreak@23
|
439 if type(module.ToggleActive) == "function" then
|
flickerstreak@23
|
440 return module:ToggleActive(not disable)
|
flickerstreak@23
|
441 elseif AceOO.inherits(self, "AceDB-2.0") then
|
flickerstreak@23
|
442 if not self.db or not self.db.raw then
|
flickerstreak@23
|
443 AceModuleCore:error("Cannot toggle a module until `RegisterDB' has been called and `ADDON_LOADED' has been fired.")
|
flickerstreak@23
|
444 end
|
flickerstreak@23
|
445 if type(self.db.raw.disabledModules) ~= "table" then
|
flickerstreak@23
|
446 self.db.raw.disabledModules = {}
|
flickerstreak@23
|
447 end
|
flickerstreak@23
|
448 local _,profile = self:GetProfile()
|
flickerstreak@23
|
449 if type(self.db.raw.disabledModules[profile]) ~= "table" then
|
flickerstreak@23
|
450 self.db.raw.disabledModules[profile] = {}
|
flickerstreak@23
|
451 end
|
flickerstreak@23
|
452 if type(self.db.raw.disabledModules[profile][module.name]) ~= "table" then
|
flickerstreak@23
|
453 local value = nil
|
flickerstreak@23
|
454 if disable ~= defaultState[self][module.name] then
|
flickerstreak@23
|
455 value = disable
|
flickerstreak@23
|
456 end
|
flickerstreak@23
|
457 self.db.raw.disabledModules[profile][module.name] = value
|
flickerstreak@23
|
458 end
|
flickerstreak@23
|
459 if not disable then
|
flickerstreak@23
|
460 if not next(self.db.raw.disabledModules[profile]) then
|
flickerstreak@23
|
461 self.db.raw.disabledModules[profile] = nil
|
flickerstreak@23
|
462 end
|
flickerstreak@23
|
463 if not next(self.db.raw.disabledModules) then
|
flickerstreak@23
|
464 self.db.raw.disabledModules = nil
|
flickerstreak@23
|
465 end
|
flickerstreak@23
|
466 end
|
flickerstreak@23
|
467 else
|
flickerstreak@23
|
468 if type(self.disabledModules) ~= "table" then
|
flickerstreak@23
|
469 self.disabledModules = {}
|
flickerstreak@23
|
470 end
|
flickerstreak@23
|
471 local value = nil
|
flickerstreak@23
|
472 if disable ~= defaultState[self][module.name] then
|
flickerstreak@23
|
473 value = disable
|
flickerstreak@23
|
474 end
|
flickerstreak@23
|
475 self.disabledModules[module.name] = value
|
flickerstreak@23
|
476 end
|
flickerstreak@23
|
477 if AceOO.inherits(module, "AceAddon-2.0") then
|
flickerstreak@23
|
478 if not AceAddon.addonsStarted[module] then
|
flickerstreak@23
|
479 return
|
flickerstreak@23
|
480 end
|
flickerstreak@23
|
481 end
|
flickerstreak@23
|
482 if not disable then
|
flickerstreak@23
|
483 local first = nil
|
flickerstreak@23
|
484 if AceOO.inherits(module, "AceAddon-2.0") then
|
flickerstreak@23
|
485 if AceAddon.addonsEnabled and not AceAddon.addonsEnabled[module] then
|
flickerstreak@23
|
486 AceAddon.addonsEnabled[module] = true
|
flickerstreak@23
|
487 first = true
|
flickerstreak@23
|
488 end
|
flickerstreak@23
|
489 end
|
flickerstreak@23
|
490 local current = module.class
|
flickerstreak@23
|
491 while true do
|
flickerstreak@23
|
492 if current == AceOO.Class then
|
flickerstreak@23
|
493 break
|
flickerstreak@23
|
494 end
|
flickerstreak@23
|
495 if current.mixins then
|
flickerstreak@23
|
496 for mixin in pairs(current.mixins) do
|
flickerstreak@23
|
497 if type(mixin.OnEmbedEnable) == "function" then
|
flickerstreak@23
|
498 safecall(mixin.OnEmbedEnable, mixin, module, first)
|
flickerstreak@23
|
499 end
|
flickerstreak@23
|
500 end
|
flickerstreak@23
|
501 end
|
flickerstreak@23
|
502 current = current.super
|
flickerstreak@23
|
503 end
|
flickerstreak@23
|
504 if type(module.OnEnable) == "function" then
|
flickerstreak@23
|
505 safecall(module.OnEnable, module, first)
|
flickerstreak@23
|
506 end
|
flickerstreak@23
|
507 if AceEvent then
|
flickerstreak@23
|
508 AceEvent:TriggerEvent("Ace2_AddonEnabled", module, first)
|
flickerstreak@23
|
509 end
|
flickerstreak@23
|
510 else
|
flickerstreak@23
|
511 local current = module.class
|
flickerstreak@23
|
512 while true do
|
flickerstreak@23
|
513 if current == AceOO.Class then
|
flickerstreak@23
|
514 break
|
flickerstreak@23
|
515 end
|
flickerstreak@23
|
516 if current.mixins then
|
flickerstreak@23
|
517 for mixin in pairs(current.mixins) do
|
flickerstreak@23
|
518 if type(mixin.OnEmbedDisable) == "function" then
|
flickerstreak@23
|
519 safecall(mixin.OnEmbedDisable, mixin, module)
|
flickerstreak@23
|
520 end
|
flickerstreak@23
|
521 end
|
flickerstreak@23
|
522 end
|
flickerstreak@23
|
523 current = current.super
|
flickerstreak@23
|
524 end
|
flickerstreak@23
|
525 if type(module.OnDisable) == "function" then
|
flickerstreak@23
|
526 safecall(module.OnDisable, module)
|
flickerstreak@23
|
527 end
|
flickerstreak@23
|
528 if AceEvent then
|
flickerstreak@23
|
529 AceEvent:TriggerEvent("Ace2_AddonDisabled", module)
|
flickerstreak@23
|
530 end
|
flickerstreak@23
|
531 end
|
flickerstreak@23
|
532 return not disable
|
flickerstreak@23
|
533 end
|
flickerstreak@23
|
534
|
flickerstreak@23
|
535 --[[-----------------------------------------------------------------------
|
flickerstreak@23
|
536 Notes:
|
flickerstreak@23
|
537 Returns whether the module is in an active (enabled) state. This calls module:IsActive() if available. if notLoaded is set, then "name" must be a string.
|
flickerstreak@23
|
538 Arguments:
|
flickerstreak@23
|
539 string/table - name of the module or a reference to the module
|
flickerstreak@23
|
540 [optional] - boolean - if set, this will check modules that are not loaded as well. (default: false)
|
flickerstreak@23
|
541 Returns:
|
flickerstreak@23
|
542 * boolean - Whether the module is in an active (enabled) state.
|
flickerstreak@23
|
543 Example:
|
flickerstreak@23
|
544 assert(self:IsModuleActive('bank'))
|
flickerstreak@23
|
545 ------------------------------------------------------------------------]]
|
flickerstreak@23
|
546 function AceModuleCore:IsModuleActive(module, notLoaded)
|
flickerstreak@23
|
547 AceModuleCore:argCheck(module, 2, "table", "string")
|
flickerstreak@23
|
548 AceModuleCore:argCheck(notLoaded, 3, "nil", "boolean")
|
flickerstreak@23
|
549 if notLoaded then
|
flickerstreak@23
|
550 AceModuleCore:argCheck(module, 2, "string")
|
flickerstreak@23
|
551 end
|
flickerstreak@23
|
552
|
flickerstreak@23
|
553 if AceModuleCore == self then
|
flickerstreak@23
|
554 self:argCheck(module, 2, "table")
|
flickerstreak@23
|
555
|
flickerstreak@23
|
556 local core = AceModuleCore.totalModules[module]
|
flickerstreak@23
|
557 if not core then
|
flickerstreak@23
|
558 self:error("Bad argument #2 to `IsModuleActive'. Not a module")
|
flickerstreak@23
|
559 end
|
flickerstreak@23
|
560 return core:IsModuleActive(module)
|
flickerstreak@23
|
561 end
|
flickerstreak@23
|
562
|
flickerstreak@23
|
563 if type(module) == "string" then
|
flickerstreak@23
|
564 if not notLoaded and not self:HasModule(module) then
|
flickerstreak@23
|
565 AceModuleCore:error("Cannot find module %q", module)
|
flickerstreak@23
|
566 end
|
flickerstreak@23
|
567 if not notLoaded then
|
flickerstreak@23
|
568 module = self:GetModule(module)
|
flickerstreak@23
|
569 else
|
flickerstreak@23
|
570 module = self:HasModule(module) and self:GetModule(module) or module
|
flickerstreak@23
|
571 end
|
flickerstreak@23
|
572 else
|
flickerstreak@23
|
573 if not self:IsModule(module) then
|
flickerstreak@23
|
574 AceModuleCore:error("%q is not a module", module)
|
flickerstreak@23
|
575 end
|
flickerstreak@23
|
576 end
|
flickerstreak@23
|
577
|
flickerstreak@23
|
578 return not isDisabled(self, module)
|
flickerstreak@23
|
579 end
|
flickerstreak@23
|
580
|
flickerstreak@23
|
581 -- #NODOC
|
flickerstreak@23
|
582 function AceModuleCore:OnInstanceInit(target)
|
flickerstreak@23
|
583 if target.modules then
|
flickerstreak@23
|
584 do return end
|
flickerstreak@23
|
585 AceModuleCore:error("OnInstanceInit cannot be called twice")
|
flickerstreak@23
|
586 end
|
flickerstreak@23
|
587
|
flickerstreak@23
|
588 if not AceAddon then
|
flickerstreak@23
|
589 if AceLibrary:HasInstance("AceAddon-2.0") then
|
flickerstreak@23
|
590 AceAddon = AceLibrary("AceAddon-2.0")
|
flickerstreak@23
|
591 else
|
flickerstreak@23
|
592 self:error(MAJOR_VERSION .. " requires AceAddon-2.0")
|
flickerstreak@23
|
593 end
|
flickerstreak@23
|
594 end
|
flickerstreak@23
|
595 target.modules = {}
|
flickerstreak@23
|
596
|
flickerstreak@23
|
597 target.moduleClass = AceOO.Class("AceAddon-2.0")
|
flickerstreak@23
|
598 target.modulePrototype = target.moduleClass.prototype
|
flickerstreak@23
|
599 end
|
flickerstreak@23
|
600
|
flickerstreak@23
|
601 AceModuleCore.OnManualEmbed = AceModuleCore.OnInstanceInit
|
flickerstreak@23
|
602
|
flickerstreak@23
|
603 function AceModuleCore.OnEmbedProfileDisable(AceModuleCore, self, newProfile)
|
flickerstreak@23
|
604 if not AceOO.inherits(self, "AceDB-2.0") then
|
flickerstreak@23
|
605 return
|
flickerstreak@23
|
606 end
|
flickerstreak@23
|
607 local _,currentProfile = self:GetProfile()
|
flickerstreak@23
|
608 for k, module in pairs(self.modules) do
|
flickerstreak@23
|
609 if type(module.IsActive) == "function" or type(module.ToggleActive) == "function" then
|
flickerstreak@23
|
610 -- continue
|
flickerstreak@23
|
611 else
|
flickerstreak@23
|
612 local currentActive = not self.db or not self.db.raw or not self.db.raw.disabledModules or not self.db.raw.disabledModules[currentProfile] or not self.db.raw.disabledModules[currentProfile][module.name]
|
flickerstreak@23
|
613 local newActive = not self.db or not self.db.raw or not self.db.raw.disabledModules or not self.db.raw.disabledModules[newProfile] or not self.db.raw.disabledModules[newProfile][module.name]
|
flickerstreak@23
|
614 if currentActive ~= newActive then
|
flickerstreak@23
|
615 self:ToggleModuleActive(module)
|
flickerstreak@23
|
616 if not self.db.raw.disabledModules then
|
flickerstreak@23
|
617 self.db.raw.disabledModules = {}
|
flickerstreak@23
|
618 end
|
flickerstreak@23
|
619 if not self.db.raw.disabledModules[currentProfile] then
|
flickerstreak@23
|
620 self.db.raw.disabledModules[currentProfile] = {}
|
flickerstreak@23
|
621 end
|
flickerstreak@23
|
622 self.db.raw.disabledModules[currentProfile][module.name] = not currentActive or nil
|
flickerstreak@23
|
623 end
|
flickerstreak@23
|
624 end
|
flickerstreak@23
|
625 end
|
flickerstreak@23
|
626 end
|
flickerstreak@23
|
627
|
flickerstreak@23
|
628 -- #NODOC
|
flickerstreak@23
|
629 function AceModuleCore:Ace2_AddonEnabled(module, first)
|
flickerstreak@23
|
630 local addon = self.totalModules[module]
|
flickerstreak@23
|
631 if not addon then
|
flickerstreak@23
|
632 return
|
flickerstreak@23
|
633 end
|
flickerstreak@23
|
634
|
flickerstreak@23
|
635 if modulesWithMethod[addon] then
|
flickerstreak@23
|
636 for k,v in pairs(modulesWithMethod[addon]) do
|
flickerstreak@23
|
637 modulesWithMethod[addon] = del(v)
|
flickerstreak@23
|
638 end
|
flickerstreak@23
|
639 end
|
flickerstreak@23
|
640 if type(addon.OnModuleEnable) == "function" then
|
flickerstreak@23
|
641 safecall(addon.OnModuleEnable, addon, module, first)
|
flickerstreak@23
|
642 end
|
flickerstreak@23
|
643 end
|
flickerstreak@23
|
644
|
flickerstreak@23
|
645 -- #NODOC
|
flickerstreak@23
|
646 function AceModuleCore:Ace2_AddonDisabled(module)
|
flickerstreak@23
|
647 local addon = self.totalModules[module]
|
flickerstreak@23
|
648 if not addon then
|
flickerstreak@23
|
649 return
|
flickerstreak@23
|
650 end
|
flickerstreak@23
|
651
|
flickerstreak@23
|
652 if modulesWithMethod[addon] then
|
flickerstreak@23
|
653 for k,v in pairs(modulesWithMethod[addon]) do
|
flickerstreak@23
|
654 modulesWithMethod[addon] = del(v)
|
flickerstreak@23
|
655 end
|
flickerstreak@23
|
656 end
|
flickerstreak@23
|
657 if type(addon.OnModuleDisable) == "function" then
|
flickerstreak@23
|
658 safecall(addon.OnModuleDisable, addon, module)
|
flickerstreak@23
|
659 end
|
flickerstreak@23
|
660 end
|
flickerstreak@23
|
661
|
flickerstreak@23
|
662 local function activate(self, oldLib, oldDeactivate)
|
flickerstreak@23
|
663 AceModuleCore = self
|
flickerstreak@23
|
664
|
flickerstreak@23
|
665 self.totalModules = oldLib and oldLib.totalModules or {}
|
flickerstreak@23
|
666
|
flickerstreak@23
|
667 self:activate(oldLib, oldDeactivate)
|
flickerstreak@23
|
668
|
flickerstreak@23
|
669 if oldDeactivate then
|
flickerstreak@23
|
670 oldDeactivate(oldLib)
|
flickerstreak@23
|
671 end
|
flickerstreak@23
|
672 end
|
flickerstreak@23
|
673
|
flickerstreak@23
|
674 local function external(self, major, instance)
|
flickerstreak@23
|
675 if major == "AceEvent-2.0" then
|
flickerstreak@23
|
676 AceEvent = instance
|
flickerstreak@23
|
677 AceEvent:embed(self)
|
flickerstreak@23
|
678
|
flickerstreak@23
|
679 self:UnregisterAllEvents()
|
flickerstreak@23
|
680 self:RegisterEvent("Ace2_AddonEnabled")
|
flickerstreak@23
|
681 self:RegisterEvent("Ace2_AddonDisabled")
|
flickerstreak@23
|
682 elseif major == "AceAddon-2.0" then
|
flickerstreak@23
|
683 AceAddon = instance
|
flickerstreak@23
|
684 end
|
flickerstreak@23
|
685 end
|
flickerstreak@23
|
686
|
flickerstreak@23
|
687 AceLibrary:Register(AceModuleCore, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)
|
flickerstreak@23
|
688 AceModuleCore = AceLibrary(MAJOR_VERSION)
|