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