Mercurial > wow > dependencyloader
diff DependencyLoader_Core/Core.lua @ 0:9852fcd5e59e
initial import
author | mckenziemc |
---|---|
date | Tue, 30 Nov 2010 16:13:04 -0800 |
parents | |
children | 930871e163bc |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DependencyLoader_Core/Core.lua Tue Nov 30 16:13:04 2010 -0800 @@ -0,0 +1,298 @@ + + +local addonName, addonTable = ... + + +print("running Core.lua") + +-- TODO: prevent infinite loops in the recursive functions + + +local Core, core = addonTable:NewClass("Core") + +local Addon = addonTable.classes.Addon + +function Core:New() + local instance = {} + setmetatable(instance, self.instanceMetatable) + + instance.addons = {} + instance.nameToIndex = {} + + for i=1,GetNumAddOns() do + local newAddon = Addon:New(i) + + instance.addons[i] = newAddon + instance.nameToIndex[newAddon:GetName()] = i + end + + -- TODO: enable dependencies for any addons that have already loaded + + return instance +end + + +-- @param addon Name or index of the addon to retrieve. +-- @return The addon object, or nil if not found +function core:GetAddon(addon) + if not Addon:Exists(addon) then + return nil + end + + local index + + if type(addon) == "string" then + index = self.nameToIndex[addon] + elseif type(addon) == "number" then + index = addon + end + + return self.addons[index] +end + + +-- Checks if the tree rooted at the specified addon can be force-loaded. +-- @param root The name or index of the root addon. +function core:CanForceLoadTree(root) + -- convert root to an Addon object + root = self:GetAddon(root) + assert(root) + + if root:IsLoaded() then + return true + end + + -- check if the root itself can be force-loaded + if not root:CanForceLoad() then + return false + end + + -- now check dependencies recursively + -- FIXME: prevent infinite recursion + + local dependencies = {root:GetDependencies()} + for i, depName in pairs(dependencies) do + local dep = self:GetAddon(depName) + + if dep == nil then + return false -- missing dependency + end + + -- if it's already loaded then skip to next one + if not dep:IsLoaded() then + if not self:CanForceLoadTree(depName) then + return false + end + end + end + + return true +end + +-- NOTE: any tree that can be loaded on demand is also eligible for force-loading +-- Checks if the tree rooted at the specified addon can be loaded on demand. +-- @param root The name or index of the root addon. +function core:CanLoDTree(root) + root = self:GetAddon(root) + assert(root) + + -- since this will be used recursively, return true if + -- this is already loaded. + if root:IsLoaded() then + return true + end + + -- true if all dependencies are loaded or LoD + + if not root:CanLoD() then + return false + end + + -- now check dependencies recursively + local dependencies = {root:GetDependencies()} + for i, depName in pairs(dependencies) do + local dep = self:GetAddon(depName) + + if not dep then + return false -- missing + end + + if not dep:IsLoaded() then + if not self:CanLoDTree(depName) then + return false + end + end + end + + return true +end + + +-- Checks if the tree rooted at the specified addon +-- can be loaded if all dependencies are enabled +-- the UI is reloaded. +-- Basically makes sure all dependencies are installed. +function core:CanReloadTree(root) + -- convert root to an Addon object + root = self:GetAddon(root) + assert(root) + + if root:IsLoaded() then + return true + -- FIXME: deps may have been disabled + end + + -- TODO: make sure the root isn't incompatible + + -- now check dependencies recursively + -- FIXME: prevent infinite recursion + + local dependencies = {root:GetDependencies()} + for i, depName in pairs(dependencies) do + local dep = self:GetAddon(depName) + + if dep == nil then + return false -- missing dependency + end + + -- TODO: make sure it's compatible + end + + return true +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 core:LoadTree(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 + + +-- load the root too, since it may actually be a leaf +function core:ForceLoadTree(root) + root = self:GetAddon(root) + assert(root) + + -- load dependencies + local dependencies = {root:GetDependencies(addon)} + for i, depName in pairs(dependencies) do + self:ForceLoadTree(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:ForceLoadTree(embedName) + end + end + + root:ForceLoad() +end + + +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 + + +-- 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 core:PrepareLoDTree(root) + root = self:GetAddon(root) + assert(root) + + -- assume root is LoD + + -- check dependencies + local dependencies = {root:GetDependencies(addon)} + for i, depName in pairs(dependencies) do + local dep = self:GetAddon(depName) + + -- assume external code made sure it exists + + 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 = {root:GetEmbeds(addon)} -- FIXME: addon? + for i, embedName in pairs(embeds) do + local embed = self:GetAddon(embedName) + + 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 + + +function Core:PrepareReloadTree(addon) + root = self:GetAddon(root) + assert(root) + + root:Enable() + + -- check dependencies + local dependencies = {root:GetDependencies()} + for i, depName in pairs(dependencies) do + self:PrepareReloadTree(depName) + end + + -- prepare embeds, if they are available separately + local embeds = {root:GetEmbeds(addon)} + for i, embedName in pairs(embeds) do + local embed = self:GetAddon(embedName) + + if embed then + self:PrepareReloadTree(embedName) + end + end +end + + +function Core:ForceLoadAvailable() + return true + -- FIXME: use field and a frame registered for PLAYER_LOGIN +end