annotate DependencyLoader_Core/Core.lua @ 0:9852fcd5e59e

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