farmbuyer@1: local addon = select(2,...) farmbuyer@67: if addon.NOLOAD then return end farmbuyer@1: farmbuyer@1: --[[ farmbuyer@1: Purely the AceGUI-related routines, and the subroutines needed for support. farmbuyer@1: ------ Constants farmbuyer@6: ------ Globals farmbuyer@1: ------ Behind the scenes routines farmbuyer@1: ------ Main GUI Window farmbuyer@1: ------ Popup dialogs farmbuyer@1: ]] farmbuyer@1: farmbuyer@1: ------ Constants farmbuyer@1: local eoi_st_rowheight = 20 farmbuyer@83: local eoi_st_displayed_rows = math.floor(416/eoi_st_rowheight) farmbuyer@1: local eoi_st_textured_item_format = "|T%s:"..(eoi_st_rowheight-2).."|t %s[%s]|r%s" farmbuyer@84: -- This can get indexed by kind/reason/etc, and will default to lib-st's farmbuyer@84: -- default "blank" background at runtime. farmbuyer@1: local eoi_st_otherrow_bgcolortable = { farmbuyer@1: wipe = { ["r"] = 0.3, ["g"] = 0.3, ["b"] = 0.3}, farmbuyer@1: kill = { ["r"] = 0.2, ["g"] = 0.2, ["b"] = 0.2}, farmbuyer@1: time = { ["r"] = 0x0/255, ["g"] = 0x0/255, ["b"] = 1, ["a"] = 0.3}, farmbuyer@1: } farmbuyer@1: eoi_st_otherrow_bgcolortable[""] = eoi_st_otherrow_bgcolortable["kill"] farmbuyer@1: local eoi_st_otherrow_bgcolortable_default farmbuyer@1: local eoi_st_lootrow_col3_colortable = { farmbuyer@73: normal = { text = "", r = "ff", g = "ff", b = "ff" }, farmbuyer@73: shard = { text = "shard", r = "a3", g = "35", b = "ee" }, farmbuyer@73: offspec = { text = "offspec", r = "c6", g = "9b", b = "6d" }, farmbuyer@73: gvault = { text = "guild vault", r = "33", g = "ff", b = "99" }, farmbuyer@1: } farmbuyer@73: for k,v in pairs(eoi_st_lootrow_col3_colortable) do farmbuyer@73: -- for chat output by core code farmbuyer@73: v.hex = "|cff" .. v.r .. v.g .. v.b farmbuyer@73: -- for lib-st farmbuyer@73: v.r = tonumber(v.r,16)/255 farmbuyer@73: v.g = tonumber(v.g,16)/255 farmbuyer@73: v.b = tonumber(v.b,16)/255 farmbuyer@73: v.a = 1 farmbuyer@73: end farmbuyer@73: addon.disposition_colors = eoi_st_lootrow_col3_colortable farmbuyer@73: local function eoi_st_lootrow_col3_colortable_func (data, _, realrow) farmbuyer@1: local disp = data[realrow].disposition farmbuyer@73: return eoi_st_lootrow_col3_colortable[disp or 'normal'] farmbuyer@1: end farmbuyer@95: local time_column1_used_mt = { __index = { farmbuyer@1: [2] = {value=""}, farmbuyer@1: [3] = {value=""}, farmbuyer@1: } } farmbuyer@1: farmbuyer@1: farmbuyer@6: ------ Globals farmbuyer@95: local AceGUI = LibStub("AceGUI-3.0") farmbuyer@1: local flib = LibStub("LibFarmbuyer") farmbuyer@1: farmbuyer@95: local gui = { farmbuyer@95: -- These are used to build the tabgroup_tabs array fed to TabGroup, and farmbuyer@95: -- for the official source of mouseover tab titles, etc. Not completely farmbuyer@95: -- hidden because we need to reach in and fiddle too often to be worth it. farmbuyer@95: tabtexts = { farmbuyer@95: ["eoi"] = {title=[[Loot]], desc=[[Observed loot, plus boss kills and other events of interest]]}, farmbuyer@95: ["hist"] = {title=[[History]], desc=[[A short semi-permanent record]]}, farmbuyer@95: }, farmbuyer@95: taborder = { "eoi" }, farmbuyer@95: taborder_APPEND = { "hist", "help", "opt" }, farmbuyer@95: } farmbuyer@95: addon.gui_state_pointer = gui -- only during loading, then cleaned out farmbuyer@95: if addon.author_debug then farmbuyer@95: _G.OLgui = gui farmbuyer@95: end farmbuyer@95: farmbuyer@1: local g_loot = nil farmbuyer@79: local g_uniques = nil farmbuyer@1: local g_generated = nil farmbuyer@17: local window_title = "Ouro Loot" farmbuyer@47: local dirty_tabs = nil farmbuyer@1: farmbuyer@76: local error = addon.error farmbuyer@76: local assert = addon.assert farmbuyer@76: farmbuyer@56: local pairs, ipairs, tinsert, tremove, tostring, tonumber = farmbuyer@56: pairs, ipairs, table.insert, table.remove, tostring, tonumber farmbuyer@1: farmbuyer@1: local pprint, tabledump = addon.pprint, flib.tabledump farmbuyer@11: local GetItemInfo, ITEM_QUALITY_COLORS = GetItemInfo, ITEM_QUALITY_COLORS farmbuyer@90: local GetNumRaidMembers = GetNumGroupMembers or GetNumRaidMembers farmbuyer@93: local IsInRaid = IsInRaid or (function() return GetNumRaidMembers() > 0 end) farmbuyer@1: farmbuyer@1: -- En masse forward decls of symbols defined inside local blocks farmbuyer@83: local _generate_text, _populate_text_specials, _markup farmbuyer@95: local eoi_dropdownfuncs -- filled out in gui block scope farmbuyer@96: local _hide_debugging_tooltip, _build_debugging_tooltip farmbuyer@78: local _new_rebroadcast_hyperlink farmbuyer@1: farmbuyer@49: --[[ farmbuyer@49: This is a table of callback functions, each responsible for drawing a tab farmbuyer@49: into the container passed in the first argument. Special-purpose buttons farmbuyer@49: can optionally be created (mkbutton) and added to the container in the second farmbuyer@49: argument. farmbuyer@49: ]] farmbuyer@49: local tabs_OnGroupSelected = {} farmbuyer@49: local mkbutton farmbuyer@49: local tabs_OnGroupSelected_func, tabs_generated_text_OGS farmbuyer@83: -- Similarly for the popup tips on the right side of the window. farmbuyer@83: local noob_tips = {} farmbuyer@88: -- And any special handling for additional CLI arguments. farmbuyer@88: local tabs_CLI_special = {} farmbuyer@49: farmbuyer@83: do farmbuyer@83: local replacement_colors = { farmbuyer@83: ["+"]="|cffffffff", -- white farmbuyer@83: ["<"]="|cff00ff00", -- light green farmbuyer@83: [">"]="|r" } farmbuyer@83: function _markup (t) farmbuyer@83: -- wonder if it would be worth memoizing this also farmbuyer@83: return t:gsub("[%+<>]",replacement_colors) farmbuyer@83: :gsub("([^\n])\n([^\n])", "%1 %2") farmbuyer@83: :gsub("|r\n\n", "|r\n") farmbuyer@83: end farmbuyer@97: gui.markup = markup -- too useful to keep local farmbuyer@83: end farmbuyer@83: farmbuyer@1: -- Working around this bug: farmbuyer@1: -- http://forums.wowace.com/showpost.php?p=295202&postcount=31 farmbuyer@1: do farmbuyer@37: local function fix_frame_level (level, ...) farmbuyer@1: for i = 1, select("#", ...) do farmbuyer@1: local button = select(i, ...) farmbuyer@1: button:SetFrameLevel(level) farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@37: local function fix_menu_frame_levels() farmbuyer@37: local f = _G.DropDownList1 farmbuyer@1: local i = 1 farmbuyer@1: while f do farmbuyer@37: fix_frame_level (f:GetFrameLevel() + 2, f:GetChildren()) farmbuyer@1: i = i + 1 farmbuyer@1: f = _G["DropDownList"..i] farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@1: -- To fix Blizzard's bug caused by the new "self:SetFrameLevel(2);" farmbuyer@37: hooksecurefunc("UIDropDownMenu_CreateFrames", fix_menu_frame_levels) farmbuyer@1: end farmbuyer@1: farmbuyer@1: farmbuyer@1: ------ Behind the scenes routines farmbuyer@1: -- Text generation farmbuyer@1: do farmbuyer@1: local text_gen_funcs, specials_gen_funcs = {}, {} farmbuyer@1: local accumulator = {} farmbuyer@1: farmbuyer@95: local function _reg (tab_code, title, description, --[[unused]]generator, farmbuyer@95: opt_specgen, opt_noobtip, opt_cli farmbuyer@95: ) farmbuyer@95: assert(type(tab_code)=='string') farmbuyer@95: assert(type(title)=='string') farmbuyer@95: assert(type(description)=='string') farmbuyer@95: gui.tabtexts[tab_code] = { title=title, desc=description } farmbuyer@95: if not gui.suppress_taborder then farmbuyer@95: gui:tabposition_insert (tab_code) farmbuyer@95: end farmbuyer@95: if opt_specgen then farmbuyer@95: assert(type(opt_specgen)=='function') farmbuyer@95: specials_gen_funcs[tab_code] = opt_specgen farmbuyer@95: end farmbuyer@95: if opt_noobtip then farmbuyer@95: if type(opt_noobtip) == 'string' then farmbuyer@95: noob_tips[tab_code] = _markup(opt_noobtip) farmbuyer@95: elseif type(opt_noobtip) == 'function' then farmbuyer@95: noob_tips[tab_code] = opt_noobtip farmbuyer@95: else farmbuyer@95: error(("Optional new user tip argument for '%s' must be a string or function!"):format(tab_code)) farmbuyer@95: end farmbuyer@95: end farmbuyer@95: if opt_cli then farmbuyer@95: assert(type(opt_cli)=='function') farmbuyer@95: tabs_CLI_special[tab_code] = opt_cli farmbuyer@95: end farmbuyer@95: dirty_tabs = true farmbuyer@95: end farmbuyer@95: farmbuyer@1: -- Can do clever things by passing other halting points as zero farmbuyer@84: function addon:zero_printed_fenceposts (zero) farmbuyer@1: for t in pairs(text_gen_funcs) do farmbuyer@1: g_loot.printed[t] = zero or g_loot.printed[t] or 0 farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@10: function addon:registered_textgen_iter() farmbuyer@10: return pairs(text_gen_funcs) farmbuyer@10: end farmbuyer@10: farmbuyer@1: -- This function is called during load, so be careful! farmbuyer@95: function addon:register_text_generator (text_type, title, description, farmbuyer@95: generator, opt_specgen, opt_noobtip, opt_cli farmbuyer@95: ) farmbuyer@95: if self.NOLOAD then return end farmbuyer@1: if type(generator) ~= 'function' then farmbuyer@1: error(("Generator for text type '%s' must be a function!"):format(text_type)) farmbuyer@1: end farmbuyer@95: _reg (text_type, title, description, generator, opt_specgen, opt_noobtip, opt_cli) farmbuyer@1: text_gen_funcs[text_type] = generator farmbuyer@1: end farmbuyer@1: farmbuyer@84: -- These two called by tabs_generated_text_OGS farmbuyer@84: -- tabs_OnGroupSelected_func will catch propagated errors farmbuyer@1: function _generate_text (text_type) farmbuyer@1: local f = text_gen_funcs[text_type] farmbuyer@1: if not f then farmbuyer@1: error(("Generator called for unregistered text type '%s'."):format(text_type)) farmbuyer@1: end farmbuyer@1: g_generated = g_generated or {} farmbuyer@1: g_loot[text_type] = g_loot[text_type] or "" farmbuyer@1: farmbuyer@1: if g_loot.printed[text_type] >= #g_loot then return false end farmbuyer@76: assert (addon.loot_clean == #g_loot, farmbuyer@76: tostring(addon.loot_clean) .. " ~= " .. #g_loot) farmbuyer@1: -- if glc is nil, #==0 test already returned farmbuyer@1: farmbuyer@1: local ok,ret = pcall (f, text_type, g_loot, g_loot.printed[text_type], g_generated, accumulator) farmbuyer@1: if not ok then farmbuyer@1: error(("ERROR: text generator '%s' failed: %s"):format(text_type, ret)) farmbuyer@1: end farmbuyer@1: if ret then farmbuyer@1: g_loot.printed[text_type] = #g_loot farmbuyer@1: g_generated[text_type] = (g_generated[text_type] or "") .. table.concat(accumulator,'\n') .. '\n' farmbuyer@1: end farmbuyer@1: wipe(accumulator) farmbuyer@1: return ret farmbuyer@1: end farmbuyer@1: function _populate_text_specials (editbox, specials, mkb, text_type) farmbuyer@1: local f = specials_gen_funcs[text_type] farmbuyer@1: if not f then return end farmbuyer@84: local ok,ret = pcall (f, text_type, editbox, specials, mkb) farmbuyer@84: if not ok then farmbuyer@84: error(("ERROR: special widget creation for '%s' failed: %s"):format(text_type, ret)) farmbuyer@84: end farmbuyer@1: end farmbuyer@49: farmbuyer@49: -- LOD tab has been clicked on. farmbuyer@49: local function _handle_LOD (tabs_container,specials,tabtitle) farmbuyer@95: -- "tabtitle" here is the name in taborder, not the colorized string farmbuyer@95: local what = gui.tabtexts[tabtitle] farmbuyer@49: local addon_index = what.LOD farmbuyer@49: local function LOAD() farmbuyer@95: gui.tabtexts[tabtitle] = nil farmbuyer@95: gui:tabposition_remove_and_remember (tabtitle) farmbuyer@49: local loaded, whynot = LoadAddOn(addon_index) farmbuyer@95: local tabdelta = gui:tabposition_restore() farmbuyer@49: if loaded then farmbuyer@57: addon:Print("%s loaded, %d |4tab:tabs; added.", tabtitle, tabdelta) farmbuyer@49: else farmbuyer@49: what.disabled = true farmbuyer@95: gui.tabtexts[tabtitle] = what -- restore this for mouseovers farmbuyer@49: addon:Print("%s could not load (game client reason was '%s').", tabtitle, whynot) farmbuyer@49: DisableAddOn(addon_index) farmbuyer@49: end farmbuyer@49: dirty_tabs = true farmbuyer@51: return addon:OpenMainDisplayToTab(tabtitle) or addon:BuildMainDisplay() farmbuyer@49: end farmbuyer@49: addon.display:Hide() farmbuyer@49: if what.LOD_enabled then farmbuyer@49: -- totally loadable, go for it farmbuyer@49: LOAD() farmbuyer@49: else farmbuyer@49: -- was disabled at addons menu farmbuyer@49: StaticPopupDialogs["OUROL_LOD_DISABLED"] = flib.StaticPopup{ farmbuyer@57: text = tabtitle.." was disabled at the character selection screen. Do you want to enable it?", farmbuyer@49: button1 = YES, farmbuyer@49: button2 = NO, farmbuyer@49: OnAccept = function() farmbuyer@49: EnableAddOn(addon_index) farmbuyer@49: LOAD() farmbuyer@49: end, farmbuyer@49: OnCancel = function() farmbuyer@49: addon:BuildMainDisplay() farmbuyer@49: end, farmbuyer@49: OnHide = function() farmbuyer@49: StaticPopupDialogs["OUROL_LOD_DISABLED"] = nil farmbuyer@49: end, farmbuyer@49: } farmbuyer@49: StaticPopup_Show("OUROL_LOD_DISABLED") farmbuyer@49: end farmbuyer@49: end farmbuyer@49: farmbuyer@49: -- Add a clickable tab that brings the real module in. Since gui_init has farmbuyer@49: -- already been called, we flag the dirty bit and let the main building farmbuyer@49: -- routine handle it like any other plugin. farmbuyer@49: function addon:_gui_add_LOD_tab (tabtitle, folder, addon_index, enabled_p, why_not) farmbuyer@95: gui.tabtexts[tabtitle] = { farmbuyer@51: title = ("|cffff0000(%s)|r"):format(tabtitle), farmbuyer@57: desc = ("Plugin '|cffff0000%s|r' is not loaded yet. Click the tab to load it now."):format(folder), farmbuyer@49: LOD = addon_index, farmbuyer@49: LOD_enabled = enabled_p, farmbuyer@49: LOD_why_not = why_not, farmbuyer@49: } farmbuyer@49: tabs_OnGroupSelected[tabtitle] = _handle_LOD farmbuyer@95: gui:tabposition_insert (tabtitle) farmbuyer@49: dirty_tabs = true farmbuyer@49: end farmbuyer@95: farmbuyer@95: -- Registering truly arbitrary tab controls, not just text generators. farmbuyer@95: -- (This is slightly out of place, but no more so than the LOD stuff.) farmbuyer@95: -- The arguments are nearly the same as those of :register_text_generator farmbuyer@95: -- but the "generator" function is the full-blown callback and there is farmbuyer@95: -- no "specgen" (since it's handled in the main generator). farmbuyer@95: function addon:register_tab_control (tab_code, title, description, farmbuyer@95: generator, opt_noobtip, opt_cli farmbuyer@95: ) farmbuyer@95: if self.NOLOAD then return end farmbuyer@95: if type(generator) ~= 'function' then farmbuyer@95: error(("Generator for tab code '%s' must be a function!"):format(tab_code)) farmbuyer@95: end farmbuyer@95: _reg (tab_code, title, description, generator, --[[opt_specgen=]]nil, opt_noobtip, opt_cli) farmbuyer@95: tabs_OnGroupSelected[tab_code] = generator farmbuyer@95: end farmbuyer@95: function addon:register_tab_control_AT_END (...) farmbuyer@95: gui.suppress_taborder = true farmbuyer@95: self:register_tab_control(...) farmbuyer@95: gui.suppress_taborder = nil farmbuyer@95: end farmbuyer@1: end farmbuyer@1: farmbuyer@1: --[[ farmbuyer@1: The g_loot table is populated only with "behavior-relevant" data (names, farmbuyer@1: links, etc). This function runs through it and fills out the "display- farmbuyer@1: relevant" bits (icons, user-friendly labels, etc). Everything from the farmbuyer@1: loot_clean index to the end of the table is filled out, loot_clean is farmbuyer@1: updated. Override the starting point with the argument. farmbuyer@1: farmbuyer@1: XXX blizzard's scrolling update and lib-st keep finding some way of displaying farmbuyer@1: the grid without ever calling the hooked refresh, thereby skipping this farmbuyer@1: function and erroring on missing columnar data. fuckit. from now on farmbuyer@1: this function gets called everywhere, all the time, and loops over the farmbuyer@1: entire goddamn table each time. If we can't find blizz's scrollframe bugs, farmbuyer@1: we'll just work around them. Sorry for your smoking CPU. farmbuyer@1: farmbuyer@1: FIXME just move this functionality to a per-entry function and call it once farmbuyer@1: in _addlootentry. --actually no, then the columnar data won't be updated once farmbuyer@1: the backend data is changed on the fly. farmbuyer@1: ]] farmbuyer@1: do farmbuyer@1: function addon:_fill_out_eoi_data (opt_starting_index) farmbuyer@1: if #g_loot < 1 then farmbuyer@1: --pprint('_f_o_e_d', "#g_loot<1") farmbuyer@1: self.loot_clean = nil farmbuyer@1: opt_starting_index = nil farmbuyer@1: end farmbuyer@1: for i = (opt_starting_index or self.loot_clean or 1), #g_loot do farmbuyer@1: local e = g_loot[i] farmbuyer@1: if e == nil then farmbuyer@1: self.loot_clean = nil farmbuyer@1: pprint('_f_o_e_d', "index",i,"somehow still in loop past",#g_loot,"bailing") farmbuyer@1: return farmbuyer@1: end farmbuyer@1: farmbuyer@97: local display_bcast_from = self.db.profile.display_bcast_from farmbuyer@1: -- XXX FIXME a major weakness here is that we're constantly replacing farmbuyer@1: -- what's already been created. Lots of garbage. Trying to detect what farmbuyer@1: -- actually needs to be replaced is even worse. We'll live with farmbuyer@1: -- garbage for now. farmbuyer@1: if e.kind == 'loot' then farmbuyer@11: local textured = eoi_st_textured_item_format:format (e.itexture, ITEM_QUALITY_COLORS[e.quality].hex, e.itemname, e.count or "") farmbuyer@1: e.cols = { farmbuyer@1: {value = textured}, farmbuyer@1: {value = e.person}, farmbuyer@73: {} farmbuyer@1: } farmbuyer@1: -- This is horrible. Must do better. farmbuyer@1: if e.extratext then for k,v in pairs(eoi_st_lootrow_col3_colortable) do farmbuyer@1: if v.text == e.extratext then farmbuyer@73: e.disposition = k ~= 'normal' and k or nil farmbuyer@1: --e.extratext = nil, not feasible farmbuyer@1: break farmbuyer@1: end farmbuyer@1: end end farmbuyer@73: local ex = eoi_st_lootrow_col3_colortable[e.disposition or 'normal'].text farmbuyer@65: if e.bcast_from and display_bcast_from and e.extratext then farmbuyer@1: ex = e.extratext .. " (from " .. e.bcast_from .. ")" farmbuyer@65: elseif e.bcast_from and display_bcast_from then farmbuyer@73: ex = ex .. (e.disposition and " " or "") farmbuyer@73: .. "(from " .. e.bcast_from .. ")" farmbuyer@1: elseif e.extratext then farmbuyer@1: ex = e.extratext farmbuyer@1: end farmbuyer@1: e.cols[3].value = ex farmbuyer@1: farmbuyer@1: elseif e.kind == 'boss' then farmbuyer@1: local v farmbuyer@52: e.duration = e.duration or 0 -- can occasionally miss getting set farmbuyer@1: if e.reason == 'kill' then farmbuyer@1: if e.attempts == 1 then farmbuyer@1: v = "one-shot" farmbuyer@1: else farmbuyer@84: v = ("kill on %d%s attempt"):format(e.attempts or 0, farmbuyer@84: e.attempts==2 and "nd" or e.attempts==3 and "rd" or "th") farmbuyer@1: end farmbuyer@1: v = ("%s (%d:%.2d)"):format(v, math.floor(e.duration/60), math.floor(e.duration%60)) farmbuyer@1: elseif e.reason == 'wipe' then farmbuyer@1: v = ("wipe (%d:%.2d)"):format(math.floor(e.duration/60), math.floor(e.duration%60)) farmbuyer@1: end farmbuyer@1: e.cols = { farmbuyer@55: {value = e.bossname}, farmbuyer@1: {value = e.instance}, farmbuyer@1: {value = v or ""}, farmbuyer@1: } farmbuyer@1: farmbuyer@1: elseif e.kind == 'time' then farmbuyer@1: e.cols = setmetatable({ farmbuyer@1: {value=e.startday.text}, farmbuyer@1: }, time_column1_used_mt) farmbuyer@1: --[[e.cols = { farmbuyer@1: {value=e.startday.text}, farmbuyer@1: {value=""}, farmbuyer@1: {value=""}, farmbuyer@1: }]] farmbuyer@1: farmbuyer@1: end farmbuyer@1: end farmbuyer@1: self.loot_clean = #g_loot farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@1: do farmbuyer@1: function addon:_fill_out_hist_data (opt_starting_index) farmbuyer@6: local new, del = flib.new, flib.del farmbuyer@6: farmbuyer@1: -- Clearing history finishes this function with #hist==0 and hist_clean==0. farmbuyer@1: -- The next call typically detects this (#<1) and handles it. If loot is farmbuyer@1: -- recorded before then, it results in hist_clean==0 and #hist==1, which farmbuyer@1: -- breaks the first iteration of the loop. Thus, the "extra" test here: farmbuyer@1: if #self.history < 1 or self.hist_clean == 0 then farmbuyer@1: self.hist_clean = nil farmbuyer@1: opt_starting_index = nil farmbuyer@1: end farmbuyer@1: if not self.history.st then farmbuyer@6: --print"creating ST!" farmbuyer@1: self.history.st = { farmbuyer@4: --[[{ kind = "realm", farmbuyer@1: cols = setmetatable({ farmbuyer@1: { value = self.history.realm }, farmbuyer@1: }, time_column1_used_mt) farmbuyer@4: }]] farmbuyer@1: } farmbuyer@1: end farmbuyer@6: farmbuyer@6: -- for now farmbuyer@6: if self.hist_clean == #self.history then return end farmbuyer@6: farmbuyer@1: local st = self.history.st farmbuyer@6: --print("starting history loop, #st ==", #st, "#history ==", #self.history) farmbuyer@6: for i,t in ipairs(st) do farmbuyer@6: del(t.cols[1]) farmbuyer@6: del(t.cols[2]) farmbuyer@6: del(t.cols[3]) farmbuyer@6: del(t.cols) farmbuyer@6: del(t) farmbuyer@6: st[i] = nil farmbuyer@6: end farmbuyer@1: farmbuyer@6: --for i = (opt_starting_index or self.hist_clean or 1), #self.history do farmbuyer@6: local cache_okay = true farmbuyer@6: for pi,player in ipairs(self.history) do farmbuyer@6: local col1 = new() farmbuyer@6: col1.OLi = pi farmbuyer@6: col1.value = player.name -- may spiffy this up in future farmbuyer@1: farmbuyer@73: for li,unique in ipairs(player.unique) do farmbuyer@6: local col2 = new() farmbuyer@6: col2.OLi = li farmbuyer@84: col2.OLu = unique farmbuyer@6: local col3 = new() farmbuyer@73: col3.value = player.when[unique] farmbuyer@6: farmbuyer@73: local id = player.id[unique] farmbuyer@73: local itexture = GetItemIcon(id) farmbuyer@73: local iname, ilink, iquality = GetItemInfo(id) farmbuyer@4: local textured farmbuyer@4: if itexture and iname then farmbuyer@6: textured = eoi_st_textured_item_format:format (itexture, farmbuyer@73: ITEM_QUALITY_COLORS[iquality].hex, iname, player.count[unique] or "") farmbuyer@4: else farmbuyer@6: textured = eoi_st_textured_item_format:format ([[ICONS\INV_Misc_QuestionMark]], farmbuyer@19: ITEM_QUALITY_COLORS[ITEM_QUALITY_COMMON].hex, 'UNKNOWN - REDISPLAY LATER', "") farmbuyer@6: cache_okay = false farmbuyer@4: end farmbuyer@6: col2.value = textured farmbuyer@6: farmbuyer@84: -- To facilitate sharing lib-st routines between EOI and this farmbuyer@84: -- one, we do some of the same fields: 'kind' and 'itemlink'. farmbuyer@84: -- These aren't used outside of the GUI. These become our data farmbuyer@84: -- table arguments to the lib-st routines (thus 'e' locals). farmbuyer@6: local dotcols = new (col1, col2, col3) farmbuyer@6: local st_entry = new() farmbuyer@84: st_entry.kind = 'hist' farmbuyer@6: st_entry.OLwho = player.name farmbuyer@86: st_entry.OLclass = player.person_class farmbuyer@6: st_entry.cols = dotcols farmbuyer@16: st_entry.itemlink = ilink -- for onenter and onclick farmbuyer@6: tinsert (st, st_entry) farmbuyer@1: end farmbuyer@6: end farmbuyer@1: farmbuyer@6: --print("finished history loop, #st ==", #st) farmbuyer@6: self.hist_clean = cache_okay and #self.history or nil farmbuyer@1: end farmbuyer@72: end farmbuyer@6: farmbuyer@74: -- Debugging tooltip (unfortunately managed by global and semi-global state farmbuyer@74: -- rather than passing around stack parameters) farmbuyer@74: do farmbuyer@74: local debug_tt farmbuyer@74: farmbuyer@74: local _creators, _builders = {}, {} farmbuyer@73: local function _create_tooltip() farmbuyer@96: local which = assert(tonumber(gui._do_debugging_tooltip)) farmbuyer@74: if type(_creators[which]) == 'function' then farmbuyer@74: _creators[which]() farmbuyer@74: end farmbuyer@74: debug_tt = _creators[which] farmbuyer@74: end farmbuyer@74: function _build_debugging_tooltip (parent, index) farmbuyer@96: local which = assert(tonumber(gui._do_debugging_tooltip)) farmbuyer@74: if type(_builders[which]) == 'function' then farmbuyer@74: _builders[which](parent,index) farmbuyer@74: end farmbuyer@74: end farmbuyer@74: function _hide_debugging_tooltip() farmbuyer@74: if debug_tt then debug_tt:Hide() end farmbuyer@74: end farmbuyer@74: farmbuyer@74: -- 2 == /dump farmbuyer@74: _creators[2] = function() farmbuyer@74: local tt = CreateFrame("GameTooltip") farmbuyer@73: UIParentLoadAddOn("Blizzard_DebugTools") farmbuyer@73: farmbuyer@73: tt:SetBackdrop{ farmbuyer@73: bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], farmbuyer@73: edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], farmbuyer@73: tile = true, farmbuyer@73: tileSize = 8, farmbuyer@73: edgeSize = 12, farmbuyer@73: insets = { left = 2, right = 2, top = 2, bottom = 2 } farmbuyer@73: } farmbuyer@73: tt:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, farmbuyer@73: TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) farmbuyer@73: tt:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, farmbuyer@73: TOOLTIP_DEFAULT_COLOR.b) farmbuyer@73: tt:SetMovable(false) farmbuyer@73: tt:EnableMouse(false) farmbuyer@73: tt:SetFrameStrata("TOOLTIP") farmbuyer@73: tt:SetToplevel(true) farmbuyer@73: tt:SetClampedToScreen(true) farmbuyer@73: farmbuyer@73: local font = CreateFont("OuroLootDebugFont") farmbuyer@73: font:CopyFontObject(GameTooltipTextSmall) farmbuyer@73: if IsAddOnLoaded"tekticles" then -- maybe check for one of the sharedmedia things? farmbuyer@73: font:SetFont([[Interface\AddOns\tekticles\Calibri.ttf]], 9) farmbuyer@73: else farmbuyer@73: font:SetFont([[Fonts\FRIZQT__.TTF]], 9) farmbuyer@73: end farmbuyer@73: farmbuyer@73: local left, right, prevleft farmbuyer@73: -- Only create as many lines as we might need (the auto growth farmbuyer@73: -- by Add*Line does odd things sometimes). farmbuyer@73: for i = 1, math.max(DEVTOOLS_MAX_ENTRY_CUTOFF,15)+5 do farmbuyer@73: prevleft = left farmbuyer@73: left = tt:CreateFontString(nil,"ARTWORK") farmbuyer@73: right = tt:CreateFontString(nil,"ARTWORK") farmbuyer@73: left:SetFontObject(font) farmbuyer@73: right:SetFontObject(font) farmbuyer@73: tt:AddFontStrings(left,right) farmbuyer@73: if prevleft then farmbuyer@73: left:SetPoint("TOPLEFT",prevleft,"BOTTOMLEFT",0,-2) farmbuyer@73: else farmbuyer@73: left:SetPoint("TOPLEFT",10,-10) -- top line farmbuyer@73: end farmbuyer@73: right:SetPoint("RIGHT",left,"LEFT") farmbuyer@73: end farmbuyer@73: tt.AddMessage = tt.AddLine farmbuyer@73: farmbuyer@74: _creators[2] = tt farmbuyer@73: end farmbuyer@73: farmbuyer@74: _builders[2] = function (parent, index) farmbuyer@73: local e = g_loot[index]; assert(type(e)=='table') farmbuyer@74: _create_tooltip() farmbuyer@74: debug_tt:SetOwner (parent, "ANCHOR_LEFT", -15, -5) farmbuyer@74: debug_tt:ClearLines() farmbuyer@73: farmbuyer@73: local real = DEFAULT_CHAT_FRAME farmbuyer@74: DEFAULT_CHAT_FRAME = debug_tt farmbuyer@73: DevTools_Dump{ [index] = e } farmbuyer@73: DEFAULT_CHAT_FRAME = real farmbuyer@73: farmbuyer@74: debug_tt:Show() farmbuyer@73: end farmbuyer@73: farmbuyer@72: -- Now here's a thing unheard-of. A tooltip not inheriting from the big farmbuyer@72: -- memory-wasteful template, but also not intended merely for scanning farmbuyer@72: -- invisible tooltips. farmbuyer@72: -- (If this ever grows beyond a text dump, then replace it with libqtip.) farmbuyer@74: -- farmbuyer@74: -- Fields to put in the fixed-fields tooltip (maybe move these into the farmbuyer@74: -- options window if I spend too much time fiddling). farmbuyer@74: local loot = {'person', 'id', 'unique', 'disposition', 'count', 'variant'} farmbuyer@74: local boss = {'bossname', 'reason', 'instance', 'maxsize', 'duration', 'raidersnap'} farmbuyer@74: farmbuyer@74: -- 3 == fixed fields farmbuyer@74: _creators[3] = function() farmbuyer@74: local tt = CreateFrame("GameTooltip") farmbuyer@72: farmbuyer@72: tt:SetBackdrop{ farmbuyer@72: bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], farmbuyer@72: edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], farmbuyer@72: tile = true, farmbuyer@72: tileSize = 8, farmbuyer@72: edgeSize = 12, farmbuyer@72: insets = { left = 2, right = 2, top = 2, bottom = 2 } farmbuyer@72: } farmbuyer@72: tt:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, farmbuyer@72: TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) farmbuyer@72: tt:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, farmbuyer@72: TOOLTIP_DEFAULT_COLOR.b) farmbuyer@72: tt:SetMovable(false) farmbuyer@72: tt:EnableMouse(false) farmbuyer@72: tt:SetFrameStrata("TOOLTIP") farmbuyer@72: tt:SetToplevel(true) farmbuyer@72: tt:SetClampedToScreen(true) farmbuyer@72: farmbuyer@72: local font = GameTooltipTextSmall farmbuyer@72: local left, right, prevleft farmbuyer@72: -- Only create as many lines as we might need (the auto growth farmbuyer@72: -- by Add*Line does odd things sometimes). farmbuyer@72: for i = 1, math.max(#loot,#boss)+2 do farmbuyer@72: prevleft = left farmbuyer@72: left = tt:CreateFontString(nil,"ARTWORK") farmbuyer@72: right = tt:CreateFontString(nil,"ARTWORK") farmbuyer@72: left:SetFontObject(font) farmbuyer@72: right:SetFontObject(font) farmbuyer@72: tt:AddFontStrings(left,right) farmbuyer@72: if prevleft then farmbuyer@72: left:SetPoint("TOPLEFT",prevleft,"BOTTOMLEFT",0,-2) farmbuyer@72: else farmbuyer@72: left:SetPoint("TOPLEFT",10,-10) -- top line farmbuyer@72: end farmbuyer@72: right:SetPoint("RIGHT",left,"LEFT") farmbuyer@72: end farmbuyer@72: farmbuyer@74: _creators[3] = tt farmbuyer@72: end farmbuyer@72: farmbuyer@74: _builders[3] = function (parent, index) farmbuyer@72: local e = g_loot[index]; assert(type(e)=='table') farmbuyer@74: _create_tooltip() farmbuyer@74: debug_tt:SetOwner (parent, "ANCHOR_LEFT", -15, -5) farmbuyer@74: debug_tt:ClearLines() farmbuyer@72: farmbuyer@72: -- change these, change the +2 above farmbuyer@74: debug_tt:AddDoubleLine (tostring(index), tostring(e), 1,1,1) farmbuyer@74: debug_tt:AddDoubleLine ('kind', e.kind, 1,1,1) farmbuyer@72: farmbuyer@72: local source = (e.kind == 'loot' and loot) or (e.kind == 'boss' and boss) farmbuyer@72: if source then farmbuyer@72: for _,field in ipairs(source) do farmbuyer@74: debug_tt:AddDoubleLine (field, tostring(e[field]), 1,1,1, 0,156/255,1) farmbuyer@72: end farmbuyer@72: end farmbuyer@74: debug_tt:Show() farmbuyer@72: end farmbuyer@1: end farmbuyer@1: farmbuyer@78: do farmbuyer@78: local rebroadcast_map -- XXX weaken this somehow? farmbuyer@78: farmbuyer@78: local function onclick (self, ident) farmbuyer@79: -- Since an arbitrary number of insert/delete ops can happen between farmbuyer@79: -- now and (potentially) clicking on the hyperlink, we can't depend on farmbuyer@79: -- the row index. Force the uniques cache to re-search (research?) it. farmbuyer@79: local u = assert(rebroadcast_map[ident]) farmbuyer@79: local cache = g_uniques:SEARCH(u) farmbuyer@79: -- A missing history entry isn't necessarily an error here, but we farmbuyer@79: -- need a loot entry to go further. farmbuyer@79: if cache.loot then farmbuyer@79: eoi_dropdownfuncs["Rebroadcast this loot entry"](cache.loot) farmbuyer@79: else farmbuyer@79: addon:Print("...guh? Entry was recorded with tag <%s> but cannot now be found!", u) farmbuyer@79: end farmbuyer@79: -- delete the entry maybe? farmbuyer@78: end farmbuyer@78: farmbuyer@79: function _new_rebroadcast_hyperlink (u) farmbuyer@78: rebroadcast_map = rebroadcast_map or flib.new() farmbuyer@78: local clicky, ident = addon.format_hypertext( farmbuyer@78: -- same color sequence as what DBM uses to announce pizza timers, farmbuyer@78: -- which looks reasonably pleasing farmbuyer@78: [[Broadcast this entry]], "|cff3588ff", onclick) farmbuyer@79: rebroadcast_map[ident] = u farmbuyer@78: return clicky farmbuyer@78: end farmbuyer@78: end farmbuyer@78: farmbuyer@83: -- UI tips window farmbuyer@83: local hide_noobtips_frame = flib.nullfunc farmbuyer@83: local function get_noobtips_frame() farmbuyer@83: local f = CreateFrame("Frame") farmbuyer@83: f:SetBackdrop{ farmbuyer@83: bgFile = [[Interface\Tooltips\UI-Tooltip-Background]], farmbuyer@83: --bgFile = [[Interface\DialogFrame\UI-DialogBox-Background]], farmbuyer@83: edgeFile = [[Interface\Tooltips\UI-Tooltip-Border]], farmbuyer@83: --edgeFile = [[Interface\DialogFrame\UI-DialogBox-Border]], farmbuyer@83: tile = true, farmbuyer@83: tileSize = 8, farmbuyer@83: --tileSize = 32, farmbuyer@83: edgeSize = 12, farmbuyer@83: --edgeSize = 32, farmbuyer@83: insets = { left = 2, right = 2, top = 2, bottom = 2 } farmbuyer@83: --insets = { left = 11, right = 12, top = 12, bottom = 11 } farmbuyer@83: } farmbuyer@83: f:SetBackdropColor(TOOLTIP_DEFAULT_BACKGROUND_COLOR.r, farmbuyer@83: TOOLTIP_DEFAULT_BACKGROUND_COLOR.g, TOOLTIP_DEFAULT_BACKGROUND_COLOR.b) farmbuyer@83: f:SetBackdropBorderColor(TOOLTIP_DEFAULT_COLOR.r, TOOLTIP_DEFAULT_COLOR.g, farmbuyer@83: TOOLTIP_DEFAULT_COLOR.b) farmbuyer@83: f:SetMovable(false) farmbuyer@83: f:EnableMouse(false) farmbuyer@83: f:SetFrameStrata("TOOLTIP") farmbuyer@83: f:SetToplevel(true) farmbuyer@83: f:SetClampedToScreen(true) farmbuyer@83: f:SetWidth(220) farmbuyer@83: local t = f:CreateFontString (nil, "ARTWORK", "GameFontHighlightSmall") farmbuyer@83: --t:SetPoint ("TOPLEFT", f, "TOPLEFT", 14, -15) farmbuyer@83: t:SetPoint ("TOPLEFT", f, "TOPLEFT", 10, -10) farmbuyer@83: t:SetJustifyH("LEFT") farmbuyer@83: farmbuyer@83: f.text = t farmbuyer@83: f.DoTextWork = function (self, text) farmbuyer@83: self.text:SetText(text) farmbuyer@83: self.text:SetWidth (self:GetWidth() - 20) farmbuyer@83: self:SetHeight (self.text:GetHeight() + 20) farmbuyer@83: end farmbuyer@83: farmbuyer@83: get_noobtips_frame = function() return f end farmbuyer@83: hide_noobtips_frame = function() f:Hide() end farmbuyer@83: return f farmbuyer@83: end farmbuyer@83: farmbuyer@1: farmbuyer@1: ------ Main GUI Window farmbuyer@95: local _d -- display when it's open, nil when it's not farmbuyer@1: local function setstatus(txt) _d:SetStatusText(txt) end farmbuyer@1: local function statusy_OnLeave() setstatus("") end farmbuyer@1: local tabgroup_tabs farmbuyer@1: farmbuyer@1: --[[ farmbuyer@1: Controls for the tabs on the left side of the main display. farmbuyer@1: ]] farmbuyer@57: farmbuyer@57: do farmbuyer@95: --local next_insertion_position = 2 -- position in taborder farmbuyer@95: local next_insertion_position = #gui.taborder + 1 farmbuyer@57: local removed, saved_offset farmbuyer@57: farmbuyer@95: function gui:tabposition_insert (tabcode) farmbuyer@95: tinsert (gui.taborder, next_insertion_position, tabcode) farmbuyer@57: next_insertion_position = next_insertion_position + 1 farmbuyer@57: end farmbuyer@57: farmbuyer@57: -- These two functions are push/pop pairs, sort of. The first removes farmbuyer@57: -- a tab and prepares to insert more tab(s) in its place. The second farmbuyer@57: -- returns the "next tab goes here" marker back to the proper end. (And farmbuyer@57: -- doing all 3 adjustments below at once is amazingly hard to read.) farmbuyer@95: function gui:tabposition_remove_and_remember (tabcode) farmbuyer@57: assert(not removed) -- enforce stack-ish discipline farmbuyer@95: for i = 2, #gui.taborder do farmbuyer@95: if gui.taborder[i] == tabcode then farmbuyer@95: tremove (gui.taborder, i) farmbuyer@57: saved_offset = next_insertion_position - i - 1 farmbuyer@57: removed, next_insertion_position = i, i farmbuyer@57: return farmbuyer@57: end farmbuyer@57: end farmbuyer@57: error(("'%s' not used as a tab-text code"):format(tabcode)) farmbuyer@57: end farmbuyer@95: function gui:tabposition_restore() farmbuyer@57: assert(removed) farmbuyer@57: local count = next_insertion_position - removed farmbuyer@57: next_insertion_position = next_insertion_position + saved_offset farmbuyer@57: removed, saved_offset = nil, nil farmbuyer@57: return count farmbuyer@57: end farmbuyer@95: farmbuyer@95: function addon:FINISH_SPECIAL_TABS() farmbuyer@95: -- very carefully not touching next_insertion_position farmbuyer@95: for i,v in ipairs(gui.taborder_APPEND) do farmbuyer@95: gui.taborder[#gui.taborder+1] = v farmbuyer@95: end farmbuyer@95: gui.taborder_APPEND = nil farmbuyer@95: self.register_tab_control_AT_END = nil farmbuyer@95: self.FINISH_SPECIAL_TABS = nil farmbuyer@95: end farmbuyer@57: end farmbuyer@57: farmbuyer@57: -- Done at startup, and whenever we've changed the population of tabs. farmbuyer@79: function addon:gui_init (loot_pointer, uniques_pointer) farmbuyer@71: g_loot = assert(loot_pointer, "something went wrong at startup") farmbuyer@79: g_uniques = assert(uniques_pointer, "something went wrong at startup") farmbuyer@1: g_generated = nil farmbuyer@1: tabgroup_tabs = {} farmbuyer@89: window_title = "Ouro Loot " .. self.version farmbuyer@46: -- TabGroup stretches out the tabs to fill the row but only if >75% of the farmbuyer@46: -- row is already full. It turns out that not doing this looks like ass. farmbuyer@46: -- If we won't have enough tabs to trigger this on its own, pad out the tab farmbuyer@46: -- titles (not looking quite as nice, ah well) to force it to trigger. farmbuyer@95: local fmtstr = #gui.taborder > 6 and "%s" or " %s " farmbuyer@95: for i,name in ipairs(gui.taborder) do farmbuyer@49: tabgroup_tabs[i] = { farmbuyer@49: value = name, farmbuyer@95: text = fmtstr:format(gui.tabtexts[name].title), farmbuyer@95: disabled = gui.tabtexts[name].disabled, farmbuyer@49: } farmbuyer@1: -- By default, tabs are editboxes with generated text farmbuyer@49: if not tabs_OnGroupSelected[name] then farmbuyer@49: tabs_OnGroupSelected[name] = tabs_generated_text_OGS farmbuyer@1: end farmbuyer@1: end farmbuyer@47: dirty_tabs = nil farmbuyer@1: end farmbuyer@1: farmbuyer@37: --[[ farmbuyer@84: Dropdown menu handling; this has grown in ungainly directions. farmbuyer@37: ]] farmbuyer@37: -- forward decls farmbuyer@1: local eoi_editcell farmbuyer@1: farmbuyer@37: local dropdownfuncs farmbuyer@37: do farmbuyer@37: local ddf_mt = { farmbuyer@37: __index = { farmbuyer@37: -- more stuff should be moved into this table farmbuyer@37: [CLOSE] = function() CloseDropDownMenus() end, farmbuyer@37: } farmbuyer@37: } farmbuyer@37: dropdownfuncs = function(t) farmbuyer@37: return setmetatable(t, ddf_mt) farmbuyer@37: end farmbuyer@37: end farmbuyer@37: farmbuyer@1: local function dropdownmenu_handler (ddbutton, subfunc, arg) farmbuyer@84: local i = _d and _d.GetUserData and _d:GetUserData("DD index") farmbuyer@26: if i then farmbuyer@26: subfunc(i,arg) farmbuyer@95: gui.which_ST:OuroLoot_Refresh(i) farmbuyer@26: end farmbuyer@1: end farmbuyer@1: farmbuyer@1: local function gen_easymenu_table (initial, list, funcs) farmbuyer@1: for _,tag in ipairs(list) do farmbuyer@1: local name, arg, tiptext farmbuyer@1: name, tiptext = strsplit('|',tag) farmbuyer@1: name, arg = strsplit('%',name) farmbuyer@1: if name == "--" then farmbuyer@1: tinsert (initial, { farmbuyer@6: disabled = true, notCheckable = true, text = "", farmbuyer@1: }) farmbuyer@1: else farmbuyer@1: if not funcs[name] then farmbuyer@1: error(("'%s' not defined as a dropdown function"):format(name)) farmbuyer@1: end farmbuyer@1: tinsert (initial, { farmbuyer@1: text = name, farmbuyer@1: func = dropdownmenu_handler, farmbuyer@1: arg1 = funcs[name], farmbuyer@1: arg2 = arg, farmbuyer@1: notCheckable = true, farmbuyer@25: tooltipOnButton = true, farmbuyer@25: tooltipWhileDisabled = true, farmbuyer@1: tooltipTitle = tiptext and name or nil, farmbuyer@1: tooltipText = tiptext, farmbuyer@1: }) farmbuyer@1: end farmbuyer@1: end farmbuyer@1: return initial farmbuyer@1: end farmbuyer@1: farmbuyer@1: local dropdownmenuframe = CreateFrame("Frame", "OuroLootDropDownMenu", nil, "UIDropDownMenuTemplate") farmbuyer@1: farmbuyer@37: farmbuyer@37: -- Tab 1: Events Of Interest farmbuyer@37: -- This actually takes up quite a bit of the file. farmbuyer@37: eoi_dropdownfuncs = dropdownfuncs{ farmbuyer@1: df_INSERT = function(rowi,text) farmbuyer@1: local which = (text == 'loot') and "OUROL_EOI_INSERT_LOOT" or "OUROL_EOI_INSERT" farmbuyer@1: local dialog = StaticPopup_Show(which,text) farmbuyer@16: dialog.editBox:SetScript("OnTextChanged",StaticPopup_EditBoxOnTextChanged) farmbuyer@1: dialog.data = {rowindex=rowi, display=_d, kind=text} farmbuyer@1: end, farmbuyer@1: farmbuyer@1: df_DELETE = function(rowi) farmbuyer@84: local gone = tremove (g_loot, rowi) farmbuyer@1: addon:Print("Removed %s.", farmbuyer@55: gone.itemlink or gone.bossname or gone.startday.text) farmbuyer@36: if gone.kind == 'loot' and IsShiftKeyDown() then farmbuyer@84: local okay,err = addon:_delHistoryEntry (gone) farmbuyer@84: if okay then farmbuyer@86: addon:Print("Removed history entry %s from %s.", farmbuyer@86: gone.itemlink, addon:colorize(gone.person,gone.person_class)) farmbuyer@84: else farmbuyer@84: addon:Print(err) farmbuyer@84: end farmbuyer@36: end farmbuyer@1: end, farmbuyer@1: farmbuyer@1: ["Delete remaining entries for this day"] = function(rowi,kind) farmbuyer@28: -- if kind is boss, also need to stop at new timestamp farmbuyer@28: local fencepost = addon._find_timeboss_fencepost (kind, rowi) farmbuyer@1: local count = fencepost and (fencepost-rowi) or (#g_loot-rowi+1) farmbuyer@1: repeat farmbuyer@37: eoi_dropdownfuncs.df_DELETE(rowi) farmbuyer@1: count = count - 1 farmbuyer@1: until count < 1 farmbuyer@1: end, farmbuyer@1: farmbuyer@1: ["Rebroadcast this loot entry"] = function(rowi) farmbuyer@1: local e = g_loot[rowi] farmbuyer@1: -- This only works because GetItemInfo accepts multiple argument formats farmbuyer@71: addon:vbroadcast('loot', e.person, e.unique, e.itemlink, e.count, e.cols[3].value) farmbuyer@28: addon:Print("Rebroadcast entry", rowi, e.itemlink) farmbuyer@1: end, farmbuyer@1: farmbuyer@1: ["Rebroadcast this boss"] = function(rowi,kind) farmbuyer@28: -- if kind is boss, also need to stop at new timestamp farmbuyer@28: local fencepost = addon._find_timeboss_fencepost (kind, rowi) or #g_loot farmbuyer@28: -- this could be a lot of traffic, but frankly it's counterproductive farmbuyer@28: -- to try to micromanage when ChatThrottleLib is already doing so farmbuyer@28: repeat farmbuyer@28: local e = g_loot[rowi] farmbuyer@28: if e.kind == 'boss' then farmbuyer@56: addon:vbroadcast('boss', e.reason, e.bossname, e.instance) farmbuyer@28: elseif e.kind == 'loot' then farmbuyer@28: -- This only works because GetItemInfo accepts multiple argument formats farmbuyer@71: addon:vbroadcast('loot', e.person, e.unique, e.itemlink, e.count, e.cols[3].value) farmbuyer@28: end farmbuyer@55: addon:Print("Rebroadcast entry", rowi, e.itemlink or e.bossname or UNKNOWN) farmbuyer@28: rowi = rowi + 1 farmbuyer@28: until rowi >= fencepost farmbuyer@1: end, farmbuyer@1: farmbuyer@73: ["Mark as normal"] = function(rowi,disp) farmbuyer@73: addon:loot_mark_disposition ("local", rowi, disp) farmbuyer@1: end, farmbuyer@1: farmbuyer@1: ["Show only this player"] = function(rowi) farmbuyer@95: local st = assert(gui.eoiST) farmbuyer@1: _d:SetUserData("player filter name", g_loot[rowi].person) farmbuyer@1: st:SetFilter(_d:GetUserData("player filter by name")) farmbuyer@1: _d:GetUserData("eoi_filter_reset"):SetDisabled(false) farmbuyer@81: -- it'd be more futureproof to get the button and call some kind farmbuyer@81: -- of :GetText() on it, but no such function is provided by acegui farmbuyer@81: setstatus[[Use the "Reset Player Filter" button in the lower-right to return to normal.]] farmbuyer@1: end, farmbuyer@1: farmbuyer@1: ["Change from 'wipe' to 'kill'"] = function(rowi) farmbuyer@1: addon:_mark_boss_kill(rowi) farmbuyer@1: -- the fillout function called automatically will start too far down the list farmbuyer@95: gui.eoiST:OuroLoot_Refresh() farmbuyer@1: end, farmbuyer@1: farmbuyer@1: ["Edit note"] = function(rowi) farmbuyer@84: eoi_editcell (rowi, _d:GetUserData("DD cell")) farmbuyer@1: end, farmbuyer@1: farmbuyer@1: df_REASSIGN = function(rowi,to_whom) farmbuyer@81: addon:reassign_loot ("local", rowi, to_whom) farmbuyer@1: CloseDropDownMenus() -- also need to close parent menu farmbuyer@1: end, farmbuyer@1: ["Enter name..."] = function(rowi) farmbuyer@25: CloseDropDownMenus() -- also need to close parent menu farmbuyer@1: local dialog = StaticPopup_Show "OUROL_REASSIGN_ENTER" farmbuyer@1: dialog.data = {index=rowi, display=_d} farmbuyer@1: end, farmbuyer@1: } farmbuyer@1: -- Would be better to move the %arg to this list rather than below, but farmbuyer@1: -- that's a lot of extra effort that doesn't buy much in return. farmbuyer@37: eoi_dropdownfuncs["Delete this loot event"] = eoi_dropdownfuncs.df_DELETE farmbuyer@37: eoi_dropdownfuncs["Delete this boss event"] = eoi_dropdownfuncs.df_DELETE farmbuyer@37: eoi_dropdownfuncs["Insert new loot entry"] = eoi_dropdownfuncs.df_INSERT farmbuyer@37: eoi_dropdownfuncs["Insert new boss kill event"] = eoi_dropdownfuncs.df_INSERT farmbuyer@37: eoi_dropdownfuncs["Mark as disenchanted"] = eoi_dropdownfuncs["Mark as normal"] farmbuyer@37: eoi_dropdownfuncs["Mark as guild vault"] = eoi_dropdownfuncs["Mark as normal"] farmbuyer@37: eoi_dropdownfuncs["Mark as offspec"] = eoi_dropdownfuncs["Mark as normal"] farmbuyer@37: eoi_dropdownfuncs["Delete remaining entries for this boss"] = farmbuyer@37: eoi_dropdownfuncs["Delete remaining entries for this day"] farmbuyer@37: eoi_dropdownfuncs["Rebroadcast this day"] = eoi_dropdownfuncs["Rebroadcast this boss"] farmbuyer@1: local eoi_time_dropdown = gen_easymenu_table( farmbuyer@1: {{ farmbuyer@1: -- this is the dropdown title, text filled in on the fly farmbuyer@1: isTitle = true, farmbuyer@1: notClickable = true, farmbuyer@1: notCheckable = true, farmbuyer@1: }}, farmbuyer@1: { farmbuyer@25: "Rebroadcast this day%time|Broadcasts everything from here down until a new day.", farmbuyer@84: "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.", farmbuyer@25: "Insert new loot entry%loot|Inserts new loot above this one, prompting you for information.", farmbuyer@25: "Insert new boss kill event%boss|Inserts new event above this one, prompting you for information.", farmbuyer@1: CLOSE farmbuyer@37: }, eoi_dropdownfuncs) farmbuyer@1: local eoi_loot_dropdown = gen_easymenu_table( farmbuyer@1: {{ farmbuyer@1: -- this is the dropdown title, text filled in on the fly farmbuyer@1: notClickable = true, farmbuyer@1: notCheckable = true, farmbuyer@1: }}, farmbuyer@1: { farmbuyer@1: "Mark as disenchanted%shard", farmbuyer@1: "Mark as offspec%offspec", farmbuyer@1: "Mark as guild vault%gvault", farmbuyer@25: "Mark as normal|This is the default. Selecting any 'Mark as ' action blanks out extra notes about who broadcast this entry, etc.", farmbuyer@1: "--", farmbuyer@1: "Rebroadcast this loot entry|Sends this loot event, including special notes, as if it just happened.", farmbuyer@84: "Delete this loot event|Permanent, no going back!\n\nHold down the Shift key to also delete the corresponding entry from player's History.", farmbuyer@84: "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.", farmbuyer@25: "Insert new loot entry%loot|Inserts new loot above this one, prompting you for information.", farmbuyer@25: "Insert new boss kill event%boss|Inserts new event above this one, prompting you for information.", farmbuyer@25: "Edit note|Same as double-clicking in the notes column.", farmbuyer@1: "--", farmbuyer@1: CLOSE farmbuyer@37: }, eoi_dropdownfuncs) farmbuyer@1: local eoi_player_dropdown = gen_easymenu_table( farmbuyer@1: { farmbuyer@1: { farmbuyer@1: -- this is the dropdown title, text filled in on the fly farmbuyer@1: isTitle = true, farmbuyer@1: notClickable = true, farmbuyer@1: notCheckable = true, farmbuyer@1: }, farmbuyer@1: { farmbuyer@1: text = "Reassign to...", farmbuyer@1: hasArrow = true, farmbuyer@1: --menuList = filled in in the fly, farmbuyer@25: tooltipOnButton = true, farmbuyer@25: tooltipWhileDisabled = true, farmbuyer@1: }, farmbuyer@1: }, farmbuyer@1: { farmbuyer@1: "Show only this player", farmbuyer@1: CLOSE farmbuyer@37: }, eoi_dropdownfuncs) farmbuyer@1: local eoi_boss_dropdown = gen_easymenu_table( farmbuyer@1: {{ farmbuyer@1: -- this is the dropdown title, text filled in on the fly farmbuyer@1: isTitle = true, farmbuyer@1: notClickable = true, farmbuyer@1: notCheckable = true, farmbuyer@1: }}, farmbuyer@1: { farmbuyer@83: "Change from 'wipe' to 'kill'|Also collapses previous wipe entries.", -- KILLWIPE farmbuyer@28: "Rebroadcast this boss%boss|Broadcasts the kill event and all subsequent loot until next boss.", farmbuyer@1: "Delete this boss event|Permanent, no going back!", farmbuyer@84: "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.", farmbuyer@25: "Insert new loot entry%loot|Inserts new loot above this one, prompting you for information.", farmbuyer@25: "Insert new boss kill event%boss|Inserts new event above this one, prompting you for information.", farmbuyer@1: "--", farmbuyer@1: CLOSE farmbuyer@37: }, eoi_dropdownfuncs) farmbuyer@1: farmbuyer@84: --[[ quoted verbatim from lib-st docs (table->stable for obvious reasons): farmbuyer@1: rowFrame This is the UI Frame table for the row. farmbuyer@1: cellFrame This is the UI Frame table for the cell in the row. farmbuyer@1: data This is the data table supplied to the scrolling table (in case you lost it :) ) farmbuyer@1: cols This is the cols table supplied to the scrolling table (again, in case you lost it :) ) farmbuyer@1: row This is the number of the UI row that the event was triggered for.
ex. If your scrolling table only shows ten rows, this number will be a number between 1 and 10. farmbuyer@1: realrow This is the exact row index (after sorting and filtering) in the data table of what data is displayed in the row you triggered the event in. (NOT the UI row!) farmbuyer@1: column This is the index of which column the event was triggered in. farmbuyer@84: stable This is a reference to the scrollingtable table. farmbuyer@1: ... Any arguments generated by the '''NORMAL''' Blizzard event triggered by the frame are passed as is. farmbuyer@1: ]] farmbuyer@84: local function eoi_st_OnEnter (rowFrame, cellFrame, data, cols, row, realrow, column, stable, motion) farmbuyer@1: if (row == nil) or (realrow == nil) then return end -- mouseover column header farmbuyer@1: local e = data[realrow] farmbuyer@1: local kind = e.kind farmbuyer@72: local tt = GameTooltip -- can this be hoisted? does GT ever get securely replaced? farmbuyer@1: farmbuyer@96: if gui._do_debugging_tooltip and column == 1 and kind ~= 'hist' then farmbuyer@72: _build_debugging_tooltip (cellFrame, realrow) farmbuyer@72: end farmbuyer@84: if (kind == 'loot' and column == 1) or (kind == 'hist' and column == 2) then farmbuyer@72: tt:SetOwner (cellFrame, "ANCHOR_RIGHT", -20, 0) farmbuyer@19: if e.cache_miss then farmbuyer@72: tt:ClearLines() farmbuyer@72: tt:AddLine("Missing Cache Data") farmbuyer@72: tt:AddLine([[Wait a few seconds, then type]], 0.8, 0.8, 0.8, 1) farmbuyer@81: tt:AddLine([[/ouroloot fix cache]], 0, 1, 64/255, nil) farmbuyer@72: tt:AddLine([[and redisplay this window.]], 0.8, 0.8, 0.8, 1) farmbuyer@72: tt:Show() farmbuyer@19: elseif e.itemlink then farmbuyer@72: tt:SetHyperlink (e.itemlink) farmbuyer@16: end farmbuyer@1: farmbuyer@1: elseif kind == 'loot' and column == 2 then farmbuyer@72: tt:SetOwner (cellFrame, "ANCHOR_BOTTOMRIGHT", -50, 5) farmbuyer@72: tt:ClearLines() farmbuyer@72: tt:AddLine(e.person.." Loot:") farmbuyer@1: local counter = 0 farmbuyer@1: for i,e2 in ipairs(data) do farmbuyer@1: if e2.person == e.person then -- would be awesome to test for alts farmbuyer@1: if counter > 10 then farmbuyer@72: tt:AddLine("...") farmbuyer@1: break farmbuyer@1: else farmbuyer@1: -- textures screw up too badly, strip them farmbuyer@1: local textured = e2.cols[1].value farmbuyer@1: local space = textured:find(" ") farmbuyer@72: tt:AddLine(textured:sub(space+1)) farmbuyer@1: counter = counter + 1 farmbuyer@1: end farmbuyer@1: end farmbuyer@1: end farmbuyer@72: tt:Show() farmbuyer@1: farmbuyer@1: elseif kind == 'loot' and column == 3 then farmbuyer@1: setstatus(e.cols[column].value) farmbuyer@1: farmbuyer@1: end farmbuyer@1: farmbuyer@1: return false -- continue with default highlighting behavior farmbuyer@1: end farmbuyer@84: local function eoi_st_OnLeave (rowFrame, cellFrame, data, cols, row, realrow, column, stable, motion) farmbuyer@1: GameTooltip:Hide() farmbuyer@72: _hide_debugging_tooltip() farmbuyer@1: if row and realrow and data[realrow].kind ~= 'loot' then farmbuyer@84: stable:SetHighLightColor (rowFrame, eoi_st_otherrow_bgcolortable[data[realrow].reason or data[realrow].kind]) farmbuyer@1: return true -- do not do anything further farmbuyer@1: else farmbuyer@1: --setstatus("") farmbuyer@1: return false -- continue with default un-highlighting behavior farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@84: local function eoi_st_OnClick (rowFrame, cellFrame, data, cols, row, realrow, column, stable, button, down) farmbuyer@1: if (row == nil) or (realrow == nil) then return true end -- click column header, suppress reordering farmbuyer@1: local e = data[realrow] farmbuyer@1: local kind = e.kind farmbuyer@1: farmbuyer@1: -- Check for shift-clicking a loot line farmbuyer@84: if IsModifiedClick("CHATLINK") and kind == 'loot' and column == 1 farmbuyer@16: then farmbuyer@1: ChatEdit_InsertLink (e.itemlink) farmbuyer@1: return true -- do not do anything further farmbuyer@1: end farmbuyer@1: farmbuyer@1: -- Remaining actions are all right-click farmbuyer@1: if button ~= "RightButton" then return true end farmbuyer@84: _d:SetUserData("DD index", realrow) farmbuyer@1: farmbuyer@1: if kind == 'loot' and (column == 1 or column == 3) then farmbuyer@84: _d:SetUserData("DD cell", cellFrame) farmbuyer@1: eoi_loot_dropdown[1].text = e.itemlink farmbuyer@1: EasyMenu (eoi_loot_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU") farmbuyer@1: farmbuyer@1: elseif kind == 'loot' and column == 2 then farmbuyer@1: eoi_player_dropdown[1].text = e.person farmbuyer@1: local raiders = {} farmbuyer@1: for i = 1, GetNumRaidMembers() do farmbuyer@1: tinsert (raiders, (GetRaidRosterInfo(i))) farmbuyer@1: end farmbuyer@1: table.sort(raiders) farmbuyer@1: for i = 1, #raiders do farmbuyer@1: local name = raiders[i] farmbuyer@1: raiders[i] = { farmbuyer@1: text = name, farmbuyer@1: func = dropdownmenu_handler, farmbuyer@37: arg1 = eoi_dropdownfuncs.df_REASSIGN, farmbuyer@1: arg2 = name, farmbuyer@1: notCheckable = true, farmbuyer@1: } farmbuyer@1: end farmbuyer@1: eoi_player_dropdown[2].menuList = farmbuyer@37: gen_easymenu_table (raiders, {"Enter name...",CLOSE}, eoi_dropdownfuncs) farmbuyer@25: if e.disposition == 'shard' or e.disposition == 'gvault' then farmbuyer@25: eoi_player_dropdown[2].disabled = true farmbuyer@25: eoi_player_dropdown[2].tooltipTitle = "Cannot Reassign" farmbuyer@25: eoi_player_dropdown[2].tooltipText = "You must first mark this item as 'normal' or 'offspec' before reassignment." farmbuyer@25: else farmbuyer@25: eoi_player_dropdown[2].disabled = nil farmbuyer@25: eoi_player_dropdown[2].tooltipTitle = nil farmbuyer@25: eoi_player_dropdown[2].tooltipText = nil farmbuyer@25: end farmbuyer@1: EasyMenu (eoi_player_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU") farmbuyer@1: farmbuyer@1: elseif kind == 'boss' then farmbuyer@55: eoi_boss_dropdown[1].text = e.bossname farmbuyer@83: -- KILLWIPE: update '2' if this is not the 2nd entry in eoi_boss_dropdown farmbuyer@83: eoi_boss_dropdown[2].tooltipWhileDisabled = nil farmbuyer@83: eoi_boss_dropdown[2].disabled = e.reason ~= 'wipe' and true or nil farmbuyer@1: EasyMenu (eoi_boss_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU") farmbuyer@1: farmbuyer@1: elseif kind == 'time' then farmbuyer@1: eoi_time_dropdown[1].text = e.startday.text farmbuyer@1: EasyMenu (eoi_time_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU") farmbuyer@1: farmbuyer@1: end farmbuyer@1: farmbuyer@1: return true -- do not do anything further farmbuyer@1: end farmbuyer@1: farmbuyer@1: function eoi_editcell (row_index, cell_frame) farmbuyer@1: local e = g_loot[row_index] farmbuyer@1: if not e then return end -- how the hell could we get this far? farmbuyer@1: local celldata = e.cols[3] farmbuyer@95: local box = AceGUI:Create("EditBox") farmbuyer@1: box:SetText(celldata.value) farmbuyer@1: box:SetUserData("old show", box.editbox:GetScript("OnShow")) farmbuyer@1: box:SetUserData("old escape", box.editbox:GetScript("OnEscapePressed")) farmbuyer@1: box.editbox:SetScript("OnShow", box.editbox.SetFocus) farmbuyer@1: box.editbox:SetScript("OnEscapePressed", function(_be) farmbuyer@1: _be:ClearFocus() farmbuyer@1: _be.obj:Release() farmbuyer@1: end) farmbuyer@1: box:SetCallback("OnEnterPressed", function(_b,event,value) farmbuyer@1: e.extratext = value farmbuyer@1: celldata.value = value farmbuyer@1: e.bcast_from = nil -- things get screwy if this field is still present. sigh. farmbuyer@1: e.extratext_byhand = true farmbuyer@1: value = value and value:match("^(x%d+)") farmbuyer@1: if value then e.count = value end farmbuyer@1: _b:Release() farmbuyer@95: return gui.eoiST:OuroLoot_Refresh(row_index) farmbuyer@1: end) farmbuyer@1: box:SetCallback("OnRelease", function(_b) farmbuyer@1: _b.editbox:ClearFocus() farmbuyer@1: _b.editbox:SetScript("OnShow", _b:GetUserData("old show")) farmbuyer@1: _b.editbox:SetScript("OnEscapePressed", _b:GetUserData("old escape")) farmbuyer@1: setstatus("") farmbuyer@1: end) farmbuyer@1: box.frame:SetAllPoints(cell_frame) farmbuyer@1: box.frame:SetParent(cell_frame) farmbuyer@1: box.frame:SetFrameLevel(cell_frame:GetFrameLevel()+1) farmbuyer@1: box.frame:Show() farmbuyer@1: setstatus("Press Enter or click Okay to accept changes, or press Escape to cancel them.") farmbuyer@1: end farmbuyer@1: farmbuyer@84: local function eoi_st_OnDoubleClick (rowFrame, cellFrame, data, cols, row, realrow, column, stable, button) farmbuyer@1: if (row == nil) or (realrow == nil) then return true end -- they clicked on column header, suppress reordering farmbuyer@1: local e = data[realrow] farmbuyer@1: local kind = e.kind farmbuyer@1: farmbuyer@84: --_d:SetUserData("DD index", realrow) farmbuyer@1: if kind == 'loot' and column == 3 and button == "LeftButton" then farmbuyer@1: eoi_editcell (realrow, cellFrame) farmbuyer@1: end farmbuyer@1: farmbuyer@1: return true -- do not do anything further farmbuyer@1: end farmbuyer@1: farmbuyer@1: -- Used for EOI column 2 and Hist column 1. Both are player name columns. farmbuyer@84: local function eoi_st_col2_DoCellUpdate (rowFrame, cellFrame, data, cols, row, realrow, column, fShow, stable) farmbuyer@1: if not fShow then farmbuyer@1: cellFrame.text:SetText("") farmbuyer@1: if cellFrame.icontexture then farmbuyer@1: cellFrame.icontexture:Hide() farmbuyer@1: end farmbuyer@1: return farmbuyer@1: end farmbuyer@1: farmbuyer@1: local e = data[realrow] farmbuyer@1: local cell = e.cols[column] farmbuyer@1: farmbuyer@1: cellFrame.text:SetText(cell.value) farmbuyer@1: farmbuyer@1: if e.person_class then farmbuyer@1: local icon farmbuyer@1: if cellFrame.icontexture then farmbuyer@1: icon = cellFrame.icontexture farmbuyer@1: else farmbuyer@1: icon = cellFrame:CreateTexture(nil,"BACKGROUND") farmbuyer@1: icon:SetPoint("LEFT", cellFrame, "LEFT") farmbuyer@1: icon:SetHeight(eoi_st_rowheight-4) farmbuyer@1: icon:SetWidth(eoi_st_rowheight-4) farmbuyer@1: icon:SetTexture("Interface\\Glues\\CharacterCreate\\UI-CharacterCreate-Classes") farmbuyer@1: cellFrame.icontexture = icon farmbuyer@1: end farmbuyer@1: icon:SetTexCoord(unpack(CLASS_ICON_TCOORDS[e.person_class])) farmbuyer@1: icon:Show() farmbuyer@1: cellFrame.text:SetPoint("LEFT", icon, "RIGHT", 1, 0) farmbuyer@86: local color = addon.class_colors[e.person_class] farmbuyer@92: cellFrame.text:SetTextColor(color.r,color.g,color.b,color.a) farmbuyer@1: else farmbuyer@1: if cellFrame.icontexture then farmbuyer@1: cellFrame.icontexture:Hide() farmbuyer@1: cellFrame.text:SetPoint("LEFT", cellFrame, "LEFT") farmbuyer@1: end farmbuyer@73: cellFrame.text:SetTextColor(1,1,1,1) farmbuyer@1: end farmbuyer@1: farmbuyer@1: --if e.kind ~= 'loot' then farmbuyer@1: stable:SetHighLightColor (rowFrame, eoi_st_otherrow_bgcolortable[e.reason or e.kind or ""]) farmbuyer@1: --else farmbuyer@84: -- stable:SetHighLightColor (rowFrame, table:GetDefaultHighlightBlank()) farmbuyer@1: --end farmbuyer@1: end farmbuyer@1: farmbuyer@1: local eoi_st_cols = { farmbuyer@1: { -- col 1 farmbuyer@1: name = "Item", farmbuyer@1: width = 250, farmbuyer@1: }, farmbuyer@1: { -- col 2 farmbuyer@1: name = "Player", farmbuyer@1: width = 130, farmbuyer@1: DoCellUpdate = eoi_st_col2_DoCellUpdate, farmbuyer@1: }, farmbuyer@1: { -- col 3 farmbuyer@1: name = "Notes", farmbuyer@3: width = 250, farmbuyer@73: color = eoi_st_lootrow_col3_colortable_func, farmbuyer@1: }, farmbuyer@1: } farmbuyer@1: farmbuyer@6: local player_filter_all farmbuyer@6: local player_filter_by_name = function (st, e) farmbuyer@1: if e.kind ~= 'loot' then return true end farmbuyer@1: return e.person == _d:GetUserData("player filter name") farmbuyer@1: end farmbuyer@1: farmbuyer@1: -- Tab 1: Events Of Interest (implementation) farmbuyer@1: tabs_OnGroupSelected["eoi"] = function(ocontainer,specials) farmbuyer@1: if (not addon.rebroadcast) and (not addon.enabled) and (#g_loot < 1) then farmbuyer@40: addon.dprint('flow', "Nothing to show in first tab, skipping creation") farmbuyer@40: return farmbuyer@1: end farmbuyer@1: farmbuyer@1: -- The first time this function is called, we set up a persistent ST farmbuyer@1: -- object and store it. Any other delayed setup work is done, and then farmbuyer@1: -- this function replaces itself with a smaller, sleeker, sexier one. farmbuyer@1: -- This function will later be garbage collected. farmbuyer@1: local ST = LibStub("ScrollingTable"):CreateST(eoi_st_cols,eoi_st_displayed_rows,eoi_st_rowheight) farmbuyer@95: gui.eoiST = assert(ST) farmbuyer@1: if addon.author_debug then farmbuyer@1: _G.OLST = ST farmbuyer@1: end farmbuyer@1: farmbuyer@1: if not eoi_st_otherrow_bgcolortable_default then farmbuyer@1: eoi_st_otherrow_bgcolortable_default = ST:GetDefaultHighlightBlank() farmbuyer@1: setmetatable(eoi_st_otherrow_bgcolortable, {__index = function (bg, key) farmbuyer@1: return eoi_st_otherrow_bgcolortable_default farmbuyer@1: end}) farmbuyer@1: end farmbuyer@1: farmbuyer@1: -- Calling SetData breaks (trying to call Refresh) if g_loot hasn't gone farmbuyer@1: -- through this loop. farmbuyer@1: addon:_fill_out_eoi_data(1) farmbuyer@1: -- safety check begin farmbuyer@1: for i,e in ipairs(g_loot) do farmbuyer@1: if type(e.cols) ~= 'table' then farmbuyer@1: addon:Print("ARGH, index",i,"bad in eoi_OGS, type",type(e.cols), farmbuyer@55: "entry kind", e.kind, "data", e.itemname or e.bossname or e.startday.text, farmbuyer@55: "-- please take a screenshot and send to Farmbuyer@US-Kilrogg.") farmbuyer@1: tabledump(e) farmbuyer@1: end farmbuyer@1: end farmbuyer@1: -- safety check end farmbuyer@1: ST:SetData(g_loot) farmbuyer@1: ST:RegisterEvents{ farmbuyer@1: OnEnter = eoi_st_OnEnter, farmbuyer@1: OnLeave = eoi_st_OnLeave, farmbuyer@1: OnClick = eoi_st_OnClick, farmbuyer@1: OnDoubleClick = eoi_st_OnDoubleClick, farmbuyer@1: } farmbuyer@1: farmbuyer@1: -- We want a single "update and redraw" function for the ST. Also, the farmbuyer@1: -- given refresh function is badly named and does nothing; the actual farmbuyer@1: -- function is SortData (also badly named when no sorting is being done), farmbuyer@1: -- which unconditionally calls the *hooked* Refresh. farmbuyer@1: local oldrefresh = ST.Refresh farmbuyer@1: ST.Refresh = function (self, opt_index) farmbuyer@1: addon:_fill_out_eoi_data(opt_index) farmbuyer@1: return oldrefresh(self) farmbuyer@1: end farmbuyer@1: ST.OuroLoot_Refresh = function (self, opt_index) farmbuyer@1: addon:_fill_out_eoi_data(opt_index) farmbuyer@1: -- safety check begin farmbuyer@1: for i,e in ipairs(g_loot) do farmbuyer@1: if type(e.cols) ~= 'table' then farmbuyer@4: addon:Print("ARGH, index",i,"bad in eoi refresh, refreshed at", opt_index, "type",type(e.cols), farmbuyer@55: "entry kind", e.kind, "data", e.itemname or e.bossname or e.startday.text, farmbuyer@55: "-- please take a screenshot and send to Farmbuyer@US-Kilrogg.") farmbuyer@1: tabledump(e) farmbuyer@1: end farmbuyer@1: end farmbuyer@1: -- safety check end farmbuyer@1: self:SortData() -- calls hooked refresh farmbuyer@1: end farmbuyer@1: farmbuyer@1: -- No need to keep creating function closures that all just "return true", farmbuyer@1: -- instead we grab the one made inside lib-st. There's no "get filter" API farmbuyer@1: -- so we just reach inside. farmbuyer@6: player_filter_all = ST.Filter farmbuyer@1: farmbuyer@1: -- Now set up the future drawing function... farmbuyer@1: tabs_OnGroupSelected["eoi"] = function(container,specials) farmbuyer@95: local st_widget = AceGUI:Create("lib-st") farmbuyer@95: local st = assert(gui.eoiST) farmbuyer@1: farmbuyer@95: gui.which_ST = st farmbuyer@84: farmbuyer@1: -- This is actually required each time farmbuyer@6: _d:SetUserData ("player filter clear", player_filter_all) farmbuyer@6: _d:SetUserData ("player filter by name", player_filter_by_name) farmbuyer@1: farmbuyer@1: st:OuroLoot_Refresh() farmbuyer@1: st_widget:WrapST(st) farmbuyer@3: st_widget.head_offset = 15 farmbuyer@3: st_widget.tail_offset = 0 farmbuyer@1: farmbuyer@97: if gui.opts.scroll_to_bottom then farmbuyer@1: local scrollbar = _G[st.scrollframe:GetName().."ScrollBar"] farmbuyer@1: if scrollbar then farmbuyer@1: local _,max = scrollbar:GetMinMaxValues() farmbuyer@1: scrollbar:SetValue(max) -- also calls hooked Refresh farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@1: container:SetLayout("Fill") farmbuyer@1: container:AddChild(st_widget) farmbuyer@1: farmbuyer@42: local b farmbuyer@42: --[===[ b = mkbutton("Generate Header", farmbuyer@42: [[]]) farmbuyer@42: b:SetFullWidth(true) farmbuyer@42: b:SetCallback("OnClick", function (_b) farmbuyer@42: end) farmbuyer@42: specials:AddChild(b) ]===] farmbuyer@42: farmbuyer@42: b = mkbutton('eoi_filter_reset', "Reset Player Filter", farmbuyer@1: [[Return to showing complete loot information.]]) farmbuyer@1: b:SetFullWidth(true) farmbuyer@1: b:SetCallback("OnClick", function (_b) farmbuyer@95: gui.eoiST:SetFilter(player_filter_all) farmbuyer@1: _b:SetDisabled(true) farmbuyer@1: end) farmbuyer@6: b:SetDisabled(st.Filter == player_filter_all) farmbuyer@1: specials:AddChild(b) farmbuyer@1: farmbuyer@95: -- FIXME iterate over the new raiders table instead farmbuyer@1: local people = { "" } farmbuyer@93: for i = 1, GetNumRaidMembers() do farmbuyer@1: tinsert(people,(GetRaidRosterInfo(i))) farmbuyer@1: end farmbuyer@1: table.sort(people) farmbuyer@1: local initial farmbuyer@1: for i,n in ipairs(people) do farmbuyer@1: if n == addon.sharder then initial = i end farmbuyer@1: end farmbuyer@1: b = mkbutton("Dropdown", nil, "", farmbuyer@1: [[If set, items received by this person will be automatically marked as disenchanted.]]) farmbuyer@1: b:SetFullWidth(true) farmbuyer@1: b:SetLabel("Auto-mark as shard:") farmbuyer@1: b:SetList(people) farmbuyer@1: b:SetValue(initial or 1) farmbuyer@1: b:SetCallback("OnValueChanged", function(_dd,event,choice) farmbuyer@1: addon.sharder = (choice ~= 1) and people[choice] or nil farmbuyer@1: end) farmbuyer@1: specials:AddChild(b) farmbuyer@1: farmbuyer@42: b = mkbutton('eoi_bcast_req', "Request B'casters", farmbuyer@1: [[Sends out a request for others to enable loot rebroadcasting if they have not already done so.]]) farmbuyer@1: b:SetFullWidth(true) farmbuyer@1: b:SetCallback("OnClick", function () farmbuyer@1: addon:Print("Sending request!") farmbuyer@1: addon.requesting = true farmbuyer@1: addon:broadcast('bcast_req') farmbuyer@1: end) farmbuyer@1: b:SetDisabled(not addon.enabled) farmbuyer@1: specials:AddChild(b) farmbuyer@1: end farmbuyer@1: -- ...and call it. farmbuyer@1: return tabs_OnGroupSelected["eoi"](ocontainer,specials) farmbuyer@1: end farmbuyer@83: noob_tips["eoi"] = _markup[[ farmbuyer@83: while over an item link to paste it into chat. farmbuyer@83: farmbuyer@83: -click any row to display a dropdown menu. The menu is different for farmbuyer@83: the Player column than it is for the Item/Notes columns, and different for farmbuyer@83: loot entries than it is for other rows.]] farmbuyer@92: --tabs_CLI_special["eoi"] = function (name) farmbuyer@92: -- -- try and scroll to a specific boss/player? farmbuyer@92: --end farmbuyer@1: farmbuyer@37: farmbuyer@1: -- Tab 2/3 (generated text) farmbuyer@1: function tabs_generated_text_OGS (container, specials, text_kind) farmbuyer@1: container:SetLayout("Fill") farmbuyer@95: local box = AceGUI:Create("MultiLineEditBox") farmbuyer@1: box:SetFullWidth(true) farmbuyer@1: box:SetFullHeight(true) farmbuyer@1: box:SetLabel("Pressing the Escape key while typing will return keystroke control to the usual chat window.") farmbuyer@1: box:DisableButton(true) farmbuyer@1: addon:_fill_out_eoi_data(1) farmbuyer@1: farmbuyer@1: -- Update the savedvar copy of the text before presenting it for editing, farmbuyer@1: -- then save it again when editing finishes. This way if the user goes farmbuyer@1: -- offline while editing, at least the unedited version is saved instead farmbuyer@1: -- of all the new text being lost entirely. (Yes, it's happened.) farmbuyer@1: -- farmbuyer@1: -- No good local-ish place to store the cursor position that will also farmbuyer@1: -- survive the entire display being released. Abuse the generated text farmbuyer@1: -- cache for this purpose. farmbuyer@1: local pos = text_kind.."_pos" farmbuyer@1: if _generate_text(text_kind) then farmbuyer@1: g_loot[text_kind] = g_loot[text_kind] .. g_generated[text_kind] farmbuyer@1: g_generated[text_kind] = nil farmbuyer@1: end farmbuyer@1: box:SetText(g_loot[text_kind]) farmbuyer@1: box.editBox:SetCursorPosition(g_generated[pos] or 0) farmbuyer@1: box.editBox:SetScript("OnShow", box.editBox.SetFocus) farmbuyer@1: box:SetCallback("OnRelease", function(_box) farmbuyer@1: box.editBox:ClearFocus() farmbuyer@1: g_loot[text_kind] = _box:GetText() farmbuyer@1: g_generated[pos] = _box.editBox:GetCursorPosition() farmbuyer@1: end) farmbuyer@1: container:AddChild(box) farmbuyer@1: farmbuyer@1: local w = mkbutton("Regenerate", farmbuyer@1: [[+DISCARD> all text in this tab, and regenerate it from the current loot information.]]) farmbuyer@1: w:SetFullWidth(true) farmbuyer@1: w:SetDisabled ((#g_loot == 0) and (box:GetText() == "")) farmbuyer@1: w:SetCallback("OnClick", function(_w) farmbuyer@1: box:SetText("") farmbuyer@1: g_loot[text_kind] = "" farmbuyer@1: g_loot.printed[text_kind] = 0 farmbuyer@1: g_generated.last_instance = nil farmbuyer@1: g_generated[pos] = nil farmbuyer@95: addon:Print("'%s' has been regenerated.", gui.tabtexts[text_kind].title) farmbuyer@1: return addon:redisplay() farmbuyer@1: end) farmbuyer@1: specials:AddChild(w) farmbuyer@95: if addon:get_plugin(text_kind) then farmbuyer@95: local pname = addon:get_plugin(text_kind):GetName() farmbuyer@58: w = mkbutton("Reset SVs & ReloadUI", farmbuyer@59: ([[ Reset savedvariables for %s plugin back to defaults, and trigger a UI reload.]]):format(pname)) farmbuyer@58: w:SetFullWidth(true) farmbuyer@58: w:SetCallback("OnClick", function(_w) farmbuyer@58: _G['OuroLoot'..pname..'_opts'] = nil farmbuyer@58: ReloadUI() farmbuyer@58: end) farmbuyer@58: specials:AddChild(w) farmbuyer@58: end farmbuyer@1: _populate_text_specials (box, specials, mkbutton, text_kind) farmbuyer@1: end farmbuyer@1: farmbuyer@37: farmbuyer@1: -- Tab 4: History farmbuyer@1: -- Much of the implementation here follows a similar desgin for the first farmbuyer@4: -- tab's handling of ST objects. We will even reuse its controlling tables farmbuyer@4: -- when feasible. farmbuyer@37: local histST, hist_dropdownfuncs farmbuyer@84: local hist_normal_status = farmbuyer@84: [[Click on a row to view all history for that player only. (Click column headers to re-sort.)]] farmbuyer@84: local hist_name_status = farmbuyer@84: [[Right-click on any row to return to normal history display.]] farmbuyer@84: farmbuyer@84: local history_filter_by_recent = function (st, e) farmbuyer@84: if e.kind ~= 'hist' then return true end farmbuyer@84: return e.cols[2].OLi == 1 farmbuyer@84: end farmbuyer@84: farmbuyer@84: local history_filter_who farmbuyer@84: local history_filter_by_name = function (st, e) farmbuyer@84: if e.kind ~= 'hist' then return true end farmbuyer@84: return e.OLwho == history_filter_who farmbuyer@84: end farmbuyer@1: farmbuyer@37: hist_dropdownfuncs = dropdownfuncs{ farmbuyer@87: ["Delete this loot event from history"] = function()--rowi farmbuyer@84: local h = _d:GetUserData("DD history entry") farmbuyer@87: local numleft,err = addon:_delHistoryEntry (h.cols[2].OLu, h.itemlink) farmbuyer@87: if numleft then farmbuyer@86: addon:Print("Removed history entry %s from %s.", farmbuyer@86: h.itemlink, addon:colorize(h.OLwho,h.OLclass)) farmbuyer@87: if numleft < 1 then farmbuyer@87: history_filter_who = nil farmbuyer@92: histST:SetFilter(history_filter_by_recent) farmbuyer@87: setstatus(hist_normal_status) farmbuyer@87: end farmbuyer@84: else farmbuyer@84: addon:Print(err) farmbuyer@84: end farmbuyer@84: end, farmbuyer@84: farmbuyer@87: ["Delete this player's entire loot history"] = function()--rowi farmbuyer@84: local h = _d:GetUserData("DD history entry") farmbuyer@84: local name = h.OLwho farmbuyer@84: local player_i = addon.history.byname[name] farmbuyer@84: local gone = tremove (addon.history, player_i) farmbuyer@84: assert(gone.name == name) farmbuyer@84: addon:_build_history_names() farmbuyer@86: addon:Print("Removed player %s from history (%d total entries).", farmbuyer@86: addon:colorize(name,gone.person_class), #gone.unique) farmbuyer@37: end, farmbuyer@37: } farmbuyer@84: local hist_general_dropdown = gen_easymenu_table( farmbuyer@84: {{ farmbuyer@84: -- this is the dropdown title, text filled in on the fly farmbuyer@84: isTitle = true, farmbuyer@84: notClickable = true, farmbuyer@84: notCheckable = true, farmbuyer@84: }}, farmbuyer@84: { farmbuyer@84: "Delete this player's entire loot history|Permanent, no going back!", farmbuyer@84: "--", farmbuyer@84: CLOSE farmbuyer@84: }, hist_dropdownfuncs) farmbuyer@84: local hist_specific_dropdown = gen_easymenu_table( farmbuyer@37: {{ farmbuyer@37: -- this is the dropdown title, text filled in on the fly farmbuyer@37: notClickable = true, farmbuyer@37: notCheckable = true, farmbuyer@37: }}, farmbuyer@37: { farmbuyer@84: "Delete this loot event from history|Permanent, no going back!", farmbuyer@37: "--", farmbuyer@37: CLOSE farmbuyer@37: }, hist_dropdownfuncs) farmbuyer@6: farmbuyer@84: -- Loot column farmbuyer@84: --[[ farmbuyer@84: local function hist_st_col2_DoCellUpdate (rowFrame, cellFrame, data, cols, row, realrow, column, fShow, stable) farmbuyer@84: end]] farmbuyer@84: farmbuyer@84: -- Formatted timestamp column farmbuyer@84: local function hist_st_col3_DoCellUpdate (rowFrame, cellFrame, data, cols, row, realrow, column, fShow, stable) farmbuyer@84: if not fShow then farmbuyer@84: cellFrame.text:SetText("") farmbuyer@84: return farmbuyer@84: end farmbuyer@84: farmbuyer@84: local h = data[realrow] farmbuyer@84: local cell = h.cols[column] farmbuyer@84: farmbuyer@84: cellFrame.text:SetText(cell.value) farmbuyer@84: cellFrame.text:SetTextColor(1,1,1,1) farmbuyer@84: farmbuyer@84: --stable:SetHighLightColor (rowFrame, eoi_st_otherrow_bgcolortable[h.kind]) farmbuyer@84: stable:SetHighLightColor (rowFrame, eoi_st_otherrow_bgcolortable_default) farmbuyer@84: end farmbuyer@84: farmbuyer@84: local function hist_st_OnClick (rowFrame, cellFrame, data, cols, row, realrow, column, stable, button, down) farmbuyer@84: if (row == nil) or (realrow == nil) then return false end -- click column header, do default resorting farmbuyer@84: local h = data[realrow] farmbuyer@84: assert(h.kind=='hist') farmbuyer@84: farmbuyer@84: -- Four button combinations we need to care about: farmbuyer@84: farmbuyer@84: -- Shift-left pastes loot farmbuyer@84: if IsModifiedClick("CHATLINK") and column == 2 then farmbuyer@84: ChatEdit_InsertLink (h.itemlink) farmbuyer@84: return true -- do not do anything further farmbuyer@84: end farmbuyer@84: farmbuyer@84: _d:SetUserData("DD index", realrow) farmbuyer@84: _d:SetUserData("DD history entry", h) farmbuyer@84: farmbuyer@84: -- The rest depends on whether we're filtering (focused in on a specific farmbuyer@84: -- player) or not. farmbuyer@84: if history_filter_who then farmbuyer@84: -- Shift-right opens a menu farmbuyer@84: if IsShiftKeyDown() and button == "RightButton" then farmbuyer@84: hist_specific_dropdown[1].text = h.itemlink farmbuyer@84: EasyMenu (hist_specific_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU") farmbuyer@84: farmbuyer@84: -- Right goes back to normal mode farmbuyer@84: elseif button == "RightButton" then farmbuyer@84: history_filter_who = nil farmbuyer@84: stable:SetFilter(history_filter_by_recent) farmbuyer@84: setstatus(hist_normal_status) farmbuyer@84: end farmbuyer@84: farmbuyer@84: else -- not focused farmbuyer@84: -- Shift-right opens a menu farmbuyer@84: if IsShiftKeyDown() and button == "RightButton" then farmbuyer@84: hist_general_dropdown[1].text = h.OLwho farmbuyer@84: EasyMenu (hist_general_dropdown, dropdownmenuframe, cellFrame, 0, 0, "MENU") farmbuyer@84: farmbuyer@84: -- Left focuses on a specific player farmbuyer@84: elseif button == "LeftButton" then farmbuyer@84: history_filter_who = h.OLwho farmbuyer@84: stable:SetFilter(history_filter_by_name) farmbuyer@84: setstatus(hist_name_status) farmbuyer@84: end farmbuyer@84: end farmbuyer@84: farmbuyer@84: return true -- do not do anything further farmbuyer@84: end farmbuyer@84: farmbuyer@84: --[[ farmbuyer@84: local function hist_st_OnDoubleClick (rowFrame, cellFrame, data, cols, row, realrow, column, stable, button) farmbuyer@84: if (row == nil) or (realrow == nil) then return true end -- they clicked on column header, suppress reordering farmbuyer@84: local h = data[realrow] farmbuyer@84: assert(h.kind=='hist') farmbuyer@84: farmbuyer@84: return true -- do not do anything further farmbuyer@84: end]] farmbuyer@84: farmbuyer@37: local hist_st_cols = { farmbuyer@37: { -- col 1 farmbuyer@37: name = "Player", farmbuyer@37: width = 130, farmbuyer@37: DoCellUpdate = eoi_st_col2_DoCellUpdate, farmbuyer@37: }, farmbuyer@37: { -- col 2 farmbuyer@37: name = "Most Recent Loot", farmbuyer@37: width = 250, farmbuyer@84: --DoCellUpdate = hist_st_col2_DoCellUpdate, farmbuyer@37: }, farmbuyer@37: { -- col 3 farmbuyer@37: name = "When", farmbuyer@37: width = 250, farmbuyer@37: DoCellUpdate = hist_st_col3_DoCellUpdate, farmbuyer@37: defaultsort = "asc", farmbuyer@37: sort = "asc", farmbuyer@37: sortnext = 1, farmbuyer@37: }, farmbuyer@37: } farmbuyer@37: farmbuyer@37: -- Tab 4: History (implementation) farmbuyer@37: tabs_OnGroupSelected["hist"] = function(container,specials) farmbuyer@37: histST = LibStub("ScrollingTable"):CreateST(hist_st_cols,eoi_st_displayed_rows,eoi_st_rowheight) farmbuyer@95: gui.histST = histST farmbuyer@37: if addon.author_debug then farmbuyer@37: _G.OLHST = histST farmbuyer@1: end farmbuyer@1: farmbuyer@37: if not eoi_st_otherrow_bgcolortable_default then farmbuyer@37: eoi_st_otherrow_bgcolortable_default = histST:GetDefaultHighlightBlank() farmbuyer@37: setmetatable(eoi_st_otherrow_bgcolortable, {__index = function (bg, key) farmbuyer@37: return eoi_st_otherrow_bgcolortable_default farmbuyer@37: end}) farmbuyer@1: end farmbuyer@1: farmbuyer@37: addon:_build_history_names() farmbuyer@37: addon:_fill_out_hist_data(1) farmbuyer@37: histST:SetData(addon.history.st) farmbuyer@37: histST:RegisterEvents{ farmbuyer@37: OnEnter = eoi_st_OnEnter, farmbuyer@37: OnLeave = eoi_st_OnLeave, farmbuyer@37: OnClick = hist_st_OnClick, farmbuyer@37: --OnDoubleClick = hist_st_OnDoubleClick, farmbuyer@37: } farmbuyer@37: local oldrefresh = histST.Refresh farmbuyer@37: histST.Refresh = function (self, opt_index) farmbuyer@37: addon:_fill_out_hist_data(opt_index) farmbuyer@37: return oldrefresh(self) farmbuyer@37: end farmbuyer@37: histST.OuroLoot_Refresh = function (self, opt_index) farmbuyer@37: addon:_fill_out_hist_data(opt_index) farmbuyer@37: self:SortData() -- calls hooked refresh farmbuyer@6: end farmbuyer@6: farmbuyer@37: histST:SetFilter(history_filter_by_recent) farmbuyer@6: farmbuyer@37: -- Zaps history for the given realm, or the current (current-playing farmbuyer@37: -- realm, not currently-displayed realm) one if not specified. farmbuyer@37: local function reset_current_realm (opt_realmname) farmbuyer@37: local r = assert(opt_realmname or GetRealmName()) farmbuyer@37: -- new .history table: farmbuyer@37: addon.history_all[r] = addon:_prep_new_history_category (nil, r) farmbuyer@37: addon.history = addon.history_all[r] farmbuyer@37: addon.hist_clean = nil farmbuyer@37: -- new .history.st table: farmbuyer@37: histST:OuroLoot_Refresh() farmbuyer@37: histST:SetData(addon.history.st) farmbuyer@37: end farmbuyer@6: farmbuyer@1: tabs_OnGroupSelected["hist"] = function(container,specials) farmbuyer@95: local st_widget = AceGUI:Create("lib-st") farmbuyer@95: gui.which_ST = histST farmbuyer@37: histST:OuroLoot_Refresh() farmbuyer@37: st_widget:WrapST(histST) farmbuyer@37: st_widget.head_offset = 15 farmbuyer@37: st_widget.tail_offset = 0 farmbuyer@37: container:SetLayout("Fill") farmbuyer@37: container:AddChild(st_widget) farmbuyer@37: setstatus(hist_normal_status) farmbuyer@1: farmbuyer@37: local b farmbuyer@37: do farmbuyer@37: local realms,current = {},1 farmbuyer@37: for realmname,histtable in pairs(addon.history_all) do farmbuyer@37: if type(histtable) == 'table' then farmbuyer@37: tinsert(realms,realmname) farmbuyer@37: if addon.history == histtable then current = #realms end farmbuyer@4: end farmbuyer@4: end farmbuyer@37: b = mkbutton("Dropdown", nil, "", [[Which realm to display]]) farmbuyer@1: b:SetFullWidth(true) farmbuyer@37: b:SetLabel() -- required even when empty, see ace3 ticket #234 farmbuyer@37: b:SetList(realms) farmbuyer@37: b:SetValue(current) farmbuyer@37: b:SetCallback("OnValueChanged", function(_dd,event,choice) farmbuyer@37: local r = realms[choice] farmbuyer@37: addon.history = addon:_prep_new_history_category (addon.history_all[r], r) farmbuyer@37: addon.hist_clean = nil farmbuyer@6: histST:OuroLoot_Refresh() farmbuyer@6: histST:SetData(addon.history.st) farmbuyer@37: -- Reset filters to normal farmbuyer@37: history_filter_who = nil farmbuyer@37: histST:SetFilter(history_filter_by_recent) farmbuyer@37: setstatus(hist_normal_status) farmbuyer@1: return addon:redisplay() farmbuyer@1: end) farmbuyer@1: specials:AddChild(b) farmbuyer@37: end farmbuyer@1: farmbuyer@95: --[[ b = AceGUI:Create("Spacer") b:SetFullWidth(true) b:SetHeight(10) specials:AddChild(b) ]] farmbuyer@4: farmbuyer@37: b = mkbutton("Regenerate", farmbuyer@37: [[Erases all history entries from the displayed realm, and regenerates it from current loot information.]]) farmbuyer@37: b:SetFullWidth(true) farmbuyer@37: b:SetDisabled (#addon.history == 0) farmbuyer@37: b:SetCallback("OnClick", function(_b) farmbuyer@37: local dialog = StaticPopup_Show("OUROL_HIST_REGEN", addon.history.realm) farmbuyer@37: dialog.data = addon farmbuyer@37: dialog.data2 = function(_addon) farmbuyer@37: _addon:rewrite_history (_addon.history.realm) farmbuyer@37: histST:OuroLoot_Refresh() farmbuyer@37: histST:SetData(_addon.history.st) farmbuyer@37: end farmbuyer@37: end) farmbuyer@37: specials:AddChild(b) farmbuyer@1: farmbuyer@37: b = mkbutton('hist_clear', "Clear Realm History", farmbuyer@37: [[|cffff1010Erases absolutely all> history entries from the displayed realm.]]) farmbuyer@37: b:SetFullWidth(true) farmbuyer@37: b:SetCallback("OnClick", function (_b) farmbuyer@37: local dialog = StaticPopup_Show("OUROL_HIST_CLEAR", addon.history.realm) farmbuyer@37: dialog.data = addon farmbuyer@37: dialog.data2 = function(_addon) farmbuyer@37: reset_current_realm(_addon.history.realm) farmbuyer@37: end farmbuyer@37: end) farmbuyer@37: specials:AddChild(b) farmbuyer@37: farmbuyer@37: b = mkbutton('hist_clear_all', "Clear All History", farmbuyer@37: [[|cffff1010Erases absolutely all> history entries from ALL realms.]]) farmbuyer@37: b:SetFullWidth(true) farmbuyer@37: b:SetCallback("OnClick", function (_b) farmbuyer@37: local dialog = StaticPopup_Show("OUROL_HIST_CLEAR", "ALL realms") farmbuyer@37: dialog.data = addon farmbuyer@37: dialog.data2 = function(_addon) farmbuyer@37: _addon.history_all = {} farmbuyer@37: reset_current_realm() farmbuyer@37: end farmbuyer@37: end) farmbuyer@37: specials:AddChild(b) farmbuyer@37: farmbuyer@37: b = mkbutton('hist_clear_old', "Clear Older", farmbuyer@75: [[Preserves only the latest loot entries for players on the displayed realm, removing all earlier ones.]]) farmbuyer@37: b:SetFullWidth(true) farmbuyer@37: b:SetCallback("OnClick", function (_b) farmbuyer@75: local dialog = StaticPopup_Show("OUROL_HIST_PREEN", '', addon.history.realm, addon) farmbuyer@37: dialog.data = addon farmbuyer@75: dialog.data2 = function (_addon, howmany) farmbuyer@75: _addon:preen_history (_addon.history.realm, howmany) farmbuyer@37: _addon.hist_clean = nil farmbuyer@37: histST:OuroLoot_Refresh() farmbuyer@37: end farmbuyer@37: end) farmbuyer@37: specials:AddChild(b) farmbuyer@1: end farmbuyer@37: return tabs_OnGroupSelected["hist"](container,specials) farmbuyer@1: end farmbuyer@83: noob_tips["hist"] = _markup[[ farmbuyer@83: -click a row to see all history for that player. -click any row farmbuyer@83: to return to showing all players. farmbuyer@83: farmbuyer@83: while over an item link to paste it into chat. farmbuyer@83: any row to display a dropdown menu.]] farmbuyer@95: -- '/ol hi pla' -> set filter on Playername farmbuyer@88: tabs_CLI_special["hist"] = function (name) farmbuyer@88: name = '^'..name -- already tolower'd by onslash farmbuyer@88: for _,player in ipairs(addon.history) do farmbuyer@88: if player.name:lower():find(name) then farmbuyer@88: history_filter_who = player.name farmbuyer@88: histST:SetFilter(history_filter_by_name) farmbuyer@88: setstatus(hist_name_status) farmbuyer@88: break farmbuyer@88: end farmbuyer@88: end farmbuyer@88: -- If nothing found, reset to normal or just leave alone? farmbuyer@88: end farmbuyer@1: farmbuyer@37: farmbuyer@6: -- Tab 5: Help (content in verbage.lua) farmbuyer@1: farmbuyer@37: farmbuyer@96: -- Tab 6: Options (content in options.lua) farmbuyer@1: farmbuyer@1: farmbuyer@1: -- Simply to avoid recreating the same function over and over farmbuyer@1: local tabs_OnGroupSelected_func_args = { [2] = "OnGroupSelected" } farmbuyer@1: tabs_OnGroupSelected_func = function (tabs,event,group) farmbuyer@1: tabs_OnGroupSelected_func_args[1] = tabs farmbuyer@1: tabs_OnGroupSelected_func_args[3] = group farmbuyer@83: hide_noobtips_frame() farmbuyer@1: tabs:ReleaseChildren() farmbuyer@1: local spec = tabs:GetUserData("special buttons group") farmbuyer@1: spec:ReleaseChildren() farmbuyer@95: local h = AceGUI:Create("Heading") farmbuyer@1: h:SetFullWidth(true) farmbuyer@95: h:SetText(gui.tabtexts[group].title) farmbuyer@1: spec:AddChild(h) farmbuyer@76: do farmbuyer@76: addon.sender_list.sort() farmbuyer@76: local fmt = "Received broadcast data from %d |4player:players;." farmbuyer@76: if addon.history_suppress then farmbuyer@76: -- this is the druid class color reworked into hex farmbuyer@76: fmt = fmt .. " |cffff7d0aHistory recording suppressed.|r" farmbuyer@76: end farmbuyer@76: tabs.titletext:SetFormattedText (fmt, addon.sender_list.activeI) farmbuyer@76: end farmbuyer@81: local status,err = pcall (tabs_OnGroupSelected[group], tabs, spec, group) farmbuyer@81: if not status then farmbuyer@81: addon:horrible_horrible_error(err) farmbuyer@81: end farmbuyer@97: if gui.opts.gui_noob then farmbuyer@83: local tip = noob_tips[group] farmbuyer@83: if type(tip) == 'function' then farmbuyer@83: tip = tip() farmbuyer@83: end farmbuyer@83: if type(tip) == 'string' and tip ~= "" then farmbuyer@83: local w = get_noobtips_frame() farmbuyer@83: w:SetParent (_d.content) farmbuyer@83: w:ClearAllPoints() farmbuyer@83: w:SetPoint("BOTTOMLEFT", _d.frame, "BOTTOMRIGHT", 3, 3) farmbuyer@83: w:Show() farmbuyer@83: w:DoTextWork(tip) farmbuyer@83: end farmbuyer@83: end farmbuyer@1: --[====[ farmbuyer@1: Unfortunately, :GetHeight() called on anything useful out of a TabGroup farmbuyer@1: returns the static default size (about 50 pixels) until the refresh farmbuyer@1: cycle *after* all the frames are shown. Trying to fix it up after a farmbuyer@1: single OnUpdate doesn't work either. So for now it's all hardcoded. farmbuyer@1: farmbuyer@83: Using this to determine the actual height of the usable area. (Will farmbuyer@83: error until an ST is shown, which only happens if it's tracking, etc.) farmbuyer@83: 416 pixels farmbuyer@1: if group == "eoi" then farmbuyer@1: local stframe = tabs.children[1].frame farmbuyer@1: print(stframe:GetTop(),"-",stframe:GetBottom(),"=", farmbuyer@1: stframe:GetTop()-stframe:GetBottom()) farmbuyer@1: print(stframe:GetRight(),"-",stframe:GetLeft(),"=", farmbuyer@1: stframe:GetRight()-stframe:GetLeft()) farmbuyer@1: end farmbuyer@1: ]====] farmbuyer@1: end farmbuyer@1: farmbuyer@1: --[[ farmbuyer@1: mkbutton ("WidgetType", 'display key', "Text On Widget", "the mouseover display text") farmbuyer@1: mkbutton ( [Button] 'display key', "Text On Widget", "the mouseover display text") farmbuyer@1: mkbutton ( [Button] [text] "Text On Widget", "the mouseover display text") farmbuyer@1: ]] farmbuyer@83: function mkbutton (opt_widget_type, opt_key, label, status) farmbuyer@83: if not label then farmbuyer@83: opt_widget_type, opt_key, label, status = "Button", opt_widget_type, opt_widget_type, opt_key farmbuyer@83: elseif not status then farmbuyer@83: opt_widget_type, opt_key, label, status = "Button", opt_widget_type, opt_key, label farmbuyer@1: end farmbuyer@95: local button = assert(AceGUI:Create(opt_widget_type)) farmbuyer@83: if button.SetText then button:SetText(tostring(label)) end farmbuyer@83: status = _markup(status) farmbuyer@83: button:SetCallback("OnEnter", function() setstatus(status) end) -- maybe factor that closure out farmbuyer@83: button:SetCallback("OnLeave", statusy_OnLeave) farmbuyer@83: -- retrieval key may be specified as nil if all the parameters are given farmbuyer@83: if opt_key then _d:SetUserData (opt_key, button) end farmbuyer@83: return button farmbuyer@1: end farmbuyer@96: gui.mkbutton = mkbutton farmbuyer@1: farmbuyer@1: --[[ farmbuyer@1: Creates the main window. farmbuyer@1: ]] farmbuyer@1: function addon:BuildMainDisplay (opt_tabselect) farmbuyer@1: if self.display then farmbuyer@1: -- try to get everything to update, rebuild, refresh... ugh, no farmbuyer@1: self.display:Hide() farmbuyer@1: end farmbuyer@92: if self.NOLOAD then farmbuyer@92: -- don't even try farmbuyer@92: return farmbuyer@92: end farmbuyer@1: farmbuyer@25: -- This probably causes taint... hm. farmbuyer@25: local prev_fade_time = UIDROPDOWNMENU_SHOW_TIME farmbuyer@25: UIDROPDOWNMENU_SHOW_TIME = 4 farmbuyer@25: farmbuyer@47: if dirty_tabs then farmbuyer@84: -- pointers known to be good by now, pass them back in farmbuyer@84: self:gui_init (g_loot, g_uniques) farmbuyer@47: self:zero_printed_fenceposts() farmbuyer@47: end farmbuyer@97: gui.opts = self.db.profile farmbuyer@47: farmbuyer@95: local display = AceGUI:Create("Frame") farmbuyer@1: _d = display farmbuyer@1: self.display = display farmbuyer@17: display:SetTitle(window_title) farmbuyer@1: display:SetStatusText(self.status_text) farmbuyer@1: display:SetLayout("Flow") farmbuyer@16: display:SetStatusTable{width=900,height=550} -- default height is 500 farmbuyer@47: display:EnableResize(false) farmbuyer@96: display:SetUserData("GUI state",gui) farmbuyer@1: display:SetCallback("OnClose", function(_display) farmbuyer@25: UIDROPDOWNMENU_SHOW_TIME = prev_fade_time farmbuyer@83: hide_noobtips_frame() farmbuyer@95: _d = nil farmbuyer@1: self.display = nil farmbuyer@95: AceGUI:Release(_display) farmbuyer@6: flib.clear() farmbuyer@1: collectgarbage() farmbuyer@1: end) farmbuyer@1: farmbuyer@1: ----- Right-hand panel farmbuyer@1: local rhs_width = 0.20 farmbuyer@95: local control = AceGUI:Create("SimpleGroup") farmbuyer@1: control:SetLayout("Flow") farmbuyer@1: control:SetRelativeWidth(rhs_width) farmbuyer@1: control.alignoffset = 25 farmbuyer@1: control:PauseLayout() farmbuyer@1: local h,b farmbuyer@1: farmbuyer@1: --- Main --- farmbuyer@95: h = AceGUI:Create("Heading") farmbuyer@1: h:SetFullWidth(true) farmbuyer@1: h:SetText("Main") farmbuyer@1: control:AddChild(h) farmbuyer@1: farmbuyer@1: do farmbuyer@1: b = mkbutton("Dropdown", nil, "", farmbuyer@1: [[Enable full tracking, only rebroadcasting, or disable activity altogether.]]) farmbuyer@1: b:SetFullWidth(true) farmbuyer@1: b:SetLabel("On/Off:") farmbuyer@1: b:SetList{"Full Tracking", "Broadcasting", "Disabled"} farmbuyer@1: b:SetValue(self.enabled and 1 or (self.rebroadcast and 2 or 3)) farmbuyer@1: b:SetCallback("OnValueChanged", function(_w,event,choice) farmbuyer@1: if choice == 1 then self:Activate() farmbuyer@1: elseif choice == 2 then self:Activate(nil,true) farmbuyer@1: else self:Deactivate() farmbuyer@1: end farmbuyer@1: _w = display:GetUserData('comm_ident') farmbuyer@1: if _w and _w:IsVisible() then farmbuyer@1: _w:SetDisabled(self.enabled or self.rebroadcast) farmbuyer@1: end farmbuyer@1: _w = display:GetUserData('eoi_bcast_req') farmbuyer@1: if _w and _w:IsVisible() then farmbuyer@1: _w:SetDisabled(not self.enabled) farmbuyer@1: end farmbuyer@1: end) farmbuyer@1: control:AddChild(b) farmbuyer@1: end farmbuyer@1: farmbuyer@1: b = mkbutton("Dropdown", 'threshold', "", farmbuyer@1: [[Items greater than or equal to this quality will be tracked/rebroadcast.]]) farmbuyer@1: b:SetFullWidth(true) farmbuyer@1: b:SetLabel("Threshold:") farmbuyer@1: b:SetList(self.thresholds) farmbuyer@1: b:SetValue(self.threshold) farmbuyer@1: b:SetCallback("OnValueChanged", function(_dd,event,choice) farmbuyer@1: self:SetThreshold(choice) farmbuyer@1: end) farmbuyer@1: control:AddChild(b) farmbuyer@1: farmbuyer@4: b = mkbutton("Clear Loot", farmbuyer@1: [[+Erases> all current loot information and generated text (but not saved texts).]]) farmbuyer@1: b:SetFullWidth(true) farmbuyer@1: b:SetCallback("OnClick", function() farmbuyer@1: StaticPopup_Show("OUROL_CLEAR").data = self farmbuyer@1: end) farmbuyer@1: control:AddChild(b) farmbuyer@1: farmbuyer@95: b = AceGUI:Create("Spacer") farmbuyer@1: b:SetFullWidth(true) farmbuyer@16: b:SetHeight(10) farmbuyer@1: control:AddChild(b) farmbuyer@1: farmbuyer@1: --[[ farmbuyer@1: --- Saved Texts --- farmbuyer@1: [ Save Current As... ] farmbuyer@1: saved1 farmbuyer@1: saved2 farmbuyer@1: ... farmbuyer@1: [ Load ] [ Delete ] farmbuyer@1: ]] farmbuyer@95: h = AceGUI:Create("Heading") farmbuyer@1: h:SetFullWidth(true) farmbuyer@1: h:SetText("Saved Texts") farmbuyer@1: control:AddChild(h) farmbuyer@1: b = mkbutton("Save Current As...", farmbuyer@1: [[Save forum/attendance/etc texts for later retrieval. Main loot information not included.]]) farmbuyer@1: b:SetFullWidth(true) farmbuyer@1: b:SetCallback("OnClick", function() farmbuyer@1: StaticPopup_Show "OUROL_SAVE_SAVEAS" farmbuyer@1: _d:Hide() farmbuyer@1: end) farmbuyer@1: control:AddChild(b) farmbuyer@1: farmbuyer@16: do farmbuyer@95: local scontainer = AceGUI:Create("SimpleGroup") farmbuyer@16: scontainer:SetFullWidth(true) farmbuyer@16: scontainer:SetFullHeight(false) farmbuyer@16: scontainer:SetAutoAdjustHeight(false) farmbuyer@16: scontainer:SetHeight(40) -- no relative height available anymore farmbuyer@16: scontainer:SetLayout("Fill") farmbuyer@95: local scroll = AceGUI:Create("ScrollFrame") farmbuyer@16: scroll:SetLayout("List") farmbuyer@16: local saved = self:check_saved_table(--[[silent_on_empty=]]true) farmbuyer@16: if saved then for i,s in ipairs(saved) do farmbuyer@95: local il = AceGUI:Create("InteractiveLabel") farmbuyer@16: il:SetFullWidth(true) farmbuyer@16: il:SetText(s.name) farmbuyer@16: il:SetUserData("num",i) farmbuyer@16: il:SetHighlight(1,1,1,0.4) farmbuyer@16: local str = ("%s %d entries %s"):format(s.date,s.count,s.name) farmbuyer@16: il:SetCallback("OnEnter", function() setstatus(str) end) farmbuyer@16: il:SetCallback("OnLeave", statusy_OnLeave) farmbuyer@16: il:SetCallback("OnClick", function(_il) farmbuyer@16: local prev = _d:GetUserData("saved selection") farmbuyer@16: if prev then farmbuyer@16: prev.highlight:Hide() farmbuyer@16: prev:SetColor() farmbuyer@16: end farmbuyer@16: _il:SetColor(0,1,0) farmbuyer@16: _il.highlight:Show() farmbuyer@16: _d:SetUserData("saved selection",_il) farmbuyer@16: _d:GetUserData("Load"):SetDisabled(false) farmbuyer@16: _d:GetUserData("Delete"):SetDisabled(false) farmbuyer@16: end) farmbuyer@16: scroll:AddChild(il) farmbuyer@16: end end farmbuyer@16: scontainer:AddChild(scroll) farmbuyer@16: control:AddChild(scontainer) farmbuyer@16: end farmbuyer@1: farmbuyer@1: b = mkbutton("Load", farmbuyer@1: [[Load previously saved text. +REPLACES> all current loot information!]]) farmbuyer@1: b:SetRelativeWidth(0.5) farmbuyer@1: b:SetCallback("OnClick", function() farmbuyer@1: local num = _d:GetUserData("saved selection"):GetUserData("num") farmbuyer@1: self:save_restore(num) farmbuyer@1: self:BuildMainDisplay() farmbuyer@1: end) farmbuyer@1: b:SetDisabled(true) farmbuyer@1: control:AddChild(b) farmbuyer@1: b = mkbutton("Delete", farmbuyer@1: [[Delete previously saved text.]]) farmbuyer@1: b:SetRelativeWidth(0.5) farmbuyer@1: b:SetCallback("OnClick", function() farmbuyer@1: local num = _d:GetUserData("saved selection"):GetUserData("num") farmbuyer@1: self:save_delete(num) farmbuyer@1: self:BuildMainDisplay() farmbuyer@1: end) farmbuyer@1: b:SetDisabled(true) farmbuyer@1: control:AddChild(b) farmbuyer@1: farmbuyer@95: b = AceGUI:Create("Spacer") farmbuyer@1: b:SetFullWidth(true) farmbuyer@16: b:SetHeight(10) farmbuyer@1: control:AddChild(b) farmbuyer@1: farmbuyer@1: -- Other stuff on right-hand side farmbuyer@95: local tab_specials = AceGUI:Create("SimpleGroup") farmbuyer@1: tab_specials:SetLayout("Flow") farmbuyer@1: tab_specials:SetFullWidth(true) farmbuyer@1: control:AddChild(tab_specials) farmbuyer@1: control:ResumeLayout() farmbuyer@1: farmbuyer@1: ----- Left-hand group farmbuyer@95: local tabs = AceGUI:Create("TabGroup") farmbuyer@1: tabs:SetLayout("Flow") farmbuyer@1: tabs.alignoffset = 25 farmbuyer@49: local titletext_orig_fo = tabs.titletext:GetFontObject() farmbuyer@49: tabs.titletext:SetFontObject(GameFontNormalSmall) farmbuyer@49: tabs:SetCallback("OnRelease", function(_tabs) farmbuyer@49: tabs.titletext:SetFontObject(titletext_orig_fo) farmbuyer@49: end) farmbuyer@1: tabs:SetRelativeWidth(0.99-rhs_width) farmbuyer@1: tabs:SetFullHeight(true) farmbuyer@1: tabs:SetTabs(tabgroup_tabs) farmbuyer@1: tabs:SetCallback("OnGroupSelected", tabs_OnGroupSelected_func) farmbuyer@1: tabs:SetCallback("OnTabEnter", function(_tabs,event,value,tab) farmbuyer@95: setstatus(gui.tabtexts[value].desc) farmbuyer@1: end) farmbuyer@1: tabs:SetCallback("OnTabLeave", statusy_OnLeave) farmbuyer@1: tabs:SetUserData("special buttons group",tab_specials) farmbuyer@76: tabs:SelectTab((opt_tabselect and #opt_tabselect>0) farmbuyer@76: and opt_tabselect or "eoi") farmbuyer@1: farmbuyer@1: display:AddChildren (tabs, control) farmbuyer@1: display:ApplyStatus() farmbuyer@1: farmbuyer@1: display:Show() -- without this, only appears every *other* function call farmbuyer@1: return display farmbuyer@1: end farmbuyer@1: farmbuyer@95: -- Searches tab titles from left to right. farmbuyer@88: function addon:OpenMainDisplayToTab (text, opt_arg) farmbuyer@44: text = '^'..text:lower() farmbuyer@95: for _,tab in ipairs(gui.taborder) do farmbuyer@95: local v = gui.tabtexts[tab] farmbuyer@95: if v and v.title:lower():find(text) then farmbuyer@1: self:BuildMainDisplay(tab) farmbuyer@88: if opt_arg and tabs_CLI_special[tab] then farmbuyer@88: tabs_CLI_special[tab](opt_arg) farmbuyer@88: end farmbuyer@1: return true farmbuyer@1: end farmbuyer@1: end farmbuyer@1: end farmbuyer@1: farmbuyer@1: -- Essentially a re-click on the current tab (if the current tab were clickable). farmbuyer@1: function addon:redisplay () farmbuyer@1: tabs_OnGroupSelected_func (unpack(tabs_OnGroupSelected_func_args)) farmbuyer@1: end farmbuyer@1: farmbuyer@1: farmbuyer@1: ------ Popup dialogs farmbuyer@75: local function build_my_slider_widget() farmbuyer@75: local s = CreateFrame("Slider", "OuroLootSlider", nil, "OptionsSliderTemplate") farmbuyer@75: s.text = OuroLootSliderText farmbuyer@75: s.low = OuroLootSliderLow farmbuyer@75: s.high = OuroLootSliderHigh farmbuyer@75: s:SetScript("OnValueChanged", function (_s, value) farmbuyer@75: _s.value = value -- conveniently, this is already of numeric type farmbuyer@75: --_s.text:SetText(tostring(value)) farmbuyer@75: if _s.DoOnValueChanged then farmbuyer@75: _s:DoOnValueChanged() farmbuyer@75: end farmbuyer@75: end) farmbuyer@75: build_my_slider_widget = nil farmbuyer@75: return s farmbuyer@75: end farmbuyer@75: farmbuyer@1: StaticPopupDialogs["OUROL_CLEAR"] = flib.StaticPopup{ farmbuyer@1: text = "Clear current loot information and text?", farmbuyer@16: button1 = YES, farmbuyer@16: button2 = NO, farmbuyer@1: OnAccept = function (dialog, addon) farmbuyer@1: addon:Clear(--[[verbose_p=]]true) farmbuyer@1: end, farmbuyer@1: } farmbuyer@1: farmbuyer@37: StaticPopupDialogs["OUROL_HIST_REGEN"] = flib.StaticPopup{ farmbuyer@37: -- Concatenate this once at load time. There is no ITEM_QUALITY_LEGENDARY constant. farmbuyer@75: text = "Erase all history entries from " .. ITEM_QUALITY_COLORS[5].hex farmbuyer@75: .. "%s|r, and generate it anew from current loot?", farmbuyer@37: button1 = YES, farmbuyer@37: button2 = NO, farmbuyer@37: OnAccept = function (dialog, addon, data2) farmbuyer@37: data2(addon) farmbuyer@37: addon:Print("%s history has been regenerated.", addon.history.realm) farmbuyer@37: addon:redisplay() farmbuyer@37: end, farmbuyer@37: } farmbuyer@37: farmbuyer@16: StaticPopupDialogs["OUROL_HIST_CLEAR"] = flib.StaticPopup{ farmbuyer@37: -- Concatenate this once at load time. There is no ITEM_QUALITY_LEGENDARY constant. farmbuyer@37: text = "Erase all history entries from " .. ITEM_QUALITY_COLORS[5].hex .. "%s|r?", farmbuyer@16: button1 = YES, farmbuyer@16: button2 = NO, farmbuyer@16: OnAccept = function (dialog, addon, data2) farmbuyer@16: data2(addon) farmbuyer@16: addon:Print("Stimpy, you eeediot, you've pushed the history erase button!") farmbuyer@16: addon:redisplay() farmbuyer@16: end, farmbuyer@16: } farmbuyer@16: farmbuyer@16: StaticPopupDialogs["OUROL_HIST_PREEN"] = flib.StaticPopup{ farmbuyer@37: -- Concatenate this once at load time. There is no ITEM_QUALITY_LEGENDARY constant. farmbuyer@75: text = "This will erase all but the latest " farmbuyer@75: .. ITEM_QUALITY_COLORS[ITEM_QUALITY_UNCOMMON].hex farmbuyer@75: .. "%s|r for each player on " farmbuyer@75: .. ITEM_QUALITY_COLORS[5].hex .. "%s|r. " .. CONTINUE .. "?", farmbuyer@16: button1 = YES, farmbuyer@16: button2 = NO, farmbuyer@75: OnShow = function (dialog, addon) farmbuyer@75: local thistable = StaticPopupDialogs[dialog.which] farmbuyer@75: -- StaticPopup_Resize does not take extraFrame into account, so we farmbuyer@89: -- monkeypatch the sizing method that _Resize calls at the end. farmbuyer@75: dialog.saved_setheight = dialog.SetHeight farmbuyer@75: dialog.SetHeight = function (d, h) farmbuyer@75: return d.saved_setheight(d,h+35) farmbuyer@75: end farmbuyer@75: dialog.extraFrame:ClearAllPoints() farmbuyer@75: dialog.extraFrame:SetPoint("TOP", dialog.text, "BOTTOM") farmbuyer@75: dialog.extraFrame:SetWidth(150) farmbuyer@75: dialog.extraFrame:SetHeight(35) farmbuyer@75: dialog.extraFrame:Show() farmbuyer@75: local slider = _G.OuroLootSlider or build_my_slider_widget() farmbuyer@75: slider.DoOnValueChanged = function(s) farmbuyer@75: dialog.text:SetFormattedText (thistable.text, farmbuyer@75: s.value == 1 and "single entry" or (s.value .. " entries"), farmbuyer@75: addon.history.realm) farmbuyer@75: StaticPopup_Resize (dialog, "OUROL_HIST_PREEN") farmbuyer@75: end farmbuyer@75: slider:SetOrientation('HORIZONTAL') farmbuyer@75: slider:SetMinMaxValues(1,30) farmbuyer@75: slider:SetValueStep(1) farmbuyer@75: slider.low:SetText("1") farmbuyer@75: slider.high:SetText("30") farmbuyer@75: --slider.tooltipText = ??? farmbuyer@75: slider:SetParent(dialog.extraFrame) farmbuyer@75: slider:ClearAllPoints() farmbuyer@75: slider:SetPoint("TOPLEFT",dialog.extraFrame,"TOPLEFT",0, -15) farmbuyer@75: slider:SetPoint("BOTTOMRIGHT",dialog.extraFrame,"BOTTOMRIGHT",0, 0) farmbuyer@75: slider:Show() farmbuyer@75: -- This causes OnValueChanged to fire, reformatting the text. Except farmbuyer@75: -- IF the slider has already been shown, and IF at the time it was hidden farmbuyer@75: -- it had the same value here, THEN there is technically no "change" farmbuyer@75: -- and no event is fired. We work around this clever optimization by farmbuyer@75: -- doing a pair of set's, forcing the last one to fire OVC. farmbuyer@75: slider:SetValue(1) farmbuyer@75: slider:SetValue(5) farmbuyer@75: end, farmbuyer@75: OnAccept = function (dialog, addon, callback) farmbuyer@75: local howmany = assert(tonumber(_G.OuroLootSlider.value)) farmbuyer@75: callback (addon, howmany) farmbuyer@75: addon:Print("All loot prior to the most recent %d |4entry:entries; has been erased.", howmany) farmbuyer@16: addon:redisplay() farmbuyer@16: end, farmbuyer@75: OnHide = function (dialog, addon) farmbuyer@75: dialog.SetHeight = nil farmbuyer@75: dialog.saved_setheight = nil farmbuyer@75: dialog.extraFrame:ClearAllPoints() farmbuyer@75: _G.OuroLootSlider:Hide() -- parent is hidden, why is this required? farmbuyer@75: _G.OuroLootSlider:ClearAllPoints() farmbuyer@75: _G.OuroLootSlider:SetParent(nil) farmbuyer@75: end, farmbuyer@16: } farmbuyer@16: farmbuyer@27: StaticPopupDialogs["OUROL_URL"] = { --flib.StaticPopup{ farmbuyer@27: text = "Use Control-C or equivalent to copy this URL to your system clipboard:", farmbuyer@27: button1 = OKAY, farmbuyer@27: timeout = 0, farmbuyer@27: whileDead = true, farmbuyer@27: hideOnEscape = true, farmbuyer@27: enterClicksFirstButton = true, farmbuyer@27: hasEditBox = true, farmbuyer@27: editBoxWidth = 350, farmbuyer@53: preferredIndex = 3, farmbuyer@27: OnShow = function (dialog, url) farmbuyer@27: dialog.editBox:SetText(url) farmbuyer@27: dialog.editBox:SetFocus() farmbuyer@27: dialog.editBox:HighlightText() farmbuyer@27: end, farmbuyer@27: } farmbuyer@27: farmbuyer@1: StaticPopupDialogs["OUROL_REMIND"] = flib.StaticPopup{ farmbuyer@77: text = "Do you wish to activate Ouro Loot?|n|n(Hit the Escape key to close this window without clicking; Enter is the same as Activate)", farmbuyer@1: button1 = "Activate recording", -- "accept", left farmbuyer@69: button2 = "Broadcast Only", -- "cancel", middle farmbuyer@69: button3 = HELP_LABEL, -- "alt", right farmbuyer@1: OnAccept = function (dialog, addon) farmbuyer@1: addon:Activate() farmbuyer@1: end, farmbuyer@69: noCancelOnEscape = true, farmbuyer@69: OnCancel = function (dialog, addon) farmbuyer@1: addon:Activate(nil,true) farmbuyer@1: end, farmbuyer@69: OnAlt = function (dialog, addon) farmbuyer@1: -- hitting escape also calls this, but the 3rd arg would be "clicked" farmbuyer@1: -- in both cases, not useful here. farmbuyer@89: if MouseIsOver(dialog.button3) then farmbuyer@1: -- they actually clicked the button (or at least the mouse was over "Help" farmbuyer@1: -- when they hit escape... sigh) farmbuyer@1: addon:BuildMainDisplay('help') farmbuyer@1: else farmbuyer@1: addon.popped = true farmbuyer@1: end farmbuyer@1: end, farmbuyer@1: } farmbuyer@1: farmbuyer@69: -- Callback for each Next/Accept stage of inserting a new loot or boss row via farmbuyer@69: -- dropdown. Thanks to noCancelOnReuse, each Show done here will technically farmbuyer@69: -- Hide and redisplay the same dialog, passing along the same 'data' structure farmbuyer@69: -- each time. The topmost call to our OnAccept will then finish by hiding the farmbuyer@69: -- (very last) dialog. farmbuyer@69: -- farmbuyer@69: -- This is really, really hideous to read. farmbuyer@69: local function eoi_st_insert_OnAccept_boss (dialog, data, data2) farmbuyer@69: if data.all_done then farmbuyer@69: -- It'll probably be the final entry in the table, but there might have farmbuyer@73: -- been real loot happening while the user was clicking and typing. farmbuyer@69: local boss_index = addon._addBossEntry{ farmbuyer@69: kind = 'boss', farmbuyer@97: bossname = (gui.opts.snarky_boss and addon.boss_abbrev[data.name] or data.name) or data.name, farmbuyer@69: reason = 'kill', farmbuyer@69: instance = data.instance, farmbuyer@69: duration = 0, farmbuyer@69: maxsize = data.max_raid_size, farmbuyer@69: raidersnap = data.yes_snap or {}, farmbuyer@69: } farmbuyer@69: local entry = tremove(g_loot,boss_index) farmbuyer@69: tinsert(g_loot,data.rowindex,entry) farmbuyer@69: addon:_mark_boss_kill(data.rowindex) farmbuyer@95: gui.eoiST:OuroLoot_Refresh(data.rowindex) farmbuyer@69: dialog.data = nil -- free up memory farmbuyer@78: addon:Print("Inserted %s %s at entry %d.", data.kind, data.name, data.rowindex) farmbuyer@69: return farmbuyer@69: end farmbuyer@69: farmbuyer@69: -- third click farmbuyer@69: if data.name and data.instance then farmbuyer@69: data.all_done = true farmbuyer@69: -- this is how we distinguish OnAccept from OnCancel ("clicked"); the farmbuyer@69: -- 3rd param is handled all in StaticPopup_OnClick farmbuyer@69: if data2 ~= 'clicked' then farmbuyer@69: data.yes_snap = data.maybe_snap farmbuyer@69: end farmbuyer@69: return eoi_st_insert_OnAccept_boss (dialog, data) farmbuyer@69: end farmbuyer@69: farmbuyer@69: local text = dialog.editBox:GetText():trim() farmbuyer@69: farmbuyer@69: -- second click farmbuyer@69: if data.name and text then farmbuyer@69: data.instance = text farmbuyer@92: -- not "reusing" this dialog in the same sense as with loot farmbuyer@69: dialog.data = nil farmbuyer@69: dialog:Hide() farmbuyer@69: local getsnap = StaticPopup_Show("OUROL_EOI_INSERT_INCLUDE_RAIDERSNAP") farmbuyer@69: getsnap.data = data farmbuyer@69: return true farmbuyer@69: end farmbuyer@69: farmbuyer@69: -- first click farmbuyer@69: if text then farmbuyer@69: data.name = text farmbuyer@69: local maybe_instance farmbuyer@69: data.maybe_snap, data.max_raid_size, maybe_instance = addon:snapshot_raid() farmbuyer@69: local getinstance = StaticPopup_Show("OUROL_EOI_INSERT","instance") farmbuyer@69: getinstance.data = data farmbuyer@69: getinstance.editBox:SetText(maybe_instance) farmbuyer@69: -- This suppresses auto-hide (which would cause the getinstance dialog farmbuyer@69: -- to go away), but only when mouse clicking. OnEnter is on its own. farmbuyer@69: return true farmbuyer@69: end farmbuyer@69: end farmbuyer@69: farmbuyer@69: local function eoi_st_insert_OnAccept_loot (dialog, data) farmbuyer@69: if data.all_done then farmbuyer@69: data.display:Hide() farmbuyer@73: local loot_index = assert(addon:CHAT_MSG_LOOT ("manual", data.recipient, data.name, data.notes)) farmbuyer@69: local entry = tremove(g_loot,loot_index) farmbuyer@69: tinsert(g_loot,data.rowindex,entry) farmbuyer@69: addon:_fill_out_eoi_data(data.rowindex) farmbuyer@69: addon:BuildMainDisplay() farmbuyer@79: local clicky = _new_rebroadcast_hyperlink (entry.unique) farmbuyer@69: dialog.data = nil farmbuyer@78: addon:Print ("Inserted %s %s at entry %d. %s", farmbuyer@78: data.kind, data.name, data.rowindex, tostring(clicky)) farmbuyer@69: return farmbuyer@69: end farmbuyer@69: farmbuyer@69: local text = dialog.editBox:GetText():trim() farmbuyer@69: farmbuyer@69: -- third click farmbuyer@69: if data.name and data.recipient and text then farmbuyer@69: data.notes = (text ~= "") and text or nil farmbuyer@69: data.all_done = true farmbuyer@69: return eoi_st_insert_OnAccept_loot (dialog, data) farmbuyer@69: end farmbuyer@69: farmbuyer@69: -- second click farmbuyer@69: if data.name and text then farmbuyer@69: data.recipient = text farmbuyer@69: local getnotes = StaticPopup_Show("OUROL_EOI_INSERT","notes") farmbuyer@69: getnotes.data = data farmbuyer@69: getnotes.editBox:SetText("") farmbuyer@69: getnotes.editBox:HighlightText() farmbuyer@69: return true farmbuyer@69: end farmbuyer@69: farmbuyer@69: -- first click farmbuyer@69: if text then farmbuyer@69: data.name = text farmbuyer@69: dialog:Hide() -- technically a "different" one about to be shown farmbuyer@78: StaticPopupDialogs["OUROL_EOI_INSERT"].autoCompleteParams = farmbuyer@93: AUTOCOMPLETE_LIST_TEMPLATES[IsInRaid() and "IN_GROUP" or "IN_GUILD"] farmbuyer@69: local getrecipient = StaticPopup_Show("OUROL_EOI_INSERT","recipient") farmbuyer@78: StaticPopupDialogs["OUROL_EOI_INSERT"].autoCompleteParams = nil farmbuyer@69: getrecipient.data = data farmbuyer@69: getrecipient.editBox:SetText("") farmbuyer@69: return true farmbuyer@69: end farmbuyer@69: end farmbuyer@69: farmbuyer@69: local function eoi_st_insert_OnAccept (dialog, data) farmbuyer@69: if data.kind == 'boss' then farmbuyer@69: return eoi_st_insert_OnAccept_boss (dialog, data) farmbuyer@69: elseif data.kind == 'loot' then farmbuyer@69: return eoi_st_insert_OnAccept_loot (dialog, data) farmbuyer@69: end farmbuyer@69: end farmbuyer@69: farmbuyer@1: -- The data member here is a table built with: farmbuyer@1: -- {rowindex=, display=_d, kind=} farmbuyer@1: do farmbuyer@1: local t = flib.StaticPopup{ farmbuyer@75: text = "Enter name of new %s, then click "..CONTINUE.." or press Enter:", farmbuyer@75: button1 = CONTINUE.." ->", farmbuyer@1: button2 = CANCEL, farmbuyer@1: hasEditBox = true, farmbuyer@16: editBoxWidth = 350, farmbuyer@1: maxLetters = 50, farmbuyer@1: noCancelOnReuse = true, farmbuyer@1: } farmbuyer@1: t.EditBoxOnEnterPressed = function(editbox) farmbuyer@39: if editbox:GetText() == "" then return end farmbuyer@1: local dialog = editbox:GetParent() farmbuyer@1: if not eoi_st_insert_OnAccept (dialog, dialog.data) then farmbuyer@1: dialog:Hide() -- replicate OnAccept click behavior farmbuyer@1: end farmbuyer@1: end farmbuyer@1: t.enterClicksFirstButton = nil -- no effect with editbox focused farmbuyer@1: t.OnAccept = eoi_st_insert_OnAccept farmbuyer@1: StaticPopupDialogs["OUROL_EOI_INSERT"] = t farmbuyer@1: farmbuyer@69: -- This seems to be gratuitous use of metatables, really. farmbuyer@1: local OEIL = { farmbuyer@75: text = "Paste the new item into here, then click "..CONTINUE.." or press Enter:", farmbuyer@1: __index = StaticPopupDialogs["OUROL_EOI_INSERT"] farmbuyer@1: } farmbuyer@1: StaticPopupDialogs["OUROL_EOI_INSERT_LOOT"] = setmetatable(OEIL,OEIL) farmbuyer@1: farmbuyer@1: hooksecurefunc("ChatEdit_InsertLink", function (link,...) farmbuyer@1: local dialogname = StaticPopup_Visible "OUROL_EOI_INSERT_LOOT" farmbuyer@1: if dialogname then farmbuyer@16: _G[dialogname.."EditBox"]:SetText(link) farmbuyer@1: return true farmbuyer@1: end farmbuyer@1: end) farmbuyer@69: farmbuyer@69: t = flib.StaticPopup{ farmbuyer@69: -- Concatenate this once at load time. There is no ITEM_QUALITY_LEGENDARY constant. farmbuyer@69: text = "Include a snapshot of the " .. ITEM_QUALITY_COLORS[5].hex farmbuyer@77: .. "CURRENT|r raid?|n|nClicking '" .. YES .. "' will allow this entry to " farmbuyer@69: .. "appear in attendance lists, but with the roster as it is NOW, not as it " farmbuyer@69: .. "was THEN. Clicking '" .. NO .."' means this kill cannot be included in " farmbuyer@77: .. "attendance.|n|n(Enter = '" .. YES .."', Escape = '" .. CANCEL .. "')", farmbuyer@69: button1 = YES, -- "accept", left farmbuyer@69: button2 = NO, -- "cancel", middle farmbuyer@69: button3 = CANCEL, -- "alt", right farmbuyer@69: } farmbuyer@69: -- Hitting Escape still hides the frame, but doesn't run OnCancel (which farmbuyer@69: -- is for the "No" button, not the "Cancel"/OnAlt button). Dizzy yet? farmbuyer@69: t.noCancelOnEscape = true farmbuyer@69: t.OnAccept = eoi_st_insert_OnAccept_boss farmbuyer@69: t.OnCancel = eoi_st_insert_OnAccept_boss farmbuyer@69: StaticPopupDialogs["OUROL_EOI_INSERT_INCLUDE_RAIDERSNAP"] = t farmbuyer@1: end farmbuyer@1: farmbuyer@1: StaticPopupDialogs["OUROL_REASSIGN_ENTER"] = flib.StaticPopup{ farmbuyer@1: text = "Enter the player name:", farmbuyer@1: button1 = ACCEPT, farmbuyer@1: button2 = CANCEL, farmbuyer@1: hasEditBox = true, farmbuyer@1: OnAccept = function(dialog, data) farmbuyer@1: local name = dialog.usertext --editBox:GetText() farmbuyer@81: addon:reassign_loot ("local", data.index, name) farmbuyer@95: gui.eoiST:OuroLoot_Refresh(data.index) farmbuyer@1: end, farmbuyer@1: } farmbuyer@1: farmbuyer@1: StaticPopupDialogs["OUROL_SAVE_SAVEAS"] = flib.StaticPopup{ farmbuyer@1: text = "Enter a name for the loot collection:", farmbuyer@1: button1 = ACCEPT, farmbuyer@1: button2 = CANCEL, farmbuyer@1: hasEditBox = true, farmbuyer@1: maxLetters = 30, farmbuyer@1: OnAccept = function(dialog)--, data) farmbuyer@1: local name = dialog.usertext --editBox:GetText() farmbuyer@1: addon:save_saveas(name) farmbuyer@1: addon:BuildMainDisplay() farmbuyer@1: end, farmbuyer@1: OnCancel = function(dialog)--, data, reason) farmbuyer@1: addon:BuildMainDisplay() farmbuyer@1: end, farmbuyer@1: } farmbuyer@1: farmbuyer@25: farmbuyer@25: -- Workaround this bug: http://us.battle.net/wow/en/forum/topic/3278901991 farmbuyer@25: if true then farmbuyer@25: -- Verbatim copy of UIDropDownMenuTemplates.xml:155 or so, except as farmbuyer@25: -- tagged with CHANGE. farmbuyer@25: local function onenter (self, motion) farmbuyer@25: if ( self.hasArrow ) then farmbuyer@25: local level = self:GetParent():GetID() + 1; farmbuyer@25: local listFrame = _G["DropDownList"..level]; farmbuyer@25: if ( not listFrame or not listFrame:IsShown() or select(2, listFrame:GetPoint()) ~= self ) then farmbuyer@25: ToggleDropDownMenu(self:GetParent():GetID() + 1, self.value, nil, nil, nil, nil, self.menuList, self); farmbuyer@25: end farmbuyer@25: else farmbuyer@25: CloseDropDownMenus(self:GetParent():GetID() + 1); farmbuyer@25: end farmbuyer@25: _G[self:GetName().."Highlight"]:Show(); farmbuyer@25: UIDropDownMenu_StopCounting(self:GetParent()); farmbuyer@25: if ( self.tooltipTitle ) then farmbuyer@25: if ( self.tooltipOnButton ) then farmbuyer@25: GameTooltip:SetOwner(self, "ANCHOR_RIGHT"); farmbuyer@25: GameTooltip:AddLine(self.tooltipTitle, 1.0, 1.0, 1.0); farmbuyer@25: GameTooltip:AddLine(self.tooltipText, nil,nil,nil,1); -- CHANGE added nil->1 arguments farmbuyer@25: GameTooltip:Show(); farmbuyer@25: else farmbuyer@25: GameTooltip_AddNewbieTip(self, self.tooltipTitle, 1.0, 1.0, 1.0, self.tooltipText, 1); farmbuyer@25: end farmbuyer@25: end farmbuyer@25: end farmbuyer@25: -- end verbatime copy farmbuyer@25: farmbuyer@25: for i = 1, UIDROPDOWNMENU_MAXLEVELS do farmbuyer@25: local list = _G["DropDownList"..i] farmbuyer@25: if list then farmbuyer@25: for j = 1, UIDROPDOWNMENU_MAXBUTTONS do farmbuyer@25: local button = _G["DropDownList"..i.."Button"..j] farmbuyer@25: if button then farmbuyer@25: --print("button fixup",i,j) farmbuyer@25: button:SetScript("OnEnter",onenter) farmbuyer@25: end farmbuyer@25: end farmbuyer@25: end farmbuyer@25: end farmbuyer@25: end farmbuyer@25: farmbuyer@1: -- vim:noet