changeset 99:966d06c8d9c9

- Brought plugin handling code up to date. SVs are kept in DB namespaces like they should have been. - Removed/commented all datarev code, until it becomes necessary after MoP. - Textgen special blocks for plugins do not automatically get a "reset&reload" button anymore. - New method to register option pages on the main tab. No sub-entry pages supported yet. Titles and reset&reload added here instead.
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Sun, 29 Jul 2012 23:12:18 +0000
parents b5a55c69ef67
children a57133ee3c9b
files core.lua gui.lua options.lua
diffstat 3 files changed, 202 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/core.lua	Fri Jul 27 19:09:29 2012 +0000
+++ b/core.lua	Sun Jul 29 23:12:18 2012 +0000
@@ -109,8 +109,8 @@
 ------ Constants
 local RAID_ROSTER_UPDATE_EVENT =
 	(select(4,GetBuildInfo()) >= 50000) and 'GROUP_ROSTER_UPDATE' or 'RAID_ROSTER_UPDATE'
-local option_defaults = {
-	['datarev'] = 20,    -- cheating, this isn't actually an option
+local option_defaults = { profile = {
+	--['datarev'] = 20,    -- cheating, this isn't actually an option
 	['popup_on_join'] = true,
 	['register_slash_synonyms'] = false,
 	['slash_synonyms'] = '/ol,/oloot',
@@ -137,7 +137,7 @@
 	['chatty_on_remote_changes_frame'] = 1,
 	['itemfilter'] = {},
 	['itemvault'] = {},
-}
+} }
 local virgin = "First time loaded?  Hi!  Use the /ouroloot command"
 	.." to show the main display.  You should probably browse the instructions"
 	.." if you've never used this before; %s to display the help window.  This"
@@ -154,6 +154,7 @@
 	..[[|cffffff00to see what can be done by software alone.  You may still]]
 	..[[ need to do a "/reload" afterwards, or even restart the game client.]]
 local unique_collision = "Item '%s' was carrying unique tag <%s>, but that was already in use; tried to generate a new tag and failed!|n|nRemote sender was '%s', previous cache entry was <%s/%s>.|n|nThis may require a live human to figure out; the loot in question has not been stored."
+local new_profile_warning = [[Be aware that profiles only store addon & plugin settings from the <Options> tab; loot and generated text is account-wide data, unrelated to your current profile.]]
 local remote_chatty = "|cff00ff00%s|r changed %d/%s from %s to %s"
 local qualnames = {
 	['gray'] = 0, ['grey'] = 0, ['poor'] = 0, ['trash'] = 0,
@@ -730,8 +731,10 @@
 	else
 		virgin = nil
 	end
-	self.db = _G.LibStub("AceDB-3.0"):New("OuroLootOptsDB",
-		{ profile = option_defaults } , --[[Default=]]true)
+	self.db = _G.LibStub("AceDB-3.0"):New("OuroLootOptsDB", option_defaults , --[[Default=]]true)
+	self.db.RegisterCallback (self, "OnNewProfile", function()
+		self:Print(new_profile_warning)
+	end)
 	self.db.RegisterCallback (self, "OnProfileChanged", "DBProfileRefresh")
 	self.db.RegisterCallback (self, "OnProfileCopied", "DBProfileRefresh")
 	self.db.RegisterCallback (self, "OnProfileReset", "DBProfileRefresh")
@@ -954,6 +957,15 @@
 --function addon:OnDisable() end
 
 do
+	--[[
+	Module support (aka plugins).  Field names with special meanings:
+	- option_defaults:  (IN) Standard AceDB-style table.  Use a profiles key!
+	- db:  (OUT) AceDB object, set during init.
+	- opts:  (OUT) Pointer to plugin's "db.profile" subtable.
+
+	OnInitialize, [default_]OnEnable, register_text_generator, register_tab_control
+	are all inherited.
+	]]
 	local prototype = {}
 	local registry
 
@@ -976,27 +988,35 @@
 		end
 	end
 
-	local function module_OnEnable (plugin)
+	local function module_OnInit (plugin)
 		if plugin.option_defaults then
-			local SVname = 'OuroLoot'..plugin:GetName()..'_opts'
-			if not _G[SVname] then
-				_G[SVname] = {}
-				if type(plugin.OnFirstTime) == 'function' then
-					plugin:OnFirstTime()
-				end
-			end
-			plugin.opts = _G[SVname]
-			for option,default in pairs(plugin.option_defaults) do
-				if plugin.opts[option] == nil then
-					plugin.opts[option] = default
-				end
-			end
-			plugin.option_defaults = nil
+			plugin.db = addon.db:RegisterNamespace (plugin.moduleName, plugin.option_defaults)
+			plugin.opts = plugin.db.profile
+			--plugin:SetEnabledState(plugin.db.profile.enabled)  if that flag is needed later
 		end
 	end
 
+	local function module_OnEnable (plugin)
+	end
+
+	local function module_GetOption (plugin, info)
+		local name = info[#info]
+		return plugin.db.profile[name]
+	end
+	local function module_SetOption (plugin, info, value)
+		local name = info[#info]
+		plugin.db.profile[name] = value
+		local arg = info.arg
+		if type(arg) == 'function' then
+			plugin[arg](plugin,info)
+		end
+	end
+
+	prototype.OnInitialize = module_OnInit
 	prototype.OnEnable = module_OnEnable
 	prototype.default_OnEnable = module_OnEnable
+	prototype.GetOption = module_GetOption
+	prototype.SetOption = module_SetOption
 
 	addon:SetDefaultModuleLibraries("AceConsole-3.0")
 	addon:SetDefaultModulePrototype(prototype)
@@ -1014,11 +1034,11 @@
 					"commrev "..self.commrev.." older than minimum "..mincomm)
 				return false
 			end
-			if mindata and tonumber(mindata) > opts.datarev then
+			--[[if mindata and tonumber(mindata) > opts.datarev then
 				self:Print(err,modname,
 					"datarev "..opts.datarev.." older than minimum "..mindata)
 				return false
-			end
+			end]]
 		end
 		return self:NewModule(modname)
 	end
--- a/gui.lua	Fri Jul 27 19:09:29 2012 +0000
+++ b/gui.lua	Sun Jul 29 23:12:18 2012 +0000
@@ -1537,17 +1537,6 @@
 		return addon:redisplay()
 	end)
 	specials:AddChild(w)
-	if addon:get_plugin(text_kind) then
-		local pname = addon:get_plugin(text_kind):GetName()
-		w = mkbutton("Reset SVs & ReloadUI",
-			([[<DEBUG:> Reset savedvariables for %s plugin back to defaults, and trigger a UI reload.]]):format(pname))
-		w:SetFullWidth(true)
-		w:SetCallback("OnClick", function(_w)
-			_G['OuroLoot'..pname..'_opts'] = nil
-			ReloadUI()
-		end)
-		specials:AddChild(w)
-	end
 	_populate_text_specials (box, specials, mkbutton, text_kind)
 end
 
--- a/options.lua	Fri Jul 27 19:09:29 2012 +0000
+++ b/options.lua	Sun Jul 29 23:12:18 2012 +0000
@@ -23,9 +23,9 @@
 
 -- Mark these as straight to guild vault:
 addon.default_itemvault = {
-	[52078] = true, -- Chaos Orb
-	[69237] = true, -- Living Ember
-	[71998] = true, -- Essence of Destruction
+	[52078] = true, -- Chaos Orb  (Cata heroics)
+	[69237] = true, -- Living Ember  (Cata Firelands)
+	[71998] = true, -- Essence of Destruction  (Cata Dragon Soul)
 }
 
 local options_tree = {
@@ -35,7 +35,7 @@
 	},
 	{
 		value = "basic",
-		text = "Options",
+		text = "Main Options",
 		children = {
 			{
 				value = "filter",
@@ -47,6 +47,7 @@
 			},
 		},
 	},
+	'NEW INSERTIONS HERE',  -- commenting this puts them all at the bottom
 	{
 		value = "adv",
 		text = "Advanced/Debugging",
@@ -65,6 +66,8 @@
 local flib = LibStub("LibFarmbuyer")
 local opts   
 
+local error, assert = addon.error, addon.assert
+
 local function mktoggle (opt, label, width, desc, opt_func)
 	local w = mkbutton("CheckBoxSmallLabel", nil, "", desc)
 	w:SetRelativeWidth(width)
@@ -683,7 +686,7 @@
 do
 	local funkified = {}
 	for key,f in pairs(controls) do
-		-- this is how TreeGroup makes unique keys
+		-- this is how TreeGroup makes unique keys out of nested entries
 		local funkykey = key:gsub('_','\001')
 		funkified[funkykey] = { f }
 	end
@@ -701,7 +704,9 @@
 	preload = nil
 end
 
--- Clicking an entry on the left tree column.
+local aceconfig_list = {}
+
+-- Selecting an entry on the left tree column.
 local opt_OnGroupSelected_func = function (treeg,event,category)
 	opts = addon.db.profile
 	local catfuncs = controls[category]
@@ -709,23 +714,30 @@
 		addon:horrible_horrible_error(("Category '%s' has no handler function!"):format(category:gsub('\001','_')))
 	end
 	treeg:ReleaseChildren()
-	local sf = AceGUI:Create("ScrollFrame")
-	sf:SetStatusTable(status_for_scroll)
-	sf:SetLayout("Flow")
-	-- This forces the scrolling area to be bigger than the visible area; else
-	-- some of the text gets cut off without ever triggering the scrollbar.
-	sf.content:SetHeight(700)
-	for _,func in ipairs(catfuncs) do
-		if func(sf) then break end
-	end
-	treeg:AddChild(sf)
-	if treeg:GetUserData("options restore scroll") then
-		if status_for_scroll.scrollvalue then
-			sf:SetScroll(status_for_scroll.scrollvalue)
+	if aceconfig_list[category] then
+		-- aceconfigdialog makes too many assumptions about scrolling
+		for _,func in ipairs(catfuncs) do
+			if func(treeg,category) then break end
 		end
-		treeg:SetUserData("options restore scroll", false)
 	else
-		sf:SetScroll(0)
+		local sf = AceGUI:Create("ScrollFrame")
+		sf:SetStatusTable(status_for_scroll)
+		sf:SetLayout("Flow")
+		-- This forces the scrolling area to be bigger than the visible area; else
+		-- some of the text gets cut off without ever triggering the scrollbar.
+		sf.content:SetHeight(700)
+		for _,func in ipairs(catfuncs) do
+			if func(sf,category) then break end
+		end
+		treeg:AddChild(sf)
+		if treeg:GetUserData("options restore scroll") then
+			if status_for_scroll.scrollvalue then
+				sf:SetScroll(status_for_scroll.scrollvalue)
+			end
+			treeg:SetUserData("options restore scroll", false)
+		else
+			sf:SetScroll(0)
+		end
 	end
 end
 
@@ -775,4 +787,131 @@
 addon:register_tab_control_AT_END ("opt", [[Options]],
 	[[Options for fine-tuning behavior]], tabs_OGS)
 
+
+---------------
+-- Registering new options entries
+local insertion_index = #options_tree
+for i = #options_tree, 1, -1 do
+	if options_tree[i] == 'NEW INSERTIONS HERE' then
+		insertion_index = i
+		break
+	end
+end
+if insertion_index then
+	table.remove (options_tree, insertion_index)
+else
+	insertion_index = #options_tree + 1
+end
+
+
+--[[
+PLUGIN is the module table itself.
+PARENT is nil to register in the tree list directly.
+TEXT is either the text to display in the tree list, or nil to use the
+  moduleName field out of PLUGIN (not :GetName()).
+OPTIONS is either
+  I)  a function to call directly
+  II) an aceconfig-style options table
+
+(I) Will augment options.args.name with coloring/sizing, if it exists.
+    (Set options.args.name.name before registering.)  Will create it if not
+	present.
+
+(II)  Title added unconditionally.  Callback is
+        options (scrollframe_container, plugin, unique_code)
+	  where UNIQUE_CODE is what's used by the TreeGroup widget in identifying
+	  the "button" clicked in the lefthand tree list.
+
+Will append a reset button IFF an options database has been registered already.
+]]
+function addon:register_options_entry (plugin, parent, text, options)
+	-- if this changes at all, fix up plugin_reset_button accordingly
+	local code = plugin:GetName()
+	--if parent 
+
+	text = text or plugin.moduleName
+
+	local handler
+	local pdb = self.db:GetNamespace (plugin.moduleName, --[[silent=]]true)
+	if type(options) == 'table' then
+		-- AceConfig-style options table
+		aceconfig_list[code] = true
+		if not options.args.name then
+			options.args.name = {
+				name = plugin.moduleName,
+				type = 'description',
+			}
+		end
+		options.args.name.name = '|cff30adff' .. options.args.name.name .. '|r'
+		options.args.name.fontSize = 'large'
+		options.args.name.width = 'full'
+		options.args.name.cmdHidden = true
+		options.args.name.order = 1
+		if pdb then
+			options.args.INSERTED_SPACER = {
+				name = '',
+				type = 'description',
+				cmdHidden = true,
+				width = 'full',
+				order = 9000,
+			}
+			options.args.RESET = {
+				name = "Reset",
+				desc = ([[Reset settings for <%s> plugin back to defaults.  Shift-click to also trigger a UI reload.]]):format(plugin:GetName()),
+				type = 'execute',
+				func = function()
+					pdb:ResetProfile()
+					if IsShiftKeyDown() then ReloadUI() end
+				end,
+				order = 9001,
+			}
+		end
+		LibStub("AceConfig-3.0"):RegisterOptionsTable(plugin:GetName(), options)
+		handler = function (sf)
+			LibStub("AceConfigDialog-3.0"):Open (plugin:GetName(), sf)
+		end
+
+	elseif type(options) == 'function' then
+		-- AceGUI callback
+		if pdb then
+			handler = function (sf)
+				sf:AddChildren(mktitle(text))
+				local ret = options (sf, plugin, code)
+				local w = mkbutton("Reset",
+					([[Reset settings for <%s> plugin back to defaults.  Shift-click to also trigger a UI reload.]]):format(text))
+				w:SetRelativeWidth(0.3)
+				w:SetCallback("OnClick", function(_w)
+					pdb:ResetProfile()
+					if IsShiftKeyDown() then ReloadUI() end
+				end)
+				sf:AddChildren(spacer(10),w)
+				return ret
+			end
+		else
+			handler = function (sf)
+				sf:AddChildren(mktitle(text))
+				return options (sf, plugin, code)
+			end
+		end
+
+	else
+		error(("Error: 'options' parameter for plugin '%s' is neither table nor function"):format(plugin:GetName()))
+	end
+
+	if not controls[code] then
+		controls[code] = {}
+	end
+	table.insert (controls[code], handler)
+
+	table.insert (options_tree, insertion_index, {
+		value = code,
+		text = text,  -- maybe call markup on this?
+	})
+	insertion_index = insertion_index + 1
+	-- The treegroup will rescan options_tree (via RefreshTree) several times
+	-- before the player actually sees anything; no more work needs doing.
+	return -- something that can be used as 'parent'
+end
+
+
 -- vim:noet