vanilla-wow-addons – Blame information for rev 1

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