flickerstreak@1
|
1 --[[
|
flickerstreak@1
|
2 Name: AceModuleCore-2.0
|
flickerstreak@1
|
3 Revision: $Rev: 18708 $
|
flickerstreak@1
|
4 Developed by: The Ace Development Team (http://www.wowace.com/index.php/The_Ace_Development_Team)
|
flickerstreak@1
|
5 Inspired By: Ace 1.x by Turan (turan@gryphon.com)
|
flickerstreak@1
|
6 Website: http://www.wowace.com/
|
flickerstreak@1
|
7 Documentation: http://www.wowace.com/index.php/AceModuleCore-2.0
|
flickerstreak@1
|
8 SVN: http://svn.wowace.com/root/trunk/Ace2/AceModuleCore-2.0
|
flickerstreak@1
|
9 Description: Mixin to provide a module system so that modules or plugins can
|
flickerstreak@1
|
10 use an addon as its core.
|
flickerstreak@1
|
11 Dependencies: AceLibrary, AceOO-2.0, AceAddon-2.0, AceEvent-2.0 (optional)
|
flickerstreak@1
|
12 ]]
|
flickerstreak@1
|
13
|
flickerstreak@1
|
14 local MAJOR_VERSION = "AceModuleCore-2.0"
|
flickerstreak@1
|
15 local MINOR_VERSION = "$Revision: 18708 $"
|
flickerstreak@1
|
16
|
flickerstreak@1
|
17 if not AceLibrary then error(MAJOR_VERSION .. " requires AceLibrary") end
|
flickerstreak@1
|
18 if not AceLibrary:IsNewVersion(MAJOR_VERSION, MINOR_VERSION) then return end
|
flickerstreak@1
|
19
|
flickerstreak@1
|
20 if not AceLibrary:HasInstance("AceOO-2.0") then error(MAJOR_VERSION .. " requires AceOO-2.0") end
|
flickerstreak@1
|
21
|
flickerstreak@1
|
22 local function safecall(func, ...)
|
flickerstreak@1
|
23 local success, err = pcall(func, ...)
|
flickerstreak@1
|
24 if not success then geterrorhandler()(err) end
|
flickerstreak@1
|
25 end
|
flickerstreak@1
|
26
|
flickerstreak@1
|
27 local AceEvent
|
flickerstreak@1
|
28 local AceOO = AceLibrary:GetInstance("AceOO-2.0")
|
flickerstreak@1
|
29 local AceModuleCore = AceOO.Mixin {
|
flickerstreak@1
|
30 "NewModule",
|
flickerstreak@1
|
31 "HasModule",
|
flickerstreak@1
|
32 "GetModule",
|
flickerstreak@1
|
33 "IsModule",
|
flickerstreak@1
|
34 "IterateModules",
|
flickerstreak@1
|
35 "SetModuleMixins",
|
flickerstreak@1
|
36 "SetModuleClass",
|
flickerstreak@1
|
37 "IsModuleActive",
|
flickerstreak@1
|
38 "ToggleModuleActive"
|
flickerstreak@1
|
39 }
|
flickerstreak@1
|
40
|
flickerstreak@1
|
41 local function getlibrary(lib)
|
flickerstreak@1
|
42 if type(lib) == "string" then
|
flickerstreak@1
|
43 return AceLibrary(lib)
|
flickerstreak@1
|
44 else
|
flickerstreak@1
|
45 return lib
|
flickerstreak@1
|
46 end
|
flickerstreak@1
|
47 end
|
flickerstreak@1
|
48
|
flickerstreak@1
|
49 local tmp = {}
|
flickerstreak@1
|
50 function AceModuleCore:NewModule(name, ...)
|
flickerstreak@1
|
51 if not self.modules then
|
flickerstreak@1
|
52 AceModuleCore:error("CreatePrototype() must be called before attempting to create a new module.", 2)
|
flickerstreak@1
|
53 end
|
flickerstreak@1
|
54 AceModuleCore:argCheck(name, 2, "string")
|
flickerstreak@1
|
55 if string.len(name) == 0 then
|
flickerstreak@1
|
56 AceModuleCore:error("Bad argument #2 to `NewModule`, string must not be empty")
|
flickerstreak@1
|
57 end
|
flickerstreak@1
|
58 if self.modules[name] then
|
flickerstreak@1
|
59 AceModuleCore:error("The module %q has already been registered", name)
|
flickerstreak@1
|
60 end
|
flickerstreak@1
|
61
|
flickerstreak@1
|
62 for i = 1, select('#', ...) do
|
flickerstreak@1
|
63 tmp[i] = getlibrary((select(i, ...)))
|
flickerstreak@1
|
64 end
|
flickerstreak@1
|
65
|
flickerstreak@1
|
66 if self.moduleMixins then
|
flickerstreak@1
|
67 for _,mixin in ipairs(self.moduleMixins) do
|
flickerstreak@1
|
68 local exists = false
|
flickerstreak@1
|
69 for _,v in ipairs(tmp) do
|
flickerstreak@1
|
70 if mixin == v then
|
flickerstreak@1
|
71 exists = true
|
flickerstreak@1
|
72 break
|
flickerstreak@1
|
73 end
|
flickerstreak@1
|
74 end
|
flickerstreak@1
|
75 if not exists then
|
flickerstreak@1
|
76 table.insert(tmp, mixin)
|
flickerstreak@1
|
77 end
|
flickerstreak@1
|
78 end
|
flickerstreak@1
|
79 end
|
flickerstreak@1
|
80
|
flickerstreak@1
|
81 local module = AceOO.Classpool(self.moduleClass, unpack(tmp)):new(name)
|
flickerstreak@1
|
82 self.modules[name] = module
|
flickerstreak@1
|
83 module.name = name
|
flickerstreak@1
|
84 module.title = name
|
flickerstreak@1
|
85
|
flickerstreak@1
|
86 AceModuleCore.totalModules[module] = self
|
flickerstreak@1
|
87
|
flickerstreak@1
|
88 if AceEvent then
|
flickerstreak@1
|
89 AceEvent:TriggerEvent("Ace2_ModuleCreated", module)
|
flickerstreak@1
|
90 end
|
flickerstreak@1
|
91
|
flickerstreak@1
|
92 local num = #tmp
|
flickerstreak@1
|
93 for i = 1, num do
|
flickerstreak@1
|
94 tmp[i] = nil
|
flickerstreak@1
|
95 end
|
flickerstreak@1
|
96 return module
|
flickerstreak@1
|
97 end
|
flickerstreak@1
|
98
|
flickerstreak@1
|
99 function AceModuleCore:HasModule(...)
|
flickerstreak@1
|
100 for i = 1, select('#', ...) do
|
flickerstreak@1
|
101 if not self.modules[select(i, ...)] then
|
flickerstreak@1
|
102 return false
|
flickerstreak@1
|
103 end
|
flickerstreak@1
|
104 end
|
flickerstreak@1
|
105
|
flickerstreak@1
|
106 return true
|
flickerstreak@1
|
107 end
|
flickerstreak@1
|
108
|
flickerstreak@1
|
109 function AceModuleCore:GetModule(name)
|
flickerstreak@1
|
110 if not self.modules then
|
flickerstreak@1
|
111 AceModuleCore:error("Error initializing class. Please report error.")
|
flickerstreak@1
|
112 end
|
flickerstreak@1
|
113 if not self.modules[name] then
|
flickerstreak@1
|
114 AceModuleCore:error("Cannot find module %q.", name)
|
flickerstreak@1
|
115 end
|
flickerstreak@1
|
116 return self.modules[name]
|
flickerstreak@1
|
117 end
|
flickerstreak@1
|
118
|
flickerstreak@1
|
119 function AceModuleCore:IsModule(module)
|
flickerstreak@1
|
120 if self == AceModuleCore then
|
flickerstreak@1
|
121 return AceModuleCore.totalModules[module]
|
flickerstreak@1
|
122 else
|
flickerstreak@1
|
123 for k,v in pairs(self.modules) do
|
flickerstreak@1
|
124 if v == module then
|
flickerstreak@1
|
125 return true
|
flickerstreak@1
|
126 end
|
flickerstreak@1
|
127 end
|
flickerstreak@1
|
128 return false
|
flickerstreak@1
|
129 end
|
flickerstreak@1
|
130 end
|
flickerstreak@1
|
131
|
flickerstreak@1
|
132 function AceModuleCore:IterateModules()
|
flickerstreak@1
|
133 local t = {}
|
flickerstreak@1
|
134 for k in pairs(self.modules) do
|
flickerstreak@1
|
135 table.insert(t, k)
|
flickerstreak@1
|
136 end
|
flickerstreak@1
|
137 table.sort(t)
|
flickerstreak@1
|
138 local i = 0
|
flickerstreak@1
|
139 return function()
|
flickerstreak@1
|
140 i = i + 1
|
flickerstreak@1
|
141 local x = t[i]
|
flickerstreak@1
|
142 if x then
|
flickerstreak@1
|
143 return x, self.modules[x]
|
flickerstreak@1
|
144 else
|
flickerstreak@1
|
145 t = nil
|
flickerstreak@1
|
146 return nil
|
flickerstreak@1
|
147 end
|
flickerstreak@1
|
148 end, nil, nil
|
flickerstreak@1
|
149 end
|
flickerstreak@1
|
150
|
flickerstreak@1
|
151 function AceModuleCore:SetModuleMixins(...)
|
flickerstreak@1
|
152 if self.moduleMixins then
|
flickerstreak@1
|
153 AceModuleCore:error('Cannot call "SetModuleMixins" twice')
|
flickerstreak@1
|
154 elseif not self.modules then
|
flickerstreak@1
|
155 AceModuleCore:error("Error initializing class. Please report error.")
|
flickerstreak@1
|
156 elseif next(self.modules) then
|
flickerstreak@1
|
157 AceModuleCore:error('Cannot call "SetModuleMixins" after "NewModule" has been called.')
|
flickerstreak@1
|
158 end
|
flickerstreak@1
|
159
|
flickerstreak@1
|
160 self.moduleMixins = { ... }
|
flickerstreak@1
|
161 for i,v in ipairs(self.moduleMixins) do
|
flickerstreak@1
|
162 self.moduleMixins[i] = getlibrary(v)
|
flickerstreak@1
|
163 end
|
flickerstreak@1
|
164 end
|
flickerstreak@1
|
165
|
flickerstreak@1
|
166 function AceModuleCore:SetModuleClass(class)
|
flickerstreak@1
|
167 class = getlibrary(class)
|
flickerstreak@1
|
168 AceModuleCore:assert(AceOO.inherits(class, AceOO.Class), "Bad argument #2 to `SetModuleClass' (Class expected)")
|
flickerstreak@1
|
169 if not self.modules then
|
flickerstreak@1
|
170 AceModuleCore:error("Error initializing class. Please report error.")
|
flickerstreak@1
|
171 end
|
flickerstreak@1
|
172 if self.customModuleClass then
|
flickerstreak@1
|
173 AceModuleCore:error("Cannot call `SetModuleClass' twice.")
|
flickerstreak@1
|
174 end
|
flickerstreak@1
|
175 self.customModuleClass = true
|
flickerstreak@1
|
176 self.moduleClass = class
|
flickerstreak@1
|
177 self.modulePrototype = class.prototype
|
flickerstreak@1
|
178 end
|
flickerstreak@1
|
179
|
flickerstreak@1
|
180 function AceModuleCore:ToggleModuleActive(module, state)
|
flickerstreak@1
|
181 AceModuleCore:argCheck(module, 2, "table", "string")
|
flickerstreak@1
|
182 AceModuleCore:argCheck(state, 3, "nil", "boolean")
|
flickerstreak@1
|
183
|
flickerstreak@1
|
184 if type(module) == "string" then
|
flickerstreak@1
|
185 if not self:HasModule(module) then
|
flickerstreak@1
|
186 AceModuleCore:error("Cannot find module %q", module)
|
flickerstreak@1
|
187 end
|
flickerstreak@1
|
188 module = self:GetModule(module)
|
flickerstreak@1
|
189 else
|
flickerstreak@1
|
190 if not self:IsModule(module) then
|
flickerstreak@1
|
191 AceModuleCore:error("%q is not a module", module)
|
flickerstreak@1
|
192 end
|
flickerstreak@1
|
193 end
|
flickerstreak@1
|
194
|
flickerstreak@1
|
195 local disable
|
flickerstreak@1
|
196 if state == nil then
|
flickerstreak@1
|
197 disable = self:IsModuleActive(module)
|
flickerstreak@1
|
198 else
|
flickerstreak@1
|
199 disable = not state
|
flickerstreak@1
|
200 if disable ~= self:IsModuleActive(module) then
|
flickerstreak@1
|
201 return
|
flickerstreak@1
|
202 end
|
flickerstreak@1
|
203 end
|
flickerstreak@1
|
204
|
flickerstreak@1
|
205 if type(module.ToggleActive) == "function" then
|
flickerstreak@1
|
206 return module:ToggleActive(not disable)
|
flickerstreak@1
|
207 elseif AceOO.inherits(self, "AceDB-2.0") then
|
flickerstreak@1
|
208 if not self.db or not self.db.raw then
|
flickerstreak@1
|
209 AceModuleCore:error("Cannot toggle a module until `RegisterDB' has been called and `ADDON_LOADED' has been fired.")
|
flickerstreak@1
|
210 end
|
flickerstreak@1
|
211 if type(self.db.raw.disabledModules) ~= "table" then
|
flickerstreak@1
|
212 self.db.raw.disabledModules = {}
|
flickerstreak@1
|
213 end
|
flickerstreak@1
|
214 local _,profile = self:GetProfile()
|
flickerstreak@1
|
215 if type(self.db.raw.disabledModules[profile]) ~= "table" then
|
flickerstreak@1
|
216 self.db.raw.disabledModules[profile] = {}
|
flickerstreak@1
|
217 end
|
flickerstreak@1
|
218 if type(self.db.raw.disabledModules[profile][module.name]) ~= "table" then
|
flickerstreak@1
|
219 self.db.raw.disabledModules[profile][module.name] = disable or nil
|
flickerstreak@1
|
220 end
|
flickerstreak@1
|
221 if not disable then
|
flickerstreak@1
|
222 if not next(self.db.raw.disabledModules[profile]) then
|
flickerstreak@1
|
223 self.db.raw.disabledModules[profile] = nil
|
flickerstreak@1
|
224 end
|
flickerstreak@1
|
225 if not next(self.db.raw.disabledModules) then
|
flickerstreak@1
|
226 self.db.raw.disabledModules = nil
|
flickerstreak@1
|
227 end
|
flickerstreak@1
|
228 end
|
flickerstreak@1
|
229 else
|
flickerstreak@1
|
230 if type(self.disabledModules) ~= "table" then
|
flickerstreak@1
|
231 self.disabledModules = {}
|
flickerstreak@1
|
232 end
|
flickerstreak@1
|
233 self.disabledModules[module.name] = disable or nil
|
flickerstreak@1
|
234 end
|
flickerstreak@1
|
235 if AceOO.inherits(module, "AceAddon-2.0") then
|
flickerstreak@1
|
236 local AceAddon = AceLibrary("AceAddon-2.0")
|
flickerstreak@1
|
237 if not AceAddon.addonsStarted[module] then
|
flickerstreak@1
|
238 return
|
flickerstreak@1
|
239 end
|
flickerstreak@1
|
240 end
|
flickerstreak@1
|
241 if not disable then
|
flickerstreak@1
|
242 local current = module.class
|
flickerstreak@1
|
243 while true do
|
flickerstreak@1
|
244 if current == AceOO.Class then
|
flickerstreak@1
|
245 break
|
flickerstreak@1
|
246 end
|
flickerstreak@1
|
247 if current.mixins then
|
flickerstreak@1
|
248 for mixin in pairs(current.mixins) do
|
flickerstreak@1
|
249 if type(mixin.OnEmbedEnable) == "function" then
|
flickerstreak@1
|
250 safecall(mixin.OnEmbedEnable, mixin, module)
|
flickerstreak@1
|
251 end
|
flickerstreak@1
|
252 end
|
flickerstreak@1
|
253 end
|
flickerstreak@1
|
254 current = current.super
|
flickerstreak@1
|
255 end
|
flickerstreak@1
|
256 if type(module.OnEnable) == "function" then
|
flickerstreak@1
|
257 safecall(module.OnEnable, module)
|
flickerstreak@1
|
258 end
|
flickerstreak@1
|
259 if AceEvent then
|
flickerstreak@1
|
260 AceEvent:TriggerEvent("Ace2_AddonEnabled", module)
|
flickerstreak@1
|
261 end
|
flickerstreak@1
|
262 else
|
flickerstreak@1
|
263 local current = module.class
|
flickerstreak@1
|
264 while true do
|
flickerstreak@1
|
265 if current == AceOO.Class then
|
flickerstreak@1
|
266 break
|
flickerstreak@1
|
267 end
|
flickerstreak@1
|
268 if current.mixins then
|
flickerstreak@1
|
269 for mixin in pairs(current.mixins) do
|
flickerstreak@1
|
270 if type(mixin.OnEmbedDisable) == "function" then
|
flickerstreak@1
|
271 safecall(mixin.OnEmbedDisable, mixin, module)
|
flickerstreak@1
|
272 end
|
flickerstreak@1
|
273 end
|
flickerstreak@1
|
274 end
|
flickerstreak@1
|
275 current = current.super
|
flickerstreak@1
|
276 end
|
flickerstreak@1
|
277 if type(module.OnDisable) == "function" then
|
flickerstreak@1
|
278 safecall(module.OnDisable, module)
|
flickerstreak@1
|
279 end
|
flickerstreak@1
|
280 if AceEvent then
|
flickerstreak@1
|
281 AceEvent:TriggerEvent("Ace2_AddonDisabled", module)
|
flickerstreak@1
|
282 end
|
flickerstreak@1
|
283 end
|
flickerstreak@1
|
284 return not disable
|
flickerstreak@1
|
285 end
|
flickerstreak@1
|
286
|
flickerstreak@1
|
287 function AceModuleCore:IsModuleActive(module)
|
flickerstreak@1
|
288 AceModuleCore:argCheck(module, 2, "table", "string")
|
flickerstreak@1
|
289
|
flickerstreak@1
|
290 if AceModuleCore == self then
|
flickerstreak@1
|
291 self:argCheck(module, 2, "table")
|
flickerstreak@1
|
292
|
flickerstreak@1
|
293 local core = AceModuleCore.totalModules[module]
|
flickerstreak@1
|
294 if not core then
|
flickerstreak@1
|
295 self:error("Bad argument #2 to `IsModuleActive'. Not a module")
|
flickerstreak@1
|
296 end
|
flickerstreak@1
|
297 return core:IsModuleActive(module)
|
flickerstreak@1
|
298 end
|
flickerstreak@1
|
299
|
flickerstreak@1
|
300 if type(module) == "string" then
|
flickerstreak@1
|
301 if not self:HasModule(module) then
|
flickerstreak@1
|
302 AceModuleCore:error("Cannot find module %q", module)
|
flickerstreak@1
|
303 end
|
flickerstreak@1
|
304 module = self:GetModule(module)
|
flickerstreak@1
|
305 else
|
flickerstreak@1
|
306 if not self:IsModule(module) then
|
flickerstreak@1
|
307 AceModuleCore:error("%q is not a module", module)
|
flickerstreak@1
|
308 end
|
flickerstreak@1
|
309 end
|
flickerstreak@1
|
310
|
flickerstreak@1
|
311 if type(module.IsActive) == "function" then
|
flickerstreak@1
|
312 return module:IsActive()
|
flickerstreak@1
|
313 elseif AceOO.inherits(self, "AceDB-2.0") then
|
flickerstreak@1
|
314 local _,profile = self:GetProfile()
|
flickerstreak@1
|
315 return not self.db or not self.db.raw or not self.db.raw.disabledModules or not self.db.raw.disabledModules[profile] or not self.db.raw.disabledModules[profile][module.name]
|
flickerstreak@1
|
316 else
|
flickerstreak@1
|
317 return not self.disabledModules or not self.disabledModules[module.name]
|
flickerstreak@1
|
318 end
|
flickerstreak@1
|
319 end
|
flickerstreak@1
|
320
|
flickerstreak@1
|
321 function AceModuleCore:OnInstanceInit(target)
|
flickerstreak@1
|
322 if target.modules then
|
flickerstreak@1
|
323 AceModuleCore:error("OnInstanceInit cannot be called twice")
|
flickerstreak@1
|
324 end
|
flickerstreak@1
|
325 target.modules = {}
|
flickerstreak@1
|
326
|
flickerstreak@1
|
327 target.moduleClass = AceOO.Class("AceAddon-2.0")
|
flickerstreak@1
|
328 target.modulePrototype = target.moduleClass.prototype
|
flickerstreak@1
|
329 end
|
flickerstreak@1
|
330
|
flickerstreak@1
|
331 AceModuleCore.OnManualEmbed = AceModuleCore.OnInstanceInit
|
flickerstreak@1
|
332
|
flickerstreak@1
|
333 function AceModuleCore.OnEmbedProfileDisable(AceModuleCore, self, newProfile)
|
flickerstreak@1
|
334 if not AceOO.inherits(self, "AceDB-2.0") then
|
flickerstreak@1
|
335 return
|
flickerstreak@1
|
336 end
|
flickerstreak@1
|
337 local _,currentProfile = self:GetProfile()
|
flickerstreak@1
|
338 for k, module in pairs(self.modules) do
|
flickerstreak@1
|
339 if type(module.IsActive) == "function" or type(module.ToggleActive) == "function" then
|
flickerstreak@1
|
340 -- continue
|
flickerstreak@1
|
341 else
|
flickerstreak@1
|
342 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@1
|
343 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@1
|
344 if currentActive ~= newActive then
|
flickerstreak@1
|
345 self:ToggleModuleActive(module)
|
flickerstreak@1
|
346 if not self.db.raw.disabledModules then
|
flickerstreak@1
|
347 self.db.raw.disabledModules = {}
|
flickerstreak@1
|
348 end
|
flickerstreak@1
|
349 if not self.db.raw.disabledModules[currentProfile] then
|
flickerstreak@1
|
350 self.db.raw.disabledModules[currentProfile] = {}
|
flickerstreak@1
|
351 end
|
flickerstreak@1
|
352 self.db.raw.disabledModules[currentProfile][module.name] = not currentActive or nil
|
flickerstreak@1
|
353 end
|
flickerstreak@1
|
354 end
|
flickerstreak@1
|
355 end
|
flickerstreak@1
|
356 end
|
flickerstreak@1
|
357
|
flickerstreak@1
|
358 local function activate(self, oldLib, oldDeactivate)
|
flickerstreak@1
|
359 AceModuleCore = self
|
flickerstreak@1
|
360
|
flickerstreak@1
|
361 self.totalModules = oldLib and oldLib.totalModules or {}
|
flickerstreak@1
|
362
|
flickerstreak@1
|
363 self:activate(oldLib, oldDeactivate)
|
flickerstreak@1
|
364
|
flickerstreak@1
|
365 if oldDeactivate then
|
flickerstreak@1
|
366 oldDeactivate(oldLib)
|
flickerstreak@1
|
367 end
|
flickerstreak@1
|
368 end
|
flickerstreak@1
|
369
|
flickerstreak@1
|
370 local function external(self, major, instance)
|
flickerstreak@1
|
371 if major == "AceEvent-2.0" then
|
flickerstreak@1
|
372 AceEvent = instance
|
flickerstreak@1
|
373 end
|
flickerstreak@1
|
374 end
|
flickerstreak@1
|
375
|
flickerstreak@1
|
376 AceLibrary:Register(AceModuleCore, MAJOR_VERSION, MINOR_VERSION, activate, nil, external)
|
flickerstreak@1
|
377 AceModuleCore = AceLibrary(MAJOR_VERSION)
|