diff DependencyLoader/DependencyLoader.lua @ 15:a46bf694050c

cleaned up Tree's methods a bit and improved documentation Addon:Exists will now return false for Blizzard addons (needs to be handled better) Addon.lua will now use the raw hooks from the interface module fixed the inverted returns from IsForceLoadAvailable EnableAddOn and LoadAddOn hooks will now skip the extra processing if the addon does not exist or is a Blizzard addon moved the EnableAddOn queing to the interface
author mckenziemc
date Sat, 11 Dec 2010 01:48:39 -0800
parents 78b28ebdc169
children
line wrap: on
line diff
--- a/DependencyLoader/DependencyLoader.lua	Fri Dec 10 05:29:22 2010 -0800
+++ b/DependencyLoader/DependencyLoader.lua	Sat Dec 11 01:48:39 2010 -0800
@@ -1,6 +1,7 @@
 --	DependencyLoader
 --	
 
+--	TODO: disable bootstrap if we load successfully?
 
 --	TODO: implement a feature to disable unneeded libraries when a parent 
 --	is disabled?
@@ -8,11 +9,13 @@
 local addonName, addonTable = ...
 
 
-local DependencyLoader = LibStub("AceAddon-3.0"):NewAddon(addonName, "AceHook-3.0")
+local DependencyLoader = LibStub("AceAddon-3.0"):NewAddon(addonName, "AceHook-3.0", "AceEvent-3.0")
 _G[addonName] = DependencyLoader
 
 addonTable.interface = DependencyLoader
 
+local classes = addonTable.classes
+
 
 local LibPrint = LibStub("LibPrint-1.0")
 local LibScriptLink = LibStub("LibScriptLink-1.0")
@@ -20,6 +23,8 @@
 DependencyLoader.printStream = LibPrint:NewStream("DependencyLoader", "DpLdr", print)
 DependencyLoader.debugStream = LibPrint:NewStream("DependencyLoader", "DpLdr", "mcm")
 
+DependencyLoader.queuedEnables = {}		--	addons queued to be enabled after PLAYER_LOGIN
+
 
 function DependencyLoader:Print(...)
 	self.printStream:Print(...)
@@ -38,6 +43,11 @@
 
 
 function DependencyLoader:OnEnable()
+	--	this may get called early so don't rely on 
+	--	it as an indicator for PLAYER_LOGIN
+	
+	self:RegisterEvent("PLAYER_LOGIN")
+	
 	self:RawHook("LoadAddOn", true)
 	self:RawHook("EnableAddOn", true)
 	
@@ -47,6 +57,13 @@
 end
 
 
+function DependencyLoader:PLAYER_LOGIN(...)
+	self:Debug(...)
+	
+	self:ProcessEnableQueue()
+end
+
+
 function DependencyLoader:OnDisable()
 	self:Print("Disabled", addonName)
 end
@@ -54,7 +71,11 @@
 
 --	Does not consider user settings or addon errata.
 function DependencyLoader:IsForceLoadAvailable()
-	return IsLoggedIn() and true or false
+	if IsLoggedIn() then
+		return false
+	else
+		return true
+	end
 end
 
 
@@ -75,7 +96,7 @@
 	local requestReload = false
 	
 	for i=1, GetNumAddOns() do
-		local addon = addonTable.classes.Addon:Get(i)
+		local addon = classes.Addon:Get(i)
 		
 		--	TODO: what if an addon was loaded but its deps were then disabled?
 		if addon:IsEnabled() and not addon:IsLoaded() then
@@ -92,65 +113,96 @@
 end
 
 
+--	FIXME: use pcall in EnableAddOn and LoadAddOn, so that if my part errors,  
+--	it can still use the unhooked version
+
 function DependencyLoader:EnableAddOn(...)
 	local id = ...
-	local addon = addonTable.classes.Addon:Get(id)
-	local tree = addonTable.classes.Tree:Get(addon)
 	
-	local requestReload = false
+	self:Debug("EnableAddOn", ...)
 	
-	if self:CanForceLoad() then
-		--	NOTE: if we can force-load, then will enabling LoD addons cause them to load too?
-		--	A: no, they will still wait for LoadAddOn
+	--	even though we know EnableAddOn can cause force-loading before PLAYER_LOGIN, 
+	--	DO NOT attempt to "fix" it: another addon that -does- know about 
+	--	the different behavior might call our hook.
+	
+	if classes.Addon:Exists(id) then
+		local addon = classes.Addon:Get(id)
+		local tree = classes.Tree:Get(addon)
 		
-		--	Can the addon be loaded on demand if force-loading is 
-		--	allowed for its dependencies
-		--	if so, enable all deps and force-load if nec.
-		--		deps will get enabled if all parents are lod, force-loaded
-		--		if any parent can't be loaded on demand
-		--	else
-		--	if the addon is not loadable on demand but the tree can be
-		--	force-loaded, then force-load it all
-		--		deps will all get loaded since req. for root to load
-		--	else
-		--	if it can be loaded with a reloadui then prepare after login
-		--	else
-		--	it can't be loaded, maybe tell the user
+		local requestReload = false
 		
-		if tree:CanLoDWithForce() then
-			tree:PrepareForLoD()
-		elseif tree:CanForceLoad() then
-			tree:ForceLoad()
-		elseif tree:CanLoad() then
-			tree:PrepareForReload()
-			requestReload = true
+		if self:CanForceLoad() then
+			--	NOTE: if we can force-load, then will enabling LoD addons cause them to load too?
+			--	A: no, they will still wait for LoadAddOn
+			
+			--	Can the addon be loaded on demand if force-loading is 
+			--	allowed for its dependencies
+			--	if so, enable all deps and force-load if nec.
+			--		deps will get enabled if all parents are lod, force-loaded
+			--		if any parent can't be loaded on demand
+			--	else
+			--	if the addon is not loadable on demand but the tree can be
+			--	force-loaded, then force-load it all
+			--		deps will all get loaded since req. for root to load
+			--	else
+			--	if it can be loaded with a reloadui then prepare after login
+			--	else
+			--	it can't be loaded, maybe tell the user
+			
+			if tree:CanForceLoad() then
+				if addon:CanLoD() then
+					tree:PrepareForLoD()
+				else
+					tree:ForceLoad()
+				end
+			elseif tree:CanLoad() then
+				tree:PrepareForLoad()
+				requestReload = true
+			else
+				--	TODO: tell user
+			end
+			
+			
+			--[[
+			if tree:CanLoDWithForce() then
+				tree:PrepareForLoD()
+			elseif tree:CanForceLoad() then
+				tree:ForceLoad()
+			elseif tree:CanLoad() then
+				tree:PrepareForLoad()
+				requestReload = true
+			else
+				--	TODO: tell user
+			end
+			]]
 		else
-			--	TODO: tell user
+			--	if it can be loaded on demand (deps are loaded or LoD) then
+			--	prepare it (enable all deps)
+			--	else
+			--	if it can be loaded (and isn't already) then
+			--		if force loading is available, we have to wait, then enable everything
+			--		else
+			--		prepare for reload (TODO: move this check and similar to PLAYER_LOGOUT)
+			--	else
+			--	can't be loaded, maybe tell the user
+			
+			if tree:CanLoD() then
+				tree:PrepareForLoad()
+				--	don't actually intend to reload, just enable everything
+			elseif tree:CanLoad() then
+				tree:PrepareForLoad()
+				requestReload = true
+			else
+				--	TODO: tell user
+			end
 		end
-	else
-		--	if it can be loaded on demand (deps are loaded or LoD) then
-		--	prepare it (enable all deps)
-		--	else
-		--	if it can be loaded (and isn't already) then
-		--		if force loading is available, we have to wait, then enable everything
-		--		else
-		--		prepare for reload (TODO: move this check and similar to PLAYER_LOGOUT)
-		--	else
-		--	can't be loaded, maybe tell the user
 		
-		if tree:CanLoD() then
-			tree:PrepareForReload()
-			--	don't actually intend to reload, just enable everything
-		elseif tree:CanLoad() then
-			tree:PrepareForReload()
-			requestReload = true
-		else
-			--	TODO: tell user
+		if requestReload then
+			self:RequestReload()
 		end
 	end
 	
-	--	TODO: requestReload
-	
+	--	propogate the call even if it doesn't exist or deps are unavailable
 	return self.hooks.EnableAddOn(...)
 end
 
@@ -160,16 +212,11 @@
 function DependencyLoader:LoadAddOn(...)
 	local id = ...
 	
-	local isBlizzardAddon = false
+	self:Debug("LoadAddOn", ...)
 	
-	if type(id) == "string" and string.match(id, "Blizzard_") then
-		self:Debug("Asked to load Blizzard addon", id, ", skipping")
-		isBlizzardAddon = true
-	end
-	
-	if not isBlizzardAddon then
-		local addon = addonTable.classes.Addon:Get(id)
-		local tree = addonTable.classes.Tree:Get(addon)
+	if classes.Addon:Exists(id) then
+		local addon = classes.Addon:Get(id)
+		local tree = classes.Tree:Get(addon)
 		
 		if tree:CanLoD() then
 			tree:PrepareForLoD()
@@ -181,3 +228,31 @@
 	--	call even if it can't be loaded so regular returns appear
 	return self.hooks.LoadAddOn(...)
 end
+
+
+function DependencyLoader:RequestReload()
+	--	TODO: this should only run once
+end
+
+
+function DependencyLoader:QueueEnable(name)
+	self.queuedEnables[name] = true
+end
+
+
+function DependencyLoader:RawEnableAddOn(...)
+	return self.hooks.EnableAddOn(...)
+end
+
+
+function DependencyLoader:RawLoadAddOn(...)
+	return self.hooks.LoadAddOn(...)
+end
+
+
+function DependencyLoader:ProcessEnableQueue()
+	for addon in pairs(self.queuedEnables) do
+		self:RawEnableAddOn(addon)
+		self.queuedEnables[addon] = nil
+	end
+end