Mercurial > wow > dependencyloader
view DependencyLoader/Tree.lua @ 12:b230b94d4487
fixed Addon.lua to use the unhooked EnableAddOn (still needs to be changed to grab from the interface)
improved the error message when creating an Addon object on a Blizzard addon (will add direct support later)
implemented the hooks on EnableAddOn and LoadAddOn
rearranged functions inside Tree.lua, with some edits
copied OptDeps from main module to the bootstrap module, to delegate loading to the client when possible
author | mckenziemc |
---|---|
date | Fri, 10 Dec 2010 00:21:17 -0800 |
parents | e0a4a8b5b389 |
children | a46bf694050c |
line wrap: on
line source
-- Tree -- Represents a recursive "tree" of addon -- dependencies rooted at a specific addon. local addonName, addonTable = ... -- FIXME: prevent infinite loops in the recursive functions local Tree, tree = addonTable:NewClass("Tree") Tree.trees = {} -- internal -- Creates a new tree object -- @param root Name, index, or Addon object of the root addon. function Tree:New(root) if type(root) ~= "table" then root = addonTable.classes.Addon:Get(root) end local instance = {} setmetatable(instance, self.instanceMetatable) instance.root = root return instance end --- Retrieves the tree rooted at the specified addon -- @param root Name, index, or Addon object of the root. function Tree:Get(root) if type(root) ~= "table" then root = addonTable.classes.Addon:Get(root) end local tree = self.trees[root] if tree then return tree else tree = self:New(root) self.trees[root] = tree return tree end end -- Checks if the tree rooted at the specified addon -- can be loaded if all dependencies are enabled -- and the UI is reloaded. -- Basically makes sure all dependencies are installed. function tree:CanLoad() if not self.root:CanLoad() then return false end -- check all the dependencies local dependencies = {self.root:GetDependencies()} for i, depName in pairs(dependencies) do local dep = addonTable.classes.Addon:Get(depName) if not dep:CanLoad() then return false end local depTree = Tree:Get(depName) if not depTree:CanLoad() then return false -- missing dependency end end return true end --- Checks if the tree can be loaded on demand. -- Does not consider force-loading; dependencies must -- be enabled and LoD, or loaded function tree:CanLoD() -- since this will be used recursively, return true if -- this is already loaded. if self.root:IsLoaded() then return true end -- true if all dependencies are loaded or LoD if not self.root:CanLoD() then return false end -- now check dependencies recursively local dependencies = {self.root:GetDependencies()} for i, depName in pairs(dependencies) do local depTree = Tree:Get(depName) if not depTree:CanLoD() then return false end end return true end --- Checks if this tree can be loaded on demand as long as -- force-loading is allowed for preparing dependencies. function tree:CanLoDWithForce() if not self.root:CanLoD() then return false end -- now check dependencies recursively local dependencies = {self.root:GetDependencies()} for i, depName in pairs(dependencies) do local dep = addonTable.classes.Addon:Get(depName) local depTree = Tree:Get(depName) if not dep:CanLoad() then return false end if dep:CanLoD() then if not depTree:CanLoDWithForce() then return false end elseif dep:CanForceLoad() then if not depTree:CanForceLoad() then return end end end return true end --- Checks if this tree can be force-loaded. -- Does not check user settings nor if force-loading is actually available. -- @return canForceLoad True if this tree can be force loaded, false otherwise function tree:CanForceLoad() -- TODO: remove redundencies (for now they're here for design flexibility) -- this addon must be loaded, able to load-on-demand, or able to force-load if self.root:IsLoaded() then return true end if not self.root:CanLoad() then return false end if not self.root:CanForceLoad() then return false end -- now check dependencies recursively local dependencies = {self.root:GetDependencies()} for i, depName in pairs(dependencies) do local dep = addonTable.classes.Addon:Get(depName) local depTree = Tree:Get(depName) if not dep:CanLoad() then return false end if not dep:CanLoD() and not dep:CanForceLoad() then return false end if not depTree:CanForceLoad() then return false end end return end --[[ -- Loads the tree rooted at the specified addon. -- FIXME: load the root too or not? -- Supports both LoD addons and those that require force-loading. function tree:Load(addon) -- don't check if the tree can actually be loaded. -- external code should do that itself to check if it -- should even call this at all. if self:ForceLoadAvailable() then -- LoD trees can also be force-loaded self:ForceLoadTree(addon) else self:LoadLoDTree(addon) end end ]] function tree:PrepareForReload() -- if force-loading is enabled then we have to queue this if the addon isn't lod local function callback() self.root:Enable() -- check dependencies local dependencies = {self.root:GetDependencies()} for i, depName in pairs(dependencies) do Tree:Get(depName):PrepareForReload() end -- prepare embeds, if they are available separately local embeds = {self.root:GetEmbeds(addon)} for i, embedName in pairs(embeds) do Tree:Get(embedName):PrepareForReload() end end if IsLoggedIn() then callback() else -- TODO: replace with cleaner alternative? local frame = CreateFrame("Frame") frame:SetScript("OnEvent", callback) frame:RegisterEvent("PLAYER_LOGIN") end end -- I think the problem this solves is a major issue with -- migrating to separate libs. think about it more and document -- here and in project description function tree:PrepareForLoD() -- assume root is LoD -- check dependencies local dependencies = {self.root:GetDependencies(addon)} for i, depName in pairs(dependencies) do local depTree = Tree:Get(depName) depTree:PrepareForLoD() --[[ if dep:CanLoD() then -- don't load it now but make sure its dependencies are prepared self:PrepareLoDTree(depName) else -- FIXME: if it's already loaded -- force-load it now so we can load the parent on demand self:ForceLoadTree(depName) end ]] end -- prepare embeds, if they are available separately local embeds = {self.root:GetEmbeds(addon)} -- FIXME: addon? for i, embedName in pairs(embeds) do local embedTree = Tree:Get(embedName) embedTree:PrepareForLoD() --[[ if embed then if embed:CanLoD() then -- don't load it now but make sure its dependencies are prepared self:PrepareLoDTree(embedName) else -- FIXME: if it's already loaded -- force-load it now so we can load the parent on demand self:ForceLoadTree(depName) end end ]] end end -- load the root too, since it may actually be a leaf function tree:ForceLoad() -- load dependencies local dependencies = {self.root:GetDependencies()} for i, depName in pairs(dependencies) do local depTree = Tree:Get(depName) depTree:ForceLoad() end -- load embeds, if they are available separately local embeds = {self.root:GetEmbeds()} for i, embedName in pairs(embeds) do local embedTree = Tree:Get(embedName) embedTree:ForceLoad() end root:ForceLoad() end --[[ don't think i need this function core:LoadLoDTree(root) root = self:GetAddon(root) assert(root) -- load dependencies local dependencies = {root:GetDependencies(addon)} for i, depName in pairs(dependencies) do self:LoadLoDTree(depName) end -- load embeds, if they are available separately local embeds = {root:GetEmbeds(addon)} for i, embedName in pairs(embeds) do if Addon:Exists(embedName) then self:LoadLoDTree(embedName) end end root:LoD() end ]]