comparison libs/AceModuleCore-2.0/AceModuleCore-2.0.lua @ 1:c11ca1d8ed91

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