diff gui.lua @ 73:32eb24fb2ebf

- This code is not quite ready for prime time. Do not run it yet. - Loot events have associated unique IDs, enabling some new actions over the network. These IDs are preserved as part of realm history. As a result, the stored history format has completely changed (and requires less memory as a bonus). - "Prescan for faster handling" option, default off. - "Mark as <x>" now broadcast to other trackers. Older versions can't receive the message, of course. Future: Broadcast reassigning loot. - New options controlling whether (and where) to print a message when another player broadcasts those kinds of changes to existing loot. - Names colored by class when that data is available; CUSTOM_CLASS_COLORS supported. - Metric boatloads of minor tweaks and optimizations throughout.
author Farmbuyer of US-Kilrogg <farmbuyer@gmail.com>
date Tue, 29 May 2012 22:50:09 +0000
parents bb19899c65a7
children 5edaac60449b
line wrap: on
line diff
--- a/gui.lua	Sat May 12 11:08:23 2012 +0000
+++ b/gui.lua	Tue May 29 22:50:09 2012 +0000
@@ -23,14 +23,24 @@
 --eoi_st_otherrow_bgcolortable["realm"] = eoi_st_otherrow_bgcolortable["time"]
 local eoi_st_otherrow_bgcolortable_default
 local eoi_st_lootrow_col3_colortable = {
-	[""]	= { text = "", r = 1.0, g = 1.0, b = 1.0, a = 1.0 },
-	shard	= { text = "shard", r = 0xa3/255, g = 0x35/255, b = 0xee/255, a = 1.0 },
-	offspec	= { text = "offspec", r = 0.78, g = 0.61, b = 0.43, a = 1.0 },
-	gvault	= { text = "guild vault", r = 0x33/255, g = 1.0, b = 0x99/255, a = 1.0 },
+	normal	= { text = "",            r = "ff", g = "ff", b = "ff" },
+	shard	= { text = "shard",       r = "a3", g = "35", b = "ee" },
+	offspec	= { text = "offspec",     r = "c6", g = "9b", b = "6d" },
+	gvault	= { text = "guild vault", r = "33", g = "ff", b = "99" },
 }
-local function eoi_st_lootrow_col3_colortable_func (data, cols, realrow, column, table)
+for k,v in pairs(eoi_st_lootrow_col3_colortable) do
+	-- for chat output by core code
+	v.hex = "|cff" .. v.r .. v.g .. v.b
+	-- for lib-st
+	v.r = tonumber(v.r,16)/255
+	v.g = tonumber(v.g,16)/255
+	v.b = tonumber(v.b,16)/255
+	v.a = 1
+end
+addon.disposition_colors = eoi_st_lootrow_col3_colortable
+local function eoi_st_lootrow_col3_colortable_func (data, _, realrow)
 	local disp = data[realrow].disposition
-	return eoi_st_lootrow_col3_colortable[disp or ""]
+	return eoi_st_lootrow_col3_colortable[disp or 'normal']
 end
 addon.time_column1_used_mt = { __index = {
 	[2] = {value=""},
@@ -69,6 +79,27 @@
 local mkbutton
 local tabs_OnGroupSelected_func, tabs_generated_text_OGS
 
+-- Class color support
+local class_colors-- = {}
+do
+	local function fill_out_class_colors()
+		class_colors = CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS
+		-- If we were dependant on lib-st calling this function (via a
+		-- 'color' field in eoi_st_cols[2]), then this would have to be deep
+		-- copied and an "a=1" field added to each.  But as we have to use
+		-- this ourselves via DoCellUpdate, we can just share tables and
+		-- pass an alpha value manually during cell update.
+		--for class,color in pairs(CUSTOM_CLASS_COLORS or RAID_CLASS_COLORS) do
+		--	class_colors[class] = { r = color.r, g = color.g, b = color.b, a = 1 }
+		--end
+	end
+	fill_out_class_colors()
+	if CUSTOM_CLASS_COLORS and CUSTOM_CLASS_COLORS.RegisterCallback then
+		CUSTOM_CLASS_COLORS:RegisterCallback(fill_out_class_colors)
+	end
+	addon.class_colors = class_colors
+end
+
 -- Working around this bug:
 -- http://forums.wowace.com/showpost.php?p=295202&postcount=31
 do
@@ -265,22 +296,22 @@
 				e.cols = {
 					{value = textured},
 					{value = e.person},
-					{ color = eoi_st_lootrow_col3_colortable_func }
+					{}
 				}
 				-- This is horrible. Must do better.
 				if e.extratext then for k,v in pairs(eoi_st_lootrow_col3_colortable) do
 					if v.text == e.extratext then
-						e.disposition = k
+						e.disposition = k ~= 'normal' and k or nil
 						--e.extratext = nil, not feasible
 						break
 					end
 				end end
-				local ex = e.disposition or ""
-				ex = eoi_st_lootrow_col3_colortable[ex].text
+				local ex = eoi_st_lootrow_col3_colortable[e.disposition or 'normal'].text
 				if e.bcast_from and display_bcast_from and e.extratext then
 					ex = e.extratext .. " (from " .. e.bcast_from .. ")"
 				elseif e.bcast_from and display_bcast_from then
-					ex = ex .. " (from " .. e.bcast_from .. ")"
+					ex = ex .. (e.disposition and " " or "")
+					     .. "(from " .. e.bcast_from .. ")"
 				elseif e.extratext then
 					ex = e.extratext
 				end
@@ -366,18 +397,19 @@
 			col1.OLn   = #player
 			col1.value = player.name   -- may spiffy this up in future
 
-			for li,loot in ipairs(player) do
+			for li,unique in ipairs(player.unique) do
 				local col2 = new()
 				col2.OLi   = li
 				local col3 = new()
-				col3.value = loot.when
+				col3.value = player.when[unique]
 
-				local itexture = GetItemIcon(loot.id)
-				local iname, ilink, iquality = GetItemInfo(loot.id)
+				local id = player.id[unique]
+				local itexture = GetItemIcon(id)
+				local iname, ilink, iquality = GetItemInfo(id)
 				local textured
 				if itexture and iname then
 					textured = eoi_st_textured_item_format:format (itexture,
-						ITEM_QUALITY_COLORS[iquality].hex, iname, loot.count or "")
+						ITEM_QUALITY_COLORS[iquality].hex, iname, player.count[unique] or "")
 				else
 					textured = eoi_st_textured_item_format:format ([[ICONS\INV_Misc_QuestionMark]],
 						ITEM_QUALITY_COLORS[ITEM_QUALITY_COMMON].hex, 'UNKNOWN - REDISPLAY LATER', "")
@@ -401,7 +433,78 @@
 end
 
 -- Debugging tooltip
-do
+if true then
+	local tt
+	local function _create_tooltip()
+		tt = CreateFrame("GameTooltip")
+		UIParentLoadAddOn("Blizzard_DebugTools")
+
+		tt:SetBackdrop{
+			bgFile = [[Interface\Tooltips\UI-Tooltip-Background]],
+			edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]],
+			tile = true,
+			tileSize = 8,
+			edgeSize = 12,
+			insets = { left = 2, right = 2, top = 2, bottom = 2 }
+		}
+		tt:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r,
+			TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b)
+		tt:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g,
+			TOOLTIP_DEFAULT_COLOR.b)
+		tt:SetMovable(false)
+		tt:EnableMouse(false)
+		tt:SetFrameStrata("TOOLTIP")
+		tt:SetToplevel(true)
+		tt:SetClampedToScreen(true)
+
+		local font = CreateFont("OuroLootDebugFont")
+		font:CopyFontObject(GameTooltipTextSmall)
+		if IsAddOnLoaded"tekticles" then    -- maybe check for one of the sharedmedia things?
+			font:SetFont([[Interface\AddOns\tekticles\Calibri.ttf]], 9)
+		else
+			font:SetFont([[Fonts\FRIZQT__.TTF]], 9)
+		end
+
+		local left, right, prevleft
+		-- Only create as many lines as we might need (the auto growth
+		-- by Add*Line does odd things sometimes).
+		for i = 1, math.max(DEVTOOLS_MAX_ENTRY_CUTOFF,15)+5 do
+			prevleft = left
+			left = tt:CreateFontString(nil,"ARTWORK")
+			right = tt:CreateFontString(nil,"ARTWORK")
+			left:SetFontObject(font)
+			right:SetFontObject(font)
+			tt:AddFontStrings(left,right)
+			if prevleft then
+				left:SetPoint("TOPLEFT",prevleft,"BOTTOMLEFT",0,-2)
+			else
+				left:SetPoint("TOPLEFT",10,-10)  -- top line
+			end
+			right:SetPoint("RIGHT",left,"LEFT")
+		end
+		tt.AddMessage = tt.AddLine
+
+		_create_tooltip = nil
+	end
+
+	function _build_debugging_tooltip (parent, index)
+		local e = g_loot[index]; assert(type(e)=='table')
+		if not tt then _create_tooltip() end
+		tt:SetOwner (parent, "ANCHOR_LEFT", -15, -5)
+		tt:ClearLines()
+
+		local real = DEFAULT_CHAT_FRAME
+		DEFAULT_CHAT_FRAME = tt
+		DevTools_Dump{ [index] = e }
+		DEFAULT_CHAT_FRAME = real
+
+		tt:Show()
+	end
+
+	function _hide_debugging_tooltip()
+		if tt then tt:Hide() end
+	end
+else
 	-- Fields to put in the tooltip (maybe move these into the options window
 	-- if I spend too much time fiddling).
 	local loot = {'person', 'id', 'unique', 'disposition', 'count', 'variant'}
@@ -677,12 +780,8 @@
 		until rowi >= fencepost
 	end,
 
-	["Mark as normal"] = function(rowi,disp) -- broadcast the change?  ugh
-		local olddisp = g_loot[rowi].disposition
-		g_loot[rowi].disposition = disp
-		g_loot[rowi].bcast_from = nil
-		g_loot[rowi].extratext = nil
-		addon:history_handle_disposition (rowi, olddisp)
+	["Mark as normal"] = function(rowi,disp)
+		addon:loot_mark_disposition ("local", rowi, disp)
 	end,
 
 	["Show only this player"] = function(rowi)
@@ -1002,7 +1101,6 @@
 	local cell = e.cols[column]
 
 	cellFrame.text:SetText(cell.value)
-	cellFrame.text:SetTextColor(1,1,1,1)
 
 	if e.person_class then
 		local icon
@@ -1019,11 +1117,14 @@
 		icon:SetTexCoord(unpack(CLASS_ICON_TCOORDS[e.person_class]))
 		icon:Show()
 		cellFrame.text:SetPoint("LEFT", icon, "RIGHT", 1, 0)
+		local color = class_colors[e.person_class]
+		cellFrame.text:SetTextColor(color.r,color.g,color.b,1)
 	else
 		if cellFrame.icontexture then
 			cellFrame.icontexture:Hide()
 			cellFrame.text:SetPoint("LEFT", cellFrame, "LEFT")
 		end
+		cellFrame.text:SetTextColor(1,1,1,1)
 	end
 
 	--if e.kind ~= 'loot' then
@@ -1046,6 +1147,7 @@
 	{  -- col 3
 		name	= "Notes",
 		width	= 250,
+		color	= eoi_st_lootrow_col3_colortable_func,
 	},
 }
 
@@ -1624,7 +1726,7 @@
 		grp:SetTitle("Debugging/Testing Options      [not saved across sessions]")
 
 		w = mkbutton("EditBox", 'comm_ident', addon.ident,
-			[[Disable the addon, change this field (click Okay or press Enter), then re-enable the addon.]])
+			[[Set tracking to 'Disabled' in the top-right dropdown, then change this field (click Okay or press Enter).]])
 		w:SetRelativeWidth(0.2)
 		w:SetLabel("Addon channel ID")
 		w:SetCallback("OnTextChanged", adv_careful_OnTextChanged)
@@ -1662,25 +1764,23 @@
 			if mod then
 				mod:EnableMod()
 				addon:Print("Now tracking ID",mod.creatureId)
-			else addon:Print("Can do nothing; DBM testing mod wasn't loaded.") end
+			else
+				addon:Print("Can do nothing; DBM testing mod wasn't loaded.")
+			end
 		end)
 		w:SetDisabled(addon.bossmod_registered ~= 'DBM')
 		grp:AddChild(w)
 
 		w = mkbutton("GC", [[full GC cycle]])
 		w:SetRelativeWidth(0.1)
-		w:SetCallback("OnClick", function() collectgarbage() end)
+		w:SetCallback("OnClick", function()
+			local before = collectgarbage('count')
+			collectgarbage('collect')
+			local after = collectgarbage('count')
+			addon:Print("Collected %d KB, %d KB still in use by Lua universe.", before-after, after)
+		end)
 		grp:AddChild(w)
 
-		--[==[ this has been well and truly debugged by now
-		w = mkbutton("EditBox", nil, addon.loot_pattern:sub(17), [[]])
-		w:SetRelativeWidth(0.35)
-		w:SetLabel("CML pattern suffix")
-		w:SetCallback("OnEnterPressed", function(_w,event,value)
-			addon.loot_pattern = addon.loot_pattern:sub(1,16) .. value
-		end)
-		grp:AddChild(w) ]==]
-
 		w = GUI:Create("Spacer") w:SetFullWidth(true) w:SetHeight(1) grp:AddChild(w)
 
 		local simple = GUI:Create("SimpleGroup")
@@ -1709,7 +1809,7 @@
 		w:SetFullWidth(true)
 		w:SetType("checkbox")
 		w:SetLabel("GOP history mode")
-		w:SetValue(false)
+		w:SetValue(addon.history_suppress)
 		w:SetCallback("OnValueChanged", function(_w,event,value) addon.history_suppress = value end)
 		simple:AddChild(w)
 		w = mkbutton("Clear All & Reload",
@@ -1763,10 +1863,15 @@
 		grp:ResumeLayout()
 		container:AddChild(grp)
 		GUI:ClearFocus()
+		container:SetScroll(1000)  -- scrollframe's max value
 	end
 
 	-- Initial lower panel function
 	local function adv_lower (container, specials)
+		local spacer = GUI:Create("Spacer")
+		spacer:SetFullWidth(true)
+		spacer:SetHeight(5)
+		container:AddChild(spacer)
 		local speedbump = GUI:Create("InteractiveLabel")
 		speedbump:SetFullWidth(true)
 		speedbump:SetFontObject(GameFontHighlightLarge)
@@ -1781,6 +1886,10 @@
 			--return tabs_OnGroupSelected_func(container.parent,"OnGroupSelected","opt")
 		end)
 		container:AddChild(speedbump)
+		spacer = GUI:Create("Spacer")
+		spacer:SetFullWidth(true)
+		spacer:SetHeight(5)
+		container:AddChild(spacer)
 	end
 
 	tabs_OnGroupSelected["opt"] = function(container,specials)
@@ -1816,7 +1925,7 @@
 			[[Register "/loot" as a slash command in addition to the normal "/ouroloot".  Relog to take effect.]])
 		grp:AddChild(w)
 
-		-- chatty mode
+		-- chatty boss mode
 		w = mkoption('chatty_on_kill', "Be chatty on boss kill", 0.49,
 			[[Print something to chat output when DBM tells Ouro Loot about a successful boss kill.]])
 		grp:AddChild(w)
@@ -1838,42 +1947,103 @@
 
 		-- showing the "(from Rebroadcasterdude)" in the notes column
 		w = mkoption('display_bcast_from', "Show rebroadcasting player", 0.49,
-			[[Include "(from Player_Name)" in the Notes column for loot that was broadcast to you.]],
+			[[Include "from PlayerName" in the Notes column for loot that was broadcast to you.  (Not included in forum output).]],
 			function(_w,_e,value)
 				opts.display_bcast_from = value
 				addon.loot_clean = nil
 			end)
 		grp:AddChild(w)
 
+		-- prefilling g_uniques with history
+		w = mkoption('precache_history_uniques', "Prescan for faster handling", 0.49,
+			[[See description under +Help -- Handy Tips -- Prescanning> for instructions.]])
+		grp:AddChild(w)
+
+		w = GUI:Create("Spacer") w:SetFullWidth(true) w:SetHeight(1) grp:AddChild(w)
+
 		-- possible keybindings
 		do
-			local pair = GUI:Create("SimpleGroup")
-			pair:SetLayout("Flow")
-			pair:SetRelativeWidth(0.95)
+			local pair = GUI:Create("InlineGroup")
+			pair:SetLayout("List")
+			pair:SetRelativeWidth(0.49)
 			local editbox, checkbox
 			editbox = mkbutton("EditBox", nil, opts.keybinding_text,
 				[[Keybinding text format is fragile!  Relog to take effect.]])
-			editbox:SetRelativeWidth(0.5)
+			editbox:SetFullWidth(true)
 			editbox:SetLabel("Keybinding text")
 			editbox:SetCallback("OnEnterPressed", function(_w,event,value)
 				opts.keybinding_text = value
 			end)
 			editbox:SetDisabled(not opts.keybinding)
-			checkbox = mkoption('keybinding', "Register keybinding", 0.5,
+			checkbox = mkoption('keybinding', "Register keybinding", 1,
 				[[Register a keybinding to toggle the loot display.  Relog to take effect.]],
 				function (_w,_,value)
 					opts.keybinding = value
 					editbox:SetDisabled(not opts.keybinding)
 				end)
+			checkbox:SetFullWidth(true)
 			pair:AddChild(checkbox)
 			pair:AddChild(editbox)
 			grp:AddChild(pair)
 		end
 
+		-- chatty disposition/assignment changes
+		do
+			local chatgroup = GUI:Create("InlineGroup")
+			chatgroup:SetLayout("List")
+			chatgroup:SetRelativeWidth(0.49)
+			chatgroup:SetTitle("Remote Changes Chat")
+			local toggle, editbox
+			toggle = mkoption('chatty_on_remote_changes', "Be chatty on remote changes", 1,
+				[[Print something to chat when other users change recorded loot.]],
+				function (_w,_,value)
+					opts.chatty_on_remote_changes = value
+					editbox:SetDisabled(not opts.chatty_on_remote_changes)
+				end)
+			toggle:SetFullWidth(true)
+			chatgroup:AddChild(toggle)
+			w = GUI:Create("Label")
+			w:SetFullWidth(true)
+			w:SetText("This controls the output of the |cff00ffff'Be chatty on remote changes'|r option.  If this field is a number, it designates which chat frame to use.  Otherwise it is the Lua variable name of a frame with AddMessage capability.")
+			chatgroup:AddChild(w)
+			editbox = mkbutton("EditBox", nil, opts.chatty_on_remote_changes_frame,
+				[[1 = default chat frame, 2 = combat log, etc]])
+			editbox:SetFullWidth(true)
+			editbox:SetLabel("Output Chatframe")
+			editbox:SetCallback("OnTextChanged", adv_careful_OnTextChanged)
+			editbox:SetCallback("OnEnterPressed", function(_w,event,value)
+				local prev = opts.chatty_on_remote_changes_frame
+				value = value:trim()
+				value = tonumber(value) or value
+				if addon:_set_remote_change_chatframe (value) then
+					opts.chatty_on_remote_changes_frame = value
+					_w:SetText(tostring(value))
+					_w.editbox:ClearFocus()
+				else
+					_w:SetText(tostring(prev))
+				end
+			end)
+			editbox:SetDisabled(not opts.chatty_on_remote_changes)
+			chatgroup:AddChild(editbox)
+			w = mkbutton("Chat Frame Numbers",
+				[[Print each chat window number in its own frame, for easy reference in the editing field.]])
+			w:SetFullWidth(true)
+			--w:SetDisabled(not opts.chatty_on_remote_changes)
+			w:SetCallback("OnClick", function()
+				for i = 1, NUM_CHAT_WINDOWS do
+					local cf = _G['ChatFrame'..i]
+					if not cf then break end
+					addon:CFPrint (cf, "This is frame number |cffff0000%d|r.", i)
+				end
+			end)
+			chatgroup:AddChild(w)
+			grp:AddChild(chatgroup)
+		end
+
 		-- boss mod selection
 		w = GUI:Create("Spacer")
 		w:SetFullWidth(true)
-		w:SetHeight(20)
+		w:SetHeight(2)
 		grp:AddChild(w)
 		do
 			local list = {}
@@ -1898,7 +2068,7 @@
 		-- item filters
 		w = GUI:Create("Spacer")
 		w:SetFullWidth(true)
-		w:SetHeight(20)
+		w:SetHeight(2)
 		grp:AddChild(w)
 		do
 			local warntext = "At least one of the items in the filter list was not in your game client's cache.  This is okay.  Just wait a few seconds, display some other Ouro Loot tab, and then display Options again."
@@ -1934,7 +2104,7 @@
 			w:SetEditBoxTooltip("Link items which should no longer be tracked.")
 			w:SetList(filterlist)
 			w:SetCallback("OnTextEnterPressed", function(_w, _, text)
-				local iname, ilink, iquality = GetItemInfo(strtrim(text))
+				local iname, ilink, iquality = GetItemInfo(text:trim())
 				if not iname then
 					return addon:Print("Error:  %s is not a valid item name/link!", text)
 				end
@@ -1963,7 +2133,7 @@
 			w:SetEditBoxTooltip("Link items which should be automatically marked as guild vault.")
 			w:SetList(vaultlist)
 			w:SetCallback("OnTextEnterPressed", function(_w, _, text)
-				local iname, ilink, iquality = GetItemInfo(strtrim(text))
+				local iname, ilink, iquality = GetItemInfo(text:trim())
 				if not iname then
 					return addon:Print("Error:  %s is not a valid item name/link!", text)
 				end
@@ -2425,7 +2595,7 @@
 local function eoi_st_insert_OnAccept_boss (dialog, data, data2)
 	if data.all_done then
 		-- It'll probably be the final entry in the table, but there might have
-		-- been real loot happening at the same time.
+		-- been real loot happening while the user was clicking and typing.
 		local boss_index = addon._addBossEntry{
 			kind		= 'boss',
 			bossname	= (OuroLootSV_opts.snarky_boss and addon.boss_abbrev[data.name] or data.name) or data.name,
@@ -2487,7 +2657,7 @@
 		--local real_rebroadcast, real_enabled = addon.rebroadcast, addon.enabled
 		--g_rebroadcast, g_enabled = false, true
 		data.display:Hide()
-		local loot_index = addon:CHAT_MSG_LOOT ("manual", data.recipient, data.name, data.notes)
+		local loot_index = assert(addon:CHAT_MSG_LOOT ("manual", data.recipient, data.name, data.notes))
 		--g_rebroadcast, g_enabled = real_g_rebroadcast, real_g_enabled
 		local entry = tremove(g_loot,loot_index)
 		tinsert(g_loot,data.rowindex,entry)