changeset 110:f93c1a93923b

Change how dropdown menus are built, and register "mark as" in the loot dropdowns.
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Wed, 08 Aug 2012 23:13:04 -0400
parents ce45011fab4c
children cfbaf001fd52
files core.lua gui.lua
diffstat 2 files changed, 211 insertions(+), 167 deletions(-) [+]
line wrap: on
line diff
--- a/core.lua	Wed Aug 08 14:43:26 2012 -0400
+++ b/core.lua	Wed Aug 08 23:13:04 2012 -0400
@@ -374,6 +374,7 @@
 local g_uniques			= nil   -- memoization of unique loot events
 local g_unique_replace	= nil
 local opts				= nil
+local g_gui				= nil
 
 local error				= addon.error
 local assert			= addon.assert
@@ -849,6 +850,7 @@
 	self:FINISH_SPECIAL_TABS()
 	_init(self)
 	self.dprint('flow', "version strings:", version_large, self.revision, self.status_text)
+	g_gui = self.gui_state_pointer
 	self.gui_state_pointer = nil
 	self.load_assert = nil
 	self.OnInitialize = nil   -- free up ALL the things!
@@ -974,6 +976,27 @@
 	g_LOOT_ITEM_SELF_MULTIPLE_ss = LOOT_ITEM_SELF_MULTIPLE:gsub('%.$','%%.'):gsub('%%s','(.+)'):gsub('x%%d','(x%%d+)')
 
 	--[[
+	Throw in the default disposition types.  This could be called during load
+	were it not for the need to talk to the GUI data (not set up yet).
+
+	Args:  code, rhex, ghex, bhex,
+		text_notes, opt_text_menu (uses notes if nil), opt_tooltip_txt,
+		can_reassign_p, do_history_p, from_notes_text_p
+	]]
+	local norm = self:_add_loot_disposition ('normal', "ff","ff","ff", "", "normal",
+		[[This is the default.  Selecting any 'Mark as <x>' action blanks out extra notes about who broadcast this entry, etc.]],
+		true, true, false)
+	self:_add_loot_disposition ('offspec', "c6","9b","6d", "offspec", nil, nil,
+		true, true, true)
+	self:_add_loot_disposition ('shard',   "a3","35","ee", "shard",
+		"disenchanted", nil, false, false, true)
+	-- suddenly changing localization mid-phrase is horky, change this to a submenu:
+	self:_add_loot_disposition ('gvault',  "33","ff","99", _G.GUILD_BANK:lower(),
+		nil, nil, false, false, true)
+	-- fix up the odd (!) standard case of having a nil disposition field
+	norm.arg2 = nil
+
+	--[[
 	Stick something in the Blizzard addons options list, where most users
 	will probably look these days.  Try to be conservative about needless
 	frame creation.
@@ -2589,23 +2612,24 @@
 	function addon:_iter_dispositions (attrib)
 		local r = {}
 		for code,disp in next, alldisps do
-			if disp.attrib then
+			if disp[attrib] then
 				r[code] = disp.text
 			end
 		end
 		return next, r
 	end
 
-	function addon:_add_loot_disposition (code, rhex, ghex, bhex, text,
-		can_reassign_p, do_history_p, from_notes_text_p
+	function addon:_add_loot_disposition (code, rhex, ghex, bhex, text_notes,
+		text_menu, tooltip_txt, can_reassign_p, do_history_p, from_notes_text_p
 	)
 		assert(type(code)=='string' and #code>0)
-		assert(type(text)=='string')
+		assert(type(text_notes)=='string')
 		assert(type(rhex)=='string')
 		assert(type(bhex)=='string')
 		assert(type(ghex)=='string')
+
 		self.disposition_colors[code] = {
-			text = text,
+			text = text_notes,
 			-- for chat output by core code
 			hex = "|cff" .. rhex .. ghex .. bhex,
 			-- for lib-st
@@ -2617,18 +2641,15 @@
 		-- not not = poor man's "toboolean", don't potentially hold arg
 		-- objects from garbage collection
 		alldisps[code] = {
-			text = text,
+			text = text_notes,
 			can_reassign = not not can_reassign_p,
 			affects_history = not not do_history_p,
 			from_notes_text = not not from_notes_text_p,
 		}
+
+		return g_gui.add_dropdown_entry ('eoi_loot', "Mark as "..(text_menu or text_notes),
+			--[[function_table=]]nil, 'df_DISPOSITION', code, tooltip_txt)
 	end
-
-	-- reassign while tagged, affects history, copy from notes
-	addon:_add_loot_disposition ('normal',  "ff","ff","ff", "",       true, true, false)
-	addon:_add_loot_disposition ('offspec', "c6","9b","6d", "offspec", true, true, true)
-	addon:_add_loot_disposition ('shard',   "a3","35","ee", "shard", false, false, true)
-	addon:_add_loot_disposition ('gvault',  "33","ff","99", _G.GUILD_BANK:lower(), false, false, true)
 end
 
 -- In the rare case of items getting put into the loot table without current
--- a/gui.lua	Wed Aug 08 14:43:26 2012 -0400
+++ b/gui.lua	Wed Aug 08 23:13:04 2012 -0400
@@ -47,6 +47,9 @@
 	},
 	taborder        = { "eoi"                        },
 	taborder_APPEND = {        "hist", "help", "opt" },
+
+	-- Tables for feeding to EasyMenu
+	dropdown = {},
 }
 addon.gui_state_pointer = gui    -- only during loading, then cleaned out
 if addon.author_debug then
@@ -820,6 +823,7 @@
 -- forward decls
 local eoi_editcell
 
+local dropdownmenuframe = CreateFrame("Frame", "OuroLootDropDownMenu", nil, "UIDropDownMenuTemplate")
 local dropdownfuncs
 do
 	local ddf_mt = {
@@ -841,37 +845,30 @@
 	end
 end
 
-local function gen_easymenu_table (initial, list, funcs)
-	for _,tag in ipairs(list) do
-		local name, arg, tiptext
-		name, tiptext = strsplit('|',tag)
-		name, arg = strsplit('%',name)
-		if name == "--" then
-			tinsert (initial, {
-				disabled = true, notCheckable = true, text = "",
-			})
-		else
-			if not funcs[name] then
-				error(("'%s' not defined as a dropdown function"):format(name))
-			end
-			tinsert (initial, {
-				text = name,
-				func = dropdownmenu_handler,
-				arg1 = funcs[name],
-				arg2 = arg,
-				notCheckable = true,
-				tooltipOnButton = true,
-				tooltipWhileDisabled = true,
-				tooltipTitle = tiptext and name or nil,
-				tooltipText = tiptext,
-			})
+local function gen_dd_entry (name, functbl, funci, arg, ttt)
+	local entry
+	if name == '--' then
+		entry = {
+			text = "", disabled = true, notCheckable = true,
+		}
+	else
+		local a1 = functbl[name]
+		if type(funci) == 'string' then
+			a1 = functbl[funci]
 		end
+		entry = {
+			text = name,
+			func = dropdownmenu_handler, arg1 = a1, arg2 = arg,
+			notCheckable = true,
+			tooltipOnButton = true,
+			tooltipWhileDisabled = true,
+			tooltipTitle = ttt and name or nil,
+			tooltipText = ttt,
+		}
 	end
-	return initial
+	return entry
 end
 
-local dropdownmenuframe = CreateFrame("Frame", "OuroLootDropDownMenu", nil, "UIDropDownMenuTemplate")
-
 
 -- Tab 1:  Events Of Interest
 -- This actually takes up quite a bit of the file.
@@ -902,6 +899,10 @@
 		end
 	end,
 
+	df_DISPOSITION = function(rowi,disp)   -- all "mark as <x>" entries start here
+		addon:loot_mark_disposition ("local", rowi, disp)
+	end,
+
 	["Delete remaining entries for this day"] = function(rowi,kind)
 		-- if kind is boss, also need to stop at new timestamp
 		local fencepost = addon._find_timeboss_fencepost (kind, rowi)
@@ -937,10 +938,6 @@
 		until rowi >= fencepost
 	end,
 
-	["Mark as normal"] = function(rowi,disp)
-		addon:loot_mark_disposition ("local", rowi, disp)
-	end,
-
 	["Show only this player"] = function(rowi)
 		local st = assert(gui.eoiST)
 		_d:SetUserData("player filter name", g_loot[rowi].person)
@@ -971,55 +968,42 @@
 		dialog.data = {index=rowi, display=_d}
 	end,
 }
--- Would be better to move the %arg to this list rather than below, but
--- that's a lot of extra effort that doesn't buy much in return.
-eoi_dropdownfuncs["Delete this loot event"] = eoi_dropdownfuncs.df_DELETE
-eoi_dropdownfuncs["Delete this boss event"] = eoi_dropdownfuncs.df_DELETE
-eoi_dropdownfuncs["Insert new loot entry"] = eoi_dropdownfuncs.df_INSERT
-eoi_dropdownfuncs["Insert new boss kill event"] = eoi_dropdownfuncs.df_INSERT
-eoi_dropdownfuncs["Mark as disenchanted"] = eoi_dropdownfuncs["Mark as normal"]
-eoi_dropdownfuncs["Mark as ".._G.GUILD_BANK:lower()] = eoi_dropdownfuncs["Mark as normal"]
-eoi_dropdownfuncs["Mark as offspec"] = eoi_dropdownfuncs["Mark as normal"]
-eoi_dropdownfuncs["Delete remaining entries for this boss"] =
-	eoi_dropdownfuncs["Delete remaining entries for this day"]
-eoi_dropdownfuncs["Rebroadcast this day"] = eoi_dropdownfuncs["Rebroadcast this boss"]
-local eoi_time_dropdown = gen_easymenu_table(
-	{{
-		-- this is the dropdown title, text filled in on the fly
-		isTitle = true,
-		notClickable = true,
-		notCheckable = true,
-	}},
-	{
-		"Rebroadcast this day%time|Broadcasts everything from here down until a new day.",
-		"Delete remaining entries for this day%time|Erases everything from here down until a new day.\n\nHold down the Shift key to also delete the corresponding entries from player History.",
-		"Insert new loot entry%loot|Inserts new loot above this one, prompting you for information.",
-		"Insert new boss kill event%boss|Inserts new event above this one, prompting you for information.",
-		CLOSE
-	}, eoi_dropdownfuncs)
-local eoi_loot_dropdown = gen_easymenu_table(
-	{{
-		-- this is the dropdown title, text filled in on the fly
-		notClickable = true,
-		notCheckable = true,
-	}},
-	{
-		"Mark as disenchanted%shard",
-		"Mark as offspec%offspec",
-		"Mark as ".._G.GUILD_BANK:lower().."%gvault",
-		"Mark as normal|This is the default.  Selecting any 'Mark as <x>' action blanks out extra notes about who broadcast this entry, etc.",
-		"--",
-		"Rebroadcast this loot entry|Sends this loot event, including special notes, as if it just happened.",
-		"Delete this loot event|Permanent, no going back!\n\nHold down the Shift key to also delete the corresponding entry from player's History.",
-		"Delete remaining entries for this boss%boss|Erases everything from here down until a new boss/day.\n\nHold down the Shift key to also delete the corresponding entries from player History.",
-		"Insert new loot entry%loot|Inserts new loot above this one, prompting you for information.",
-		"Insert new boss kill event%boss|Inserts new event above this one, prompting you for information.",
-		"Edit note|Same as double-clicking in the notes column.",
-		"--",
-		CLOSE
-	}, eoi_dropdownfuncs)
-local eoi_player_dropdown = gen_easymenu_table(
-	{
+
+do
+	local function E (name, funci, arg, ttt)
+		return gen_dd_entry (name, eoi_dropdownfuncs, funci, arg, ttt)
+	end
+
+	gui.dropdown.eoi_time = {
+		{
+			-- this is the dropdown title, text filled in on the fly
+			isTitle = true,
+			notClickable = true,
+			notCheckable = true,
+		},
+		E("Rebroadcast this day", "Rebroadcast this boss", 'time', "Broadcasts everything from here down until a new day."),
+		E("Delete remaining entries for this day", nil, 'time', "Erases everything from here down until a new day.\n\nHold down the Shift key to also delete the corresponding entries from player History."),
+		E("Insert new loot entry", 'df_INSERT', 'loot', "Inserts new loot above this one, prompting you for information."),
+		E("Insert new boss kill event", 'df_INSERT', 'boss', "Inserts new event above this one, prompting you for information."),
+		E(CLOSE),
+	}
+	gui.dropdown.eoi_loot = {
+		{
+			-- this is the dropdown title, text filled in on the fly
+			notClickable = true,
+			notCheckable = true,
+		},
+		E("--"),
+		E("Rebroadcast this loot entry", nil, nil, "Sends this loot event, including special notes, as if it just happened."),
+		E("Delete this loot event", 'df_DELETE', nil, "Permanent, no going back!\n\nHold down the Shift key to also delete the corresponding entry from player's History."),
+		E("Delete remaining entries for this boss", "Delete remaining entries for this day", 'boss', "Erases everything from here down until a new boss/day.\n\nHold down the Shift key to also delete the corresponding entries from player History."),
+		E("Insert new loot entry", 'df_INSERT', 'loot', "Inserts new loot above this one, prompting you for information."),
+		E("Insert new boss kill event", 'df_INSERT', 'boss', "Inserts new event above this one, prompting you for information."),
+		E("Edit note", nil, nil, "Same as double-clicking in the Notes column."),
+		E("--"),
+		E(CLOSE),
+	}
+	gui.dropdown.eoi_player = {
 		{
 			-- this is the dropdown title, text filled in on the fly
 			isTitle = true,
@@ -1033,28 +1017,27 @@
 			tooltipOnButton = true,
 			tooltipWhileDisabled = true,
 		},
-	},
-	{
-		"Show only this player",
-		CLOSE
-	}, eoi_dropdownfuncs)
-local eoi_boss_dropdown = gen_easymenu_table(
-	{{
-		-- this is the dropdown title, text filled in on the fly
-		isTitle = true,
-		notClickable = true,
-		notCheckable = true,
-	}},
-	{
-		"Change from 'wipe' to 'kill'|Also collapses previous wipe entries.", -- KILLWIPE
-		"Rebroadcast this boss%boss|Broadcasts the kill event and all subsequent loot until next boss.",
-		"Delete this boss event|Permanent, no going back!",
-		"Delete remaining entries for this boss%boss|Erases everything from here down until a new boss/day.\n\nHold down the Shift key to also delete the corresponding entries from player History.",
-		"Insert new loot entry%loot|Inserts new loot above this one, prompting you for information.",
-		"Insert new boss kill event%boss|Inserts new event above this one, prompting you for information.",
-		"--",
-		CLOSE
-	}, eoi_dropdownfuncs)
+		E("Show only this player"),
+		E(CLOSE),
+	}
+	gui.dropdown.eoi_boss = {
+		{
+			-- this is the dropdown title, text filled in on the fly
+			isTitle = true,
+			notClickable = true,
+			notCheckable = true,
+		},
+		E("Change from 'wipe' to 'kill'", nil, nil, "Also collapses previous wipe entries."), -- KILLWIPE
+		E("Rebroadcast this boss", nil, 'boss', "Broadcasts the kill event and all subsequent loot until next boss."),
+		E("Delete this boss event", 'df_DELETE', nil, "Permanent, no going back!"),
+		E("Delete remaining entries for this boss", "Delete remaining entries for this day", 'boss', "Erases everything from here down until a new boss/day.\n\nHold down the Shift key to also delete the corresponding entries from player History."),
+		E("Insert new loot entry", 'df_INSERT', 'loot', "Inserts new loot above this one, prompting you for information."),
+		E("Insert new boss kill event", 'df_INSERT', 'boss', "Inserts new event above this one, prompting you for information."),
+		E("--"),
+		E(CLOSE),
+	}
+end
+
 
 --[[ quoted verbatim from lib-st docs (table->stable for obvious reasons):
 rowFrame This is the UI Frame table for the row.
@@ -1156,11 +1139,11 @@
 
 	if kind == 'loot' and (column == 1 or column == 3) then
 		_d:SetUserData("DD cell", cellFrame)
-		eoi_loot_dropdown[1].text = e.itemlink
-		EasyMenu (eoi_loot_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU")
+		gui.dropdown.eoi_loot[1].text = e.itemlink
+		EasyMenu (gui.dropdown.eoi_loot, dropdownmenuframe, cellFrame, 0, 0, "MENU")
 
 	elseif kind == 'loot' and column == 2 then
-		eoi_player_dropdown[1].text = e.person
+		gui.dropdown.eoi_player[1].text = e.person
 		local raiders = {}
 		for i = 1, GetNumRaidMembers() do
 			tinsert (raiders, (GetRaidRosterInfo(i)))
@@ -1168,38 +1151,33 @@
 		table.sort(raiders)
 		for i = 1, #raiders do
 			local name = raiders[i]
-			raiders[i] = {
-				text = name,
-				func = dropdownmenu_handler,
-				arg1 = eoi_dropdownfuncs.df_REASSIGN,
-				arg2 = name,
-				notCheckable = true,
-			}
+			raiders[i] = gen_dd_entry (name, eoi_dropdownfuncs, 'df_REASSIGN', name)
 		end
-		eoi_player_dropdown[2].menuList =
-			gen_easymenu_table (raiders, {"Enter name...",CLOSE}, eoi_dropdownfuncs)
+		tinsert (raiders, gen_dd_entry ("Enter name...", eoi_dropdownfuncs))
+		tinsert (raiders, gen_dd_entry (CLOSE, eoi_dropdownfuncs))
+		gui.dropdown.eoi_player[2].menuList = raiders
 
 		if not addon:_test_disposition (e.disposition, 'can_reassign') then
-			eoi_player_dropdown[2].disabled = true
-			eoi_player_dropdown[2].tooltipTitle = "Cannot Reassign"
-			eoi_player_dropdown[2].tooltipText = "You must first mark this item as 'normal' or 'offspec' before reassignment."
+			gui.dropdown.eoi_player[2].disabled = true
+			gui.dropdown.eoi_player[2].tooltipTitle = "Cannot Reassign"
+			gui.dropdown.eoi_player[2].tooltipText = "You must first mark this item as 'normal' or 'offspec' before reassignment."
 		else
-			eoi_player_dropdown[2].disabled = nil
-			eoi_player_dropdown[2].tooltipTitle = nil
-			eoi_player_dropdown[2].tooltipText = nil
+			gui.dropdown.eoi_player[2].disabled = nil
+			gui.dropdown.eoi_player[2].tooltipTitle = nil
+			gui.dropdown.eoi_player[2].tooltipText = nil
 		end
-		EasyMenu (eoi_player_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU")
+		EasyMenu (gui.dropdown.eoi_player, dropdownmenuframe, cellFrame, 0, 0, "MENU")
 
 	elseif kind == 'boss' then
-		eoi_boss_dropdown[1].text = e.bossname
-		-- KILLWIPE:  update '2' if this is not the 2nd entry in eoi_boss_dropdown
-		eoi_boss_dropdown[2].tooltipWhileDisabled = nil
-		eoi_boss_dropdown[2].disabled = e.reason ~= 'wipe' and true or nil
-		EasyMenu (eoi_boss_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU")
+		gui.dropdown.eoi_boss[1].text = e.bossname
+		-- KILLWIPE:  update '2' if this is not the 2nd entry in gui.dropdown.eoi_boss
+		gui.dropdown.eoi_boss[2].tooltipWhileDisabled = nil
+		gui.dropdown.eoi_boss[2].disabled = e.reason ~= 'wipe' and true or nil
+		EasyMenu (gui.dropdown.eoi_boss, dropdownmenuframe, cellFrame, 0, 0, "MENU")
 
 	elseif kind == 'time' then
-		eoi_time_dropdown[1].text = e.startday.text
-		EasyMenu (eoi_time_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU")
+		gui.dropdown.eoi_time[1].text = e.startday.text
+		EasyMenu (gui.dropdown.eoi_time, dropdownmenuframe, cellFrame, 0, 0, "MENU")
 
 	end
 
@@ -1537,8 +1515,11 @@
 		scrollhere = math.min (scrollhere,
 			(#gui.eoiST.filtered - eoi_st_displayed_rows) * eoi_st_rowheight)
 		gui.eoiST:SetSelection(name_or_lineno)
-		local sf = gui.eoiST.scrollframe
-		sf:GetScript("OnVerticalScroll")(sf,scrollhere)
+		if name_or_lineno > eoi_st_displayed_rows then
+			-- don't try to scroll if there's not enough lines
+			local sf = gui.eoiST.scrollframe
+			sf:GetScript("OnVerticalScroll")(sf,scrollhere)
+		end
 	end
 end
 
@@ -1643,29 +1624,34 @@
 			addon:colorize(name,gone.person_class), #gone.unique)
 	end,
 }
-local hist_general_dropdown = gen_easymenu_table(
-	{{
-		-- this is the dropdown title, text filled in on the fly
-		isTitle = true,
-		notClickable = true,
-		notCheckable = true,
-	}},
-	{
-		"Delete this player's entire loot history|Permanent, no going back!",
-		"--",
-		CLOSE
-	}, hist_dropdownfuncs)
-local hist_specific_dropdown = gen_easymenu_table(
-	{{
-		-- this is the dropdown title, text filled in on the fly
-		notClickable = true,
-		notCheckable = true,
-	}},
-	{
-		"Delete this loot event from history|Permanent, no going back!",
-		"--",
-		CLOSE
-	}, hist_dropdownfuncs)
+
+do
+	local function E (name, funci, arg, ttt)
+		return gen_dd_entry (name, hist_dropdownfuncs, funci, arg, ttt)
+	end
+
+	gui.dropdown.hist_general = {
+		{
+			-- this is the dropdown title, text filled in on the fly
+			isTitle = true,
+			notClickable = true,
+			notCheckable = true,
+		},
+		E("Delete this player's entire loot history", nil, nil, "Permanent, no going back!"),
+		E("--"),
+		E(CLOSE),
+	}
+	gui.dropdown.hist_specific = {
+		{
+			-- this is the dropdown title, text filled in on the fly
+			notClickable = true,
+			notCheckable = true,
+		},
+		E("Delete this loot event from history", nil, nil, "Permanent, no going back!"),
+		E("--"),
+		E(CLOSE),
+	}
+end
 
 -- Loot column
 --[[
@@ -1710,8 +1696,8 @@
 	if history_filter_who then
 		-- Shift-right opens a menu
 		if IsShiftKeyDown() and button == "RightButton" then
-			hist_specific_dropdown[1].text = h.itemlink
-			EasyMenu (hist_specific_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU")
+			gui.dropdown.hist_specific[1].text = h.itemlink
+			EasyMenu (gui.dropdown.hist_specific, dropdownmenuframe, cellFrame, 0, 0, "MENU")
 
 		-- Right goes back to normal mode
 		elseif button == "RightButton" then
@@ -1723,8 +1709,8 @@
 	else  -- not focused
 		-- Shift-right opens a menu
 		if IsShiftKeyDown() and button == "RightButton" then
-			hist_general_dropdown[1].text = h.OLwho
-			EasyMenu (hist_general_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU")
+			gui.dropdown.hist_general[1].text = h.OLwho
+			EasyMenu (gui.dropdown.hist_general, dropdownmenuframe, cellFrame, 0, 0, "MENU")
 
 		-- Left focuses on a specific player
 		elseif button == "LeftButton" then
@@ -2274,6 +2260,41 @@
 end
 
 
+-- We need to be able to reference the dropdownmenu locals, and I didn't want to
+-- bubble them up any higher.
+function gui.add_dropdown_entry (menutag, name, func_tbl, func_or_othername, arg, tooltiptext)
+	local emtbl = assert(gui.dropdown[menutag])
+
+	if type(func_tbl) == 'table' then
+		-- use it directly
+	elseif func_tbl == nil then
+		-- determine it from the menu tag
+		func_tbl = (menutag:sub(1,3) == 'eoi' and eoi_dropdownfuncs)
+			or (menutag:sub(1,4) == 'hist' and hist_dropdownfuncs)
+			or error("Cannot figure out function table from menu tag name")
+	end
+
+	if type(func_or_othername) == 'string' then
+		-- gen_dd_entry handles this
+	elseif type(func_or_othername) == 'function' then
+		error"bah"
+	end
+
+	local index
+	if menutag == 'eoi_loot' then
+		index = 2
+	elseif menutag == 'eoi_player' then
+		index = 3
+	else
+		index = 2
+	end
+
+	local ent = gen_dd_entry (name, func_tbl, func_or_othername, arg, tooltiptext)
+	tinsert (emtbl, index, ent)
+	return ent
+end
+
+
 ------ Popup dialogs
 local function build_my_slider_widget()
 	local s = CreateFrame("Slider", "OuroLootSlider", nil, "OptionsSliderTemplate")