Mercurial > wow > dependencyloader
comparison DependencyLoader_Core/Tree.lua @ 8:930871e163bc
created a new Tree class and started rearranging code
author | mckenziemc |
---|---|
date | Sat, 04 Dec 2010 23:05:34 -0800 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
7:f4ab9d7b97b0 | 8:930871e163bc |
---|---|
1 -- Tree | |
2 -- Represents a recursive "tree" of addon | |
3 -- dependencies rooted at a specific addon. | |
4 | |
5 | |
6 local addonName, addonTable = ... | |
7 | |
8 | |
9 -- TODO: prevent infinite loops in the recursive functions | |
10 | |
11 | |
12 local Tree, tree = addonTable:NewClass("Tree") | |
13 | |
14 | |
15 Tree.trees = {} | |
16 | |
17 -- internal | |
18 -- Creates a new tree object | |
19 -- @param root Name, index, or Addon object of the root addon. | |
20 function Tree:New(root) | |
21 if type(root) ~= "table" then | |
22 root = addonTable.classes.Addon:Get(root) | |
23 end | |
24 | |
25 local instance = {} | |
26 setmetatable(instance, self.instanceMetatable) | |
27 | |
28 instance.root = root | |
29 | |
30 return instance | |
31 end | |
32 | |
33 | |
34 --- Retrieves the tree rooted at the specified addon | |
35 -- @param root Name, index, or Addon object of the root. | |
36 function Tree:Get(root) | |
37 if type(root) ~= "table" then | |
38 root = addonTable.classes.Addon:Get(root) | |
39 end | |
40 | |
41 local tree = self.trees[root] | |
42 | |
43 if tree then | |
44 return tree | |
45 else | |
46 tree = self:New(root) | |
47 self.trees[root] = tree | |
48 return tree | |
49 end | |
50 end | |
51 | |
52 | |
53 function tree:GetLoadBitfield() | |
54 local bitfield = self.root:GetLoadBitfield() | |
55 | |
56 local dependencies = {self.root:GetDependencies()} | |
57 for i, depName in pairs(dependencies) do | |
58 local depTree = Tree:Get(depName) | |
59 | |
60 if depTree == nil then | |
61 return 0 | |
62 end | |
63 | |
64 bitfield = bit.band(bitfield, depTree:GetLoadBitfield()) | |
65 end | |
66 | |
67 return bitfield | |
68 end | |
69 | |
70 | |
71 -- Checks if the tree rooted at the specified addon can be force-loaded. | |
72 -- @param root The name or index of the root addon. | |
73 function core:CanForceLoadTree(root) | |
74 -- TODO: if some addons have already loaded, we have to check | |
75 -- forceafter for those and forcebefore for the others | |
76 return false | |
77 end | |
78 | |
79 | |
80 -- NOTE: any tree that can be loaded on demand is also eligible for force-loading | |
81 -- Checks if the tree rooted at the specified addon can be loaded on demand. | |
82 -- @param root The name or index of the root addon. | |
83 function core:CanLoDTree(root) | |
84 local bitfield = self:GetLoadBitfield() | |
85 root = self:GetAddon(root) | |
86 assert(root) | |
87 | |
88 -- since this will be used recursively, return true if | |
89 -- this is already loaded. | |
90 if root:IsLoaded() then | |
91 return true | |
92 end | |
93 | |
94 -- true if all dependencies are loaded or LoD | |
95 | |
96 if not root:CanLoD() then | |
97 return false | |
98 end | |
99 | |
100 -- now check dependencies recursively | |
101 local dependencies = {root:GetDependencies()} | |
102 for i, depName in pairs(dependencies) do | |
103 local dep = self:GetAddon(depName) | |
104 | |
105 if not dep then | |
106 return false -- missing | |
107 end | |
108 | |
109 if not dep:IsLoaded() then | |
110 if not self:CanLoDTree(depName) then | |
111 return false | |
112 end | |
113 end | |
114 end | |
115 | |
116 return true | |
117 end | |
118 | |
119 | |
120 -- Checks if the tree rooted at the specified addon | |
121 -- can be loaded if all dependencies are enabled | |
122 -- the UI is reloaded. | |
123 -- Basically makes sure all dependencies are installed. | |
124 function core:CanReloadTree(root) | |
125 -- convert root to an Addon object | |
126 root = self:GetAddon(root) | |
127 assert(root) | |
128 | |
129 if root:IsLoaded() then | |
130 return true | |
131 -- FIXME: deps may have been disabled | |
132 end | |
133 | |
134 -- TODO: make sure the root isn't incompatible | |
135 | |
136 -- now check dependencies recursively | |
137 -- FIXME: prevent infinite recursion | |
138 | |
139 local dependencies = {root:GetDependencies()} | |
140 for i, depName in pairs(dependencies) do | |
141 local dep = self:GetAddon(depName) | |
142 | |
143 if dep == nil then | |
144 return false -- missing dependency | |
145 end | |
146 | |
147 -- TODO: make sure it's compatible | |
148 end | |
149 | |
150 return true | |
151 end | |
152 | |
153 -- Loads the tree rooted at the specified addon. | |
154 -- FIXME: load the root too or not? | |
155 -- Supports both LoD addons and those that require force-loading. | |
156 function core:LoadTree(addon) | |
157 -- don't check if the tree can actually be loaded. | |
158 -- external code should do that itself to check if it | |
159 -- should even call this at all. | |
160 | |
161 if self:ForceLoadAvailable() then | |
162 -- LoD trees can also be force-loaded | |
163 self:ForceLoadTree(addon) | |
164 else | |
165 self:LoadLoDTree(addon) | |
166 end | |
167 end | |
168 | |
169 | |
170 -- load the root too, since it may actually be a leaf | |
171 function core:ForceLoadTree(root) | |
172 root = self:GetAddon(root) | |
173 assert(root) | |
174 | |
175 -- load dependencies | |
176 local dependencies = {root:GetDependencies(addon)} | |
177 for i, depName in pairs(dependencies) do | |
178 self:ForceLoadTree(depName) | |
179 end | |
180 | |
181 -- load embeds, if they are available separately | |
182 local embeds = {root:GetEmbeds(addon)} | |
183 for i, embedName in pairs(embeds) do | |
184 if Addon:Exists(embedName) then | |
185 self:ForceLoadTree(embedName) | |
186 end | |
187 end | |
188 | |
189 root:ForceLoad() | |
190 end | |
191 | |
192 | |
193 function core:LoadLoDTree(root) | |
194 root = self:GetAddon(root) | |
195 assert(root) | |
196 | |
197 -- load dependencies | |
198 local dependencies = {root:GetDependencies(addon)} | |
199 for i, depName in pairs(dependencies) do | |
200 self:LoadLoDTree(depName) | |
201 end | |
202 | |
203 -- load embeds, if they are available separately | |
204 local embeds = {root:GetEmbeds(addon)} | |
205 for i, embedName in pairs(embeds) do | |
206 if Addon:Exists(embedName) then | |
207 self:LoadLoDTree(embedName) | |
208 end | |
209 end | |
210 | |
211 root:LoD() | |
212 end | |
213 | |
214 | |
215 -- I think the problem this solves is a major issue with | |
216 -- migrating to separate libs. think about it more and document | |
217 -- here and in project description | |
218 function core:PrepareLoDTree(root) | |
219 root = self:GetAddon(root) | |
220 assert(root) | |
221 | |
222 -- assume root is LoD | |
223 | |
224 -- check dependencies | |
225 local dependencies = {root:GetDependencies(addon)} | |
226 for i, depName in pairs(dependencies) do | |
227 local dep = self:GetAddon(depName) | |
228 | |
229 -- assume external code made sure it exists | |
230 | |
231 if dep:CanLoD() then | |
232 -- don't load it now but make sure its dependencies are prepared | |
233 self:PrepareLoDTree(depName) | |
234 else | |
235 -- FIXME: if it's already loaded | |
236 -- force-load it now so we can load the parent on demand | |
237 self:ForceLoadTree(depName) | |
238 end | |
239 end | |
240 | |
241 -- prepare embeds, if they are available separately | |
242 local embeds = {root:GetEmbeds(addon)} -- FIXME: addon? | |
243 for i, embedName in pairs(embeds) do | |
244 local embed = self:GetAddon(embedName) | |
245 | |
246 if embed then | |
247 if embed:CanLoD() then | |
248 -- don't load it now but make sure its dependencies are prepared | |
249 self:PrepareLoDTree(embedName) | |
250 else | |
251 -- FIXME: if it's already loaded | |
252 -- force-load it now so we can load the parent on demand | |
253 self:ForceLoadTree(depName) | |
254 end | |
255 end | |
256 end | |
257 end | |
258 | |
259 | |
260 function Core:PrepareReloadTree(addon) | |
261 root = self:GetAddon(root) | |
262 assert(root) | |
263 | |
264 root:Enable() | |
265 | |
266 -- check dependencies | |
267 local dependencies = {root:GetDependencies()} | |
268 for i, depName in pairs(dependencies) do | |
269 self:PrepareReloadTree(depName) | |
270 end | |
271 | |
272 -- prepare embeds, if they are available separately | |
273 local embeds = {root:GetEmbeds(addon)} | |
274 for i, embedName in pairs(embeds) do | |
275 local embed = self:GetAddon(embedName) | |
276 | |
277 if embed then | |
278 self:PrepareReloadTree(embedName) | |
279 end | |
280 end | |
281 end | |
282 | |
283 | |
284 function Core:ForceLoadAvailable() | |
285 return true | |
286 -- FIXME: use field and a frame registered for PLAYER_LOGIN | |
287 end |