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