Mercurial > wow > dependencyloader
comparison DependencyLoader/Tree.lua @ 15:a46bf694050c
cleaned up Tree's methods a bit and improved documentation
Addon:Exists will now return false for Blizzard addons (needs to be handled better)
Addon.lua will now use the raw hooks from the interface module
fixed the inverted returns from IsForceLoadAvailable
EnableAddOn and LoadAddOn hooks will now skip the extra processing if the addon does not exist or is a Blizzard addon
moved the EnableAddOn queing to the interface
author | mckenziemc |
---|---|
date | Sat, 11 Dec 2010 01:48:39 -0800 |
parents | b230b94d4487 |
children | e7995d599184 |
comparison
equal
deleted
inserted
replaced
14:78b28ebdc169 | 15:a46bf694050c |
---|---|
10 | 10 |
11 | 11 |
12 local Tree, tree = addonTable:NewClass("Tree") | 12 local Tree, tree = addonTable:NewClass("Tree") |
13 | 13 |
14 | 14 |
15 local classes = addonTable.classes | |
16 | |
17 | |
15 Tree.trees = {} | 18 Tree.trees = {} |
16 | 19 |
17 | 20 |
18 -- internal | 21 --- (private) Creates a new tree object. |
19 -- Creates a new tree object | 22 -- Assumptions: root addon exists and is not a Blizzard addon. |
20 -- @param root Name, index, or Addon object of the root addon. | 23 -- @param root Name, index, or Addon object of the root addon. |
21 function Tree:New(root) | 24 function Tree:New(root) |
22 if type(root) ~= "table" then | 25 if type(root) ~= "table" then |
23 root = addonTable.classes.Addon:Get(root) | 26 root = classes.Addon:Get(root) |
24 end | 27 end |
25 | 28 |
26 local instance = {} | 29 local instance = {} |
27 setmetatable(instance, self.instanceMetatable) | 30 setmetatable(instance, self.instanceMetatable) |
28 | 31 |
31 return instance | 34 return instance |
32 end | 35 end |
33 | 36 |
34 | 37 |
35 --- Retrieves the tree rooted at the specified addon | 38 --- Retrieves the tree rooted at the specified addon |
39 -- Assumptions: root addon exists and is not a Blizzard addon | |
36 -- @param root Name, index, or Addon object of the root. | 40 -- @param root Name, index, or Addon object of the root. |
37 function Tree:Get(root) | 41 function Tree:Get(root) |
38 if type(root) ~= "table" then | 42 if type(root) ~= "table" then |
39 root = addonTable.classes.Addon:Get(root) | 43 root = classes.Addon:Get(root) |
40 end | 44 end |
41 | 45 |
42 local tree = self.trees[root] | 46 local tree = self.trees[root] |
43 | 47 |
44 if tree then | 48 if tree then |
49 return tree | 53 return tree |
50 end | 54 end |
51 end | 55 end |
52 | 56 |
53 | 57 |
54 -- Checks if the tree rooted at the specified addon | 58 -- NOTE: All tree:Can functions should check the root too. |
59 -- That way, the hooks don't have to do "if addon:Can_ and tree:Can_", | |
60 -- plus the tree can cache info that includes the capabilities of the | |
61 -- root addon. | |
62 | |
63 | |
64 --- Checks if the tree rooted at the specified addon | |
55 -- can be loaded if all dependencies are enabled | 65 -- can be loaded if all dependencies are enabled |
56 -- and the UI is reloaded. | 66 -- and the UI is reloaded. |
57 -- Basically makes sure all dependencies are installed. | 67 -- Basically makes sure all dependencies are installed. |
58 function tree:CanLoad() | 68 function tree:CanLoad() |
59 if not self.root:CanLoad() then | 69 local root = self.root |
70 | |
71 if root:IsLoaded() then | |
72 return true | |
73 end | |
74 | |
75 if not root:CanLoad() then | |
60 return false | 76 return false |
61 end | 77 end |
62 | 78 |
63 -- check all the dependencies | 79 -- check all the dependencies |
64 local dependencies = {self.root:GetDependencies()} | 80 local dependencies = {root:GetDependencies()} |
65 for i, depName in pairs(dependencies) do | 81 |
66 local dep = addonTable.classes.Addon:Get(depName) | 82 for i, depName in pairs(dependencies) do |
67 | 83 if not classes.Addon:Exists(depName) then |
68 if not dep:CanLoad() then | 84 return false |
69 return false | 85 end |
70 end | 86 |
71 | 87 local dep = classes.Addon:Get(depName) |
72 local depTree = Tree:Get(depName) | 88 local depTree = Tree:Get(dep) |
73 | 89 |
74 if not depTree:CanLoad() then | 90 if not depTree:CanLoad() then |
75 return false -- missing dependency | 91 return false |
76 end | 92 end |
77 end | 93 end |
78 | 94 |
79 return true | 95 return true |
80 end | 96 end |
81 | 97 |
82 | 98 |
83 --- Checks if the tree can be loaded on demand. | 99 --- Checks if the tree can be loaded on demand. |
84 -- Does not consider force-loading; dependencies must | 100 -- Does not allow for force-loading; dependencies must |
85 -- be enabled and LoD, or loaded | 101 -- already be loaded, or enabled and LoD. |
86 function tree:CanLoD() | 102 function tree:CanLoD() |
87 -- since this will be used recursively, return true if | 103 local root = self.root |
88 -- this is already loaded. | 104 |
89 if self.root:IsLoaded() then | 105 if root:IsLoaded() then |
90 return true | 106 return true |
91 end | 107 end |
92 | 108 |
93 -- true if all dependencies are loaded or LoD | 109 if not root:CanLoD() then |
94 | |
95 if not self.root:CanLoD() then | |
96 return false | 110 return false |
97 end | 111 end |
98 | 112 |
99 -- now check dependencies recursively | 113 -- now check dependencies recursively |
100 local dependencies = {self.root:GetDependencies()} | 114 local dependencies = {root:GetDependencies()} |
101 for i, depName in pairs(dependencies) do | 115 |
102 local depTree = Tree:Get(depName) | 116 for i, depName in pairs(dependencies) do |
117 if not classes.Addon:Exists(depName) then | |
118 return false | |
119 end | |
120 | |
121 local dep = classes.Addon:Get(depName) | |
122 local depTree = Tree:Get(dep) | |
103 | 123 |
104 if not depTree:CanLoD() then | 124 if not depTree:CanLoD() then |
105 return false | 125 return false |
106 end | 126 end |
107 end | 127 end |
108 | 128 |
109 return true | 129 return true |
110 end | 130 end |
111 | |
112 | |
113 --- Checks if this tree can be loaded on demand as long as | |
114 -- force-loading is allowed for preparing dependencies. | |
115 function tree:CanLoDWithForce() | |
116 if not self.root:CanLoD() then | |
117 return false | |
118 end | |
119 | |
120 -- now check dependencies recursively | |
121 local dependencies = {self.root:GetDependencies()} | |
122 for i, depName in pairs(dependencies) do | |
123 local dep = addonTable.classes.Addon:Get(depName) | |
124 local depTree = Tree:Get(depName) | |
125 | |
126 if not dep:CanLoad() then | |
127 return false | |
128 end | |
129 | |
130 if dep:CanLoD() then | |
131 if not depTree:CanLoDWithForce() then | |
132 return false | |
133 end | |
134 elseif dep:CanForceLoad() then | |
135 if not depTree:CanForceLoad() then | |
136 return | |
137 end | |
138 end | |
139 end | |
140 | |
141 return true | |
142 end | |
143 | |
144 | 131 |
145 | 132 |
146 --- Checks if this tree can be force-loaded. | 133 --- Checks if this tree can be force-loaded. |
147 -- Does not check user settings nor if force-loading is actually available. | 134 -- Does not check user settings nor if force-loading is actually available. |
148 -- @return canForceLoad True if this tree can be force loaded, false otherwise | 135 -- @return canForceLoad True if this tree can be force loaded, false otherwise |
149 function tree:CanForceLoad() | 136 function tree:CanForceLoad() |
137 local root = self.root | |
150 -- TODO: remove redundencies (for now they're here for design flexibility) | 138 -- TODO: remove redundencies (for now they're here for design flexibility) |
151 | 139 |
152 -- this addon must be loaded, able to load-on-demand, or able to force-load | 140 -- this addon must be loaded, able to load-on-demand, or able to force-load |
153 if self.root:IsLoaded() then | 141 if root:IsLoaded() then |
154 return true | 142 return true |
155 end | 143 end |
156 | 144 |
157 if not self.root:CanLoad() then | 145 if not root:CanForceLoad() then |
158 return false | 146 return false |
159 end | 147 end |
160 | 148 |
161 if not self.root:CanForceLoad() then | |
162 return false | |
163 end | |
164 | |
165 -- now check dependencies recursively | 149 -- now check dependencies recursively |
166 local dependencies = {self.root:GetDependencies()} | 150 local dependencies = {root:GetDependencies()} |
167 for i, depName in pairs(dependencies) do | 151 |
168 local dep = addonTable.classes.Addon:Get(depName) | 152 for i, depName in pairs(dependencies) do |
169 local depTree = Tree:Get(depName) | 153 if not classes.Addon:Exists(depName) then |
170 | 154 return false |
171 if not dep:CanLoad() then | 155 end |
172 return false | 156 |
173 end | 157 local dep = classes.Addon:Get(depName) |
174 | 158 local depTree = Tree:Get(dep) |
175 if not dep:CanLoD() and not dep:CanForceLoad() then | |
176 return false | |
177 end | |
178 | 159 |
179 if not depTree:CanForceLoad() then | 160 if not depTree:CanForceLoad() then |
180 return false | 161 return false |
181 end | 162 end |
182 end | 163 end |
183 | 164 |
184 return | 165 return true |
185 end | 166 end |
186 | 167 |
187 | 168 |
188 | 169 --- Prepares this tree to be loaded, whether through |
189 --[[ | 170 -- a ui reload or by loading on demand. |
190 -- Loads the tree rooted at the specified addon. | 171 -- Assumptions: CanLoad is true for this tree |
191 -- FIXME: load the root too or not? | 172 function tree:PrepareForLoad() |
192 -- Supports both LoD addons and those that require force-loading. | 173 local root = self.root |
193 function tree:Load(addon) | 174 |
194 -- don't check if the tree can actually be loaded. | 175 -- The Addon class will take care of delaying enables |
195 -- external code should do that itself to check if it | 176 -- till after PLAYER_LOGIN if necessary. |
196 -- should even call this at all. | 177 |
197 | 178 root:Enable() |
198 if self:ForceLoadAvailable() then | 179 |
199 -- LoD trees can also be force-loaded | 180 -- enable dependencies |
200 self:ForceLoadTree(addon) | 181 local dependencies = {root:GetDependencies()} |
201 else | 182 |
202 self:LoadLoDTree(addon) | 183 for i, depName in pairs(dependencies) do |
203 end | 184 Tree:Get(depName):PrepareForLoad() |
204 end | 185 end |
205 ]] | 186 |
206 | 187 -- prepare embeds, if they are available separately |
207 | 188 local embeds = {root:GetEmbeds(addon)} |
208 function tree:PrepareForReload() | 189 |
209 -- if force-loading is enabled then we have to queue this if the addon isn't lod | 190 for i, embedName in pairs(embeds) do |
210 local function callback() | 191 if classes.Addon:Exists(embedName) then |
211 self.root:Enable() | 192 Tree:Get(embedName):PrepareForLoad() |
212 | 193 end |
213 -- check dependencies | |
214 local dependencies = {self.root:GetDependencies()} | |
215 for i, depName in pairs(dependencies) do | |
216 Tree:Get(depName):PrepareForReload() | |
217 end | |
218 | |
219 -- prepare embeds, if they are available separately | |
220 local embeds = {self.root:GetEmbeds(addon)} | |
221 for i, embedName in pairs(embeds) do | |
222 Tree:Get(embedName):PrepareForReload() | |
223 end | |
224 end | |
225 | |
226 if IsLoggedIn() then | |
227 callback() | |
228 else | |
229 -- TODO: replace with cleaner alternative? | |
230 local frame = CreateFrame("Frame") | |
231 frame:SetScript("OnEvent", callback) | |
232 frame:RegisterEvent("PLAYER_LOGIN") | |
233 end | 194 end |
234 end | 195 end |
235 | 196 |
236 | 197 |
237 -- I think the problem this solves is a major issue with | 198 -- I think the problem this solves is a major issue with |
238 -- migrating to separate libs. think about it more and document | 199 -- migrating to separate libs. think about it more and document |
239 -- here and in project description | 200 -- here and in project description |
201 | |
202 --- Force-loads this addon tree. If a subtree can be loaded on | |
203 -- demand, this function will enable but not load the subtree. | |
204 -- Assumptions: the root addon should be force-loaded, not just enabled. | |
205 --function tree:ForceLoad() | |
206 | |
207 -- Assumptions: the root is loadable-on demand, and force-load is available. | |
208 -- and tree can be force-loaded | |
240 function tree:PrepareForLoD() | 209 function tree:PrepareForLoD() |
241 -- assume root is LoD | 210 local root = self.root |
242 | 211 |
243 -- check dependencies | 212 -- prepare dependencies first (for consistency) |
244 local dependencies = {self.root:GetDependencies(addon)} | 213 local dependencies = {root:GetDependencies()} |
245 for i, depName in pairs(dependencies) do | 214 |
246 local depTree = Tree:Get(depName) | 215 for i, depName in pairs(dependencies) do |
247 depTree:PrepareForLoD() | 216 local dep = classes.Addon:Get(depName) |
248 | 217 |
249 --[[ | 218 if not dep:IsLoaded() then |
250 if dep:CanLoD() then | 219 if dep:CanLoD() then |
251 -- don't load it now but make sure its dependencies are prepared | 220 -- don't load it now but make sure its dependencies are prepared |
252 self:PrepareLoDTree(depName) | 221 Tree:Get(dep):PrepareForLoD() |
253 else | 222 else |
254 -- FIXME: if it's already loaded | 223 -- Based on our assumption about the tree, this addon |
255 -- force-load it now so we can load the parent on demand | 224 -- should be able to force-load. |
256 self:ForceLoadTree(depName) | 225 -- force-load it now so we can load the parent on demand |
257 end | 226 Tree:Get(dep):ForceLoad() |
258 ]] | 227 end |
228 end | |
259 end | 229 end |
260 | 230 |
261 -- prepare embeds, if they are available separately | 231 -- prepare embeds, if they are available separately |
262 local embeds = {self.root:GetEmbeds(addon)} -- FIXME: addon? | 232 local embeds = {root:GetEmbeds()} |
233 | |
263 for i, embedName in pairs(embeds) do | 234 for i, embedName in pairs(embeds) do |
264 local embedTree = Tree:Get(embedName) | 235 if classes.Addon:Exists(embedName) then |
265 embedTree:PrepareForLoD() | 236 local embed = classes.Addon:Get(embedName) |
266 | 237 |
267 --[[ | 238 if not embed:IsLoaded() then |
268 if embed then | 239 if embed:CanLoD() then |
269 if embed:CanLoD() then | 240 Tree:Get(embed):PrepareForLoD() |
270 -- don't load it now but make sure its dependencies are prepared | 241 else |
271 self:PrepareLoDTree(embedName) | 242 Tree:Get(embed):ForceLoad() |
272 else | 243 end |
273 -- FIXME: if it's already loaded | |
274 -- force-load it now so we can load the parent on demand | |
275 self:ForceLoadTree(depName) | |
276 end | 244 end |
277 end | 245 end |
278 ]] | 246 end |
279 end | 247 |
280 end | 248 root:Enable() |
281 | 249 end |
282 | 250 |
283 -- load the root too, since it may actually be a leaf | 251 |
252 --- Force-loads this tree. | |
253 -- This will also load any LoD addons in the tree | |
284 function tree:ForceLoad() | 254 function tree:ForceLoad() |
255 local root = self.root | |
256 | |
257 -- FIXME: if already loaded | |
258 | |
285 -- load dependencies | 259 -- load dependencies |
286 local dependencies = {self.root:GetDependencies()} | 260 local dependencies = {root:GetDependencies()} |
287 for i, depName in pairs(dependencies) do | 261 |
288 local depTree = Tree:Get(depName) | 262 for i, depName in pairs(dependencies) do |
289 depTree:ForceLoad() | 263 Tree:Get(depName):ForceLoad() |
290 end | 264 end |
291 | 265 |
292 -- load embeds, if they are available separately | 266 -- load embeds, if they are available separately |
293 local embeds = {self.root:GetEmbeds()} | 267 local embeds = {root:GetEmbeds()} |
268 | |
294 for i, embedName in pairs(embeds) do | 269 for i, embedName in pairs(embeds) do |
295 local embedTree = Tree:Get(embedName) | 270 if classes.Addon:Exists(embedName) then |
296 embedTree:ForceLoad() | 271 Tree:Get(embedName):ForceLoad() |
272 end | |
297 end | 273 end |
298 | 274 |
299 root:ForceLoad() | 275 root:ForceLoad() |
300 end | 276 end |
301 | |
302 | |
303 --[[ don't think i need this | |
304 function core:LoadLoDTree(root) | |
305 root = self:GetAddon(root) | |
306 assert(root) | |
307 | |
308 -- load dependencies | |
309 local dependencies = {root:GetDependencies(addon)} | |
310 for i, depName in pairs(dependencies) do | |
311 self:LoadLoDTree(depName) | |
312 end | |
313 | |
314 -- load embeds, if they are available separately | |
315 local embeds = {root:GetEmbeds(addon)} | |
316 for i, embedName in pairs(embeds) do | |
317 if Addon:Exists(embedName) then | |
318 self:LoadLoDTree(embedName) | |
319 end | |
320 end | |
321 | |
322 root:LoD() | |
323 end | |
324 ]] | |
325 |