Mercurial > wow > dependencyloader
view DependencyLoader/Tree.lua @ 13:110baf84e7a8
fixed the LibPrint external in .pkgmeta (maybe)
author | mckenziemc |
---|---|
date | Fri, 10 Dec 2010 04:33:30 -0800 |
parents | b230b94d4487 |
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 ]]