From 6f4d4945e88caf389d2e319baa4647b68d46cbef Mon Sep 17 00:00:00 2001 From: "James D. Callahan III" Date: Sat, 10 Jul 2010 01:13:12 -0400 Subject: [PATCH] Split the code for the ListFrame off into its own file. --- Frame.lua | 1572 +--------------------------------------------------- Interface/List.lua | 1566 +++++++++++++++++++++++++++++++++++++++++++++++++++ interface.xml | 1 + 3 files changed, 1588 insertions(+), 1551 deletions(-) create mode 100644 Interface/List.lua diff --git a/Frame.lua b/Frame.lua index 9691a92..4328a90 100644 --- a/Frame.lua +++ b/Frame.lua @@ -81,15 +81,9 @@ local FACTION_HORDE = BFAC["Horde"] local FACTION_ALLIANCE = BFAC["Alliance"] local FACTION_NEUTRAL = BFAC["Neutral"] -local CATEGORY_COLORS = private.category_colors local BASIC_COLORS = private.basic_colors -local SF = private.recipe_state_flags - local A = private.acquire_types -local A_MAX = 9 - -local COMMON1 = private.common_flags_word1 ------------------------------------------------------------------------------- -- Define the static popups we're going to call when people haven't scanned or @@ -147,7 +141,6 @@ local SetTextColor = private.SetTextColor local AcquireTable = private.AcquireTable local ReleaseTable = private.ReleaseTable -local ListFrame local MainPanel local FilterValueMap -- Assigned in InitializeFrame() @@ -307,486 +300,6 @@ do end -- do ------------------------------------------------------------------------------- --- Tooltip functions and data. -------------------------------------------------------------------------------- -local spell_tip = CreateFrame("GameTooltip", "arlSpellTooltip", UIParent, "GameTooltipTemplate") -local acquire_tip - --- Font Objects needed for acquire_tip -local narrowFont -local normalFont - -local ListItem_ShowTooltip -do - -- Fallback in case the user doesn't have LSM-3.0 installed - if not LibStub:GetLibrary("LibSharedMedia-3.0", true) then - - local locale = GetLocale() - -- Fix for font issues on koKR - if locale == "koKR" then - narrowFont = "Fonts\\2002.TTF" - normalFont = "Fonts\\2002.TTF" - else - narrowFont = "Fonts\\ARIALN.TTF" - normalFont = "Fonts\\FRIZQT__.TTF" - end - else - -- Register LSM 3.0 - local LSM3 = LibStub("LibSharedMedia-3.0") - - narrowFont = LSM3:Fetch(LSM3.MediaType.FONT, "Arial Narrow") - normalFont = LSM3:Fetch(LSM3.MediaType.FONT, "Friz Quadrata TT") - end - local narrowFontObj = CreateFont(MODNAME.."narrowFontObj") - local normalFontObj = CreateFont(MODNAME.."normalFontObj") - - -- I want to do a bit more comprehensive tooltip processing. Things like changing font sizes, - -- adding padding to the left hand side, and using better color handling. So... this function - -- will do that for me. - local function ttAdd( - leftPad, -- number of times to pad two spaces on left side - textSize, -- add to or subtract from addon.db.profile.tooltip.acquire_fontsize to get fontsize - narrow, -- if 1, use ARIALN instead of FRITZQ - str1, -- left-hand string - hexcolor1, -- hex color code for left-hand side - str2, -- if present, this is the right-hand string - hexcolor2) -- if present, hex color code for right-hand side - - -- are we changing fontsize or narrow? - local fontSize - - if narrow or textSize ~= 0 then - local font = narrow and narrowFont or normalFont - local fontObj = narrow and narrowFontObj or normalFontObj - - fontSize = addon.db.profile.tooltip.acquire_fontsize + textSize - - fontObj:SetFont(font, fontSize) - acquire_tip:SetFont(fontObj) - end - - -- Add in our left hand padding - local loopPad = leftPad - local leftStr = str1 - - while loopPad > 0 do - leftStr = " " .. leftStr - loopPad = loopPad - 1 - end - -- Set maximum width to match fontSize to maintain uniform tooltip size. -Torhal - local width = math.ceil(fontSize * 37.5) - local line = acquire_tip:AddLine() - - if str2 then - width = width / 2 - - acquire_tip:SetCell(line, 1, "|cff"..hexcolor1..leftStr.."|r", "LEFT", nil, nil, 0, 0, width, width) - acquire_tip:SetCell(line, 2, "|cff"..hexcolor2..str2.."|r", "RIGHT", nil, nil, 0, 0, width, width) - else - acquire_tip:SetCell(line, 1, "|cff"..hexcolor1..leftStr.."|r", nil, "LEFT", 2, nil, 0, 0, width, width) - end - end - - local function SetSpellTooltip(owner, loc, link) - spell_tip:SetOwner(owner, "ANCHOR_NONE") - spell_tip:ClearAllPoints() - - if loc == "Top" then - spell_tip:SetPoint("BOTTOMLEFT", owner, "TOPLEFT") - elseif loc == "Bottom" then - spell_tip:SetPoint("TOPLEFT", owner, "BOTTOMLEFT") - elseif loc == "Left" then - spell_tip:SetPoint("TOPRIGHT", owner, "TOPLEFT") - elseif loc == "Right" then - spell_tip:SetPoint("TOPLEFT", owner, "TOPRIGHT") - end - - -- Add TipTac Support - if _G.TipTac and _G.TipTac.AddModifiedTip and not spell_tip.tiptac then - _G.TipTac:AddModifiedTip(spell_tip) - spell_tip.tiptac = true - end - - -- Set the spell tooltip's scale, and copy its other values from GameTooltip so AddOns which modify it will work. - spell_tip:SetBackdrop(GameTooltip:GetBackdrop()) - spell_tip:SetBackdropColor(GameTooltip:GetBackdropColor()) - spell_tip:SetBackdropBorderColor(GameTooltip:GetBackdropBorderColor()) - spell_tip:SetScale(addon.db.profile.tooltip.scale) - spell_tip:SetClampedToScreen(true) - spell_tip:SetHyperlink(link) - spell_tip:Show() - end - - local function GetTipFactionInfo(comp_faction) - local display_tip - local color - - if comp_faction == FACTION_NEUTRAL then - color = private.reputation_colors["neutral"] - display_tip = true - elseif comp_faction == BFAC[Player.faction] then - color = private.reputation_colors["exalted"] - display_tip = true - else - color = private.reputation_colors["hated"] - display_tip = addon.db.profile.filters.general.faction - end - return display_tip, color - end - - ------------------------------------------------------------------------------- - -- Functions for adding individual acquire type data to the tooltip. - ------------------------------------------------------------------------------- - local function Tooltip_AddTrainer(id_num, location, addline_func) - local trainer = private.trainer_list[id_num] - - if location and trainer.location ~= location then - return - end - local display_tip, name_color = GetTipFactionInfo(trainer.faction) - - if display_tip then - local coord_text = "" - - if trainer.coord_x ~= 0 and trainer.coord_y ~= 0 then - coord_text = "(" .. trainer.coord_x .. ", " .. trainer.coord_y .. ")" - end - addline_func(0, -2, false, L["Trainer"], CATEGORY_COLORS["trainer"], trainer.name, name_color) - addline_func(1, -2, true, trainer.location, CATEGORY_COLORS["location"], coord_text, CATEGORY_COLORS["coords"]) - end - end - - local function Tooltip_AddVendor(recipe_id, id_num, location, addline_func) - local vendor = private.vendor_list[id_num] - - if location and vendor.location ~= location then - return - end - local type_color = CATEGORY_COLORS["vendor"] - local display_tip, name_color = GetTipFactionInfo(vendor.faction) - - if display_tip then - local coord_text = "" - - if vendor.coord_x ~= 0 and vendor.coord_y ~= 0 then - coord_text = "(" .. vendor.coord_x .. ", " .. vendor.coord_y .. ")" - end - addline_func(0, -1, false, L["Vendor"], type_color, vendor.name, name_color) - addline_func(1, -2, true, vendor.location, CATEGORY_COLORS["location"], coord_text, CATEGORY_COLORS["coords"]) - - local quantity = vendor.item_list[recipe_id] - - if type(quantity) == "number" then - addline_func(2, -2, true, L["LIMITED_SUPPLY"], type_color, string.format("(%d)", quantity), BASIC_COLORS["white"]) - end - end - end - - local function Tooltip_AddMobDrop(id_num, location, addline_func) - local mob = private.mob_list[id_num] - - if location and mob.location ~= location then - return - end - local coord_text = "" - - if mob.coord_x ~= 0 and mob.coord_y ~= 0 then - coord_text = "(" .. mob.coord_x .. ", " .. mob.coord_y .. ")" - end - addline_func(0, -1, false, L["Mob Drop"], CATEGORY_COLORS["mobdrop"], mob.name, private.reputation_colors["hostile"]) - addline_func(1, -2, true, mob.location, CATEGORY_COLORS["location"], coord_text, CATEGORY_COLORS["coords"]) - end - - local function Tooltip_AddQuest(id_num, location, addline_func) - local quest = private.quest_list[id_num] - - if location and quest.location ~= location then - return - end - local type_color = CATEGORY_COLORS["quest"] - local display_tip, name_color = GetTipFactionInfo(quest.faction) - - if display_tip then - local coord_text = "" - - if quest.coord_x ~= 0 and quest.coord_y ~= 0 then - coord_text = "(" .. quest.coord_x .. ", " .. quest.coord_y .. ")" - end - addline_func(0, -1, false, L["Quest"], type_color, private.quest_names[id_num], name_color) - addline_func(1, -2, true, quest.location, CATEGORY_COLORS["location"], coord_text, CATEGORY_COLORS["coords"]) - end - end - - local function Tooltip_AddRepVendor(id_num, location, rep_id, rep_level, vendor_id, addline_func) - local rep_vendor = private.vendor_list[vendor_id] - - if location and rep_vendor.location ~= location then - return - end - local display_tip, name_color = GetTipFactionInfo(rep_vendor.faction) - - if display_tip then - local rep_color = private.reputation_colors - local rep_str = "" - local type_color - - if rep_level == 0 then - rep_str = FACTION_NEUTRAL - type_color = rep_color["neutral"] - elseif rep_level == 1 then - rep_str = BFAC["Friendly"] - type_color = rep_color["friendly"] - elseif rep_level == 2 then - rep_str = BFAC["Honored"] - type_color = rep_color["honored"] - elseif rep_level == 3 then - rep_str = BFAC["Revered"] - type_color = rep_color["revered"] - else - rep_str = BFAC["Exalted"] - type_color = rep_color["exalted"] - end - addline_func(0, -1, false, _G.REPUTATION, CATEGORY_COLORS["reputation"], private.reputation_list[id_num].name, CATEGORY_COLORS["repname"]) - addline_func(1, -2, false, rep_str, type_color, rep_vendor.name, name_color) - - local coord_text = "" - - if rep_vendor.coord_x ~= 0 and rep_vendor.coord_y ~= 0 then - coord_text = "(" .. rep_vendor.coord_x .. ", " .. rep_vendor.coord_y .. ")" - end - addline_func(2, -2, true, rep_vendor.location, CATEGORY_COLORS["location"], coord_text, CATEGORY_COLORS["coords"]) - end - end - - local function Tooltip_AddWorldDrop(recipe_id, id_num, location, addline_func) - local drop_location = type(id_num) == "string" and BZ[id_num] or nil - - if location and drop_location ~= location then - return - end - local item_id = private.spell_to_recipe_map[recipe_id] - local _, item_level - - if item_id then - _, _, _, item_level = GetItemInfo(item_id) - end - local _, _, _, quality_color = GetItemQualityColor(private.recipe_list[recipe_id].quality) - local type_color = string.gsub(quality_color, "|cff", "") - - if type(id_num) == "string" then - local location_text = item_level and string.format("%s (%d - %d)", drop_location, item_level - 5, item_level + 5) or drop_location - - addline_func(0, -1, false, L["World Drop"], type_color, location_text, CATEGORY_COLORS["location"]) - else - local location_text = item_level and string.format("%s (%d - %d)", _G.UNKNOWN, item_level - 5, item_level + 5) or _G.UNKNOWN - - addline_func(0, -1, false, L["World Drop"], type_color, location_text, CATEGORY_COLORS["location"]) - end - end - - ------------------------------------------------------------------------------- - -- Public API function for displaying a recipe's acquire data. - -- * The addline_func paramater must be a function which accepts the same - -- * arguments as ARL's ttAdd function. - ------------------------------------------------------------------------------- - function addon:DisplayAcquireData(recipe_id, acquire_id, location, addline_func) - local recipe = private.recipe_list[recipe_id] - - if not recipe then - return - end - - for acquire_type, acquire_data in pairs(recipe.acquire_data) do - local can_display = (not acquire_id or acquire_type == acquire_id) - - if can_display then - for id_num, info in pairs(acquire_data) do - if acquire_type == A.TRAINER then - Tooltip_AddTrainer(id_num, location, addline_func) - elseif acquire_type == A.VENDOR then - Tooltip_AddVendor(recipe_id, id_num, location, addline_func) - elseif acquire_type == A.MOB_DROP then - Tooltip_AddMobDrop(id_num, location, addline_func) - elseif acquire_type == A.QUEST then - Tooltip_AddQuest(id_num, location, addline_func) - elseif acquire_type == A.SEASONAL then - color_1 = CATEGORY_COLORS["seasonal"] - addline_func(0, -1, 0, private.acquire_names[A.SEASONAL], color_1, private.seasonal_list[id_num].name, color_1) - elseif acquire_type == A.REPUTATION then - for rep_level, level_info in pairs(info) do - for vendor_id in pairs(level_info) do - Tooltip_AddRepVendor(id_num, location, rep_id, rep_level, vendor_id, addline_func) - end - end - elseif acquire_type == A.WORLD_DROP then - Tooltip_AddWorldDrop(recipe_id, id_num, location, addline_func) - elseif acquire_type == A.CUSTOM then - addline_func(0, -1, false, private.custom_list[id_num].name, CATEGORY_COLORS["custom"]) - --@alpha@ - elseif can_display then - -- Unhandled - addline_func(0, -1, 0, L["Unhandled Recipe"], BASIC_COLORS["normal"]) - --@end-alpha@ - end - end -- for id_num - end -- if can_display - end -- for acquire_type - end - - ------------------------------------------------------------------------------- - -- Main tooltip-generating function. - ------------------------------------------------------------------------------- - local BINDING_FLAGS = { - [COMMON1.IBOE] = L["BOEFilter"], - [COMMON1.IBOP] = L["BOPFilter"], - [COMMON1.IBOA] = L["BOAFilter"], - [COMMON1.RBOE] = L["RecipeBOEFilter"], - [COMMON1.RBOP] = L["RecipeBOPFilter"], - [COMMON1.RBOA] = L["RecipeBOAFilter"] - } - - function ListItem_ShowTooltip(owner, list_entry) - if not list_entry then - return - end - local recipe_id = list_entry.recipe_id - local recipe = private.recipe_list[recipe_id] - - if not recipe then - return - end - local spell_tip_anchor = addon.db.profile.spelltooltiplocation - local acquire_tip_anchor = addon.db.profile.acquiretooltiplocation - local spell_link = GetSpellLink(recipe.spell_id) - local MainPanel = addon.Frame - - if acquire_tip_anchor == _G.OFF then - QTip:Release(acquire_tip) - - -- If we have the spell link tooltip, anchor it to MainPanel instead so it shows - if spell_tip_anchor ~= _G.OFF and spell_link then - SetSpellTooltip(MainPanel, spell_tip_anchor, spell_link) - else - spell_tip:Hide() - end - return - end - acquire_tip = QTip:Acquire(MODNAME.." Tooltip", 2, "LEFT", "LEFT") - acquire_tip:ClearAllPoints() - - if acquire_tip_anchor == "Right" then - acquire_tip:SetPoint("TOPLEFT", MainPanel, "TOPRIGHT", MainPanel.is_expanded and -90 or -35, 0) - elseif acquire_tip_anchor == "Left" then - acquire_tip:SetPoint("TOPRIGHT", MainPanel, "TOPLEFT") - elseif acquire_tip_anchor == "Top" then - acquire_tip:SetPoint("BOTTOMLEFT", MainPanel, "TOPLEFT") - elseif acquire_tip_anchor == "Bottom" then - acquire_tip:SetPoint("TOPLEFT", MainPanel, "BOTTOMLEFT", 0, 55) - elseif acquire_tip_anchor == "Mouse" then - local x, y = GetCursorPosition() - local uiscale = UIParent:GetEffectiveScale() - - acquire_tip:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", x / uiscale, y / uiscale) - end - acquire_tip:SetClampedToScreen(true) - - if _G.TipTac and _G.TipTac.AddModifiedTip then - -- Pass true as second parameter because hooking OnHide causes C stack overflows -Torhal - _G.TipTac:AddModifiedTip(acquire_tip, true) - end - local _, _, _, quality_color = GetItemQualityColor(recipe.quality) - - acquire_tip:Clear() - acquire_tip:SetScale(addon.db.profile.tooltip.scale) - acquire_tip:AddHeader() - acquire_tip:SetCell(1, 1, quality_color..recipe.name, "CENTER", 2) - - -- check if the recipe is excluded - if addon.db.profile.exclusionlist[recipe_id] then - ttAdd(0, -1, true, L["RECIPE_EXCLUDED"], "ff0000") - end - - -- Add in skill level requirement, colored correctly - local color_1 = BASIC_COLORS["normal"] - local color_2 - - local skill_level = Player["ProfessionLevel"] - local recipe_level = recipe.skill_level - local optimal_level = recipe.optimal_level - local medium_level = recipe.medium_level - local easy_level = recipe.easy_level - local trivial_level = recipe.trivial_level - local difficulty = private.difficulty_colors - - if recipe_level > skill_level then - color_2 = difficulty["impossible"] - elseif skill_level >= trivial_level then - color_2 = difficulty["trivial"] - elseif skill_level >= easy_level then - color_2 = difficulty["easy"] - elseif skill_level >= medium_level then - color_2 = difficulty["medium"] - elseif skill_level >= optimal_level then - color_2 = difficulty["optimal"] - else - color_2 = difficulty["trivial"] - end - ttAdd(0, -1, false, string.format("%s:", _G.SKILL_LEVEL), color_1, recipe.skill_level, color_2) - - -- Binding info - acquire_tip:AddSeparator() - color_1 = BASIC_COLORS["normal"] - - for flag, label in pairs(BINDING_FLAGS) do - if bit.band(recipe.flags.common1, flag) == flag then - ttAdd(0, -1, true, label, color_1) - end - end - acquire_tip:AddSeparator() - - if recipe.specialty then - local spec = recipe.specialty - local spec_name = GetSpellInfo(spec) - local known = (spec == Player["Specialty"]) - - ttAdd(0, -1, false, string.format(_G.ITEM_REQ_SKILL, spec_name), known and BASIC_COLORS["white"] or difficulty["impossible"]) - acquire_tip:AddSeparator() - end - - ttAdd(0, -1, false, L["Obtained From"] .. " : ", BASIC_COLORS["normal"]) - - local acquire_id = list_entry.acquire_id - local location = list_entry.location_id - - addon:DisplayAcquireData(recipe_id, acquire_id, location, ttAdd) - - if not addon.db.profile.hide_tooltip_hint then - -- Give the tooltip hint a unique color. - color_1 = "c9c781" - - acquire_tip:AddSeparator() - acquire_tip:AddSeparator() - - ttAdd(0, -1, 0, L["ALT_CLICK"], color_1) - ttAdd(0, -1, 0, L["CTRL_CLICK"], color_1) - ttAdd(0, -1, 0, L["SHIFT_CLICK"], color_1) - - if acquire_id ~= A.WORLD_DROP and acquire_id ~= A.CUSTOM and (_G.TomTom or _G.Cartographer_Waypoints) and (addon.db.profile.worldmap or addon.db.profile.minimap) then - ttAdd(0, -1, 0, L["CTRL_SHIFT_CLICK"], color_1) - end - end - acquire_tip:Show() - - -- If we have the spell link tooltip, link it to the acquire tooltip. - if spell_tip_anchor ~= _G.OFF and spell_link then - SetSpellTooltip(acquire_tip, spell_tip_anchor, spell_link) - else - spell_tip:Hide() - end - end -end -- do - -------------------------------------------------------------------------------- -- Create the MainPanel and set its values ------------------------------------------------------------------------------- local MainPanel @@ -1163,7 +676,7 @@ MainPanel.search_editbox = SearchBox SearchBox:SetText(_G.SEARCH) SearchBox:SetHistoryLines(10) --- Resets the SearchBox text and the state of all ListFrame and recipe_list entries. +-- Resets the SearchBox text and the state of all MainPanel.list_frame and recipe_list entries. function SearchBox:Reset() local recipe_list = private.recipe_list @@ -1174,7 +687,7 @@ function SearchBox:Reset() self:SetText(_G.SEARCH) self:ClearFocus() - ListFrame:Update(nil, false) + MainPanel.list_frame:Update(nil, false) end -- If there is text in the search box, return the recipe's RELEVANT state. @@ -1206,7 +719,7 @@ SearchBox:SetScript("OnEnterPressed", self:HighlightText() self:AddHistoryLine(searchtext) SearchRecipes(searchtext) - ListFrame:Update(nil, false) + MainPanel.list_frame:Update(nil, false) end) SearchBox:SetScript("OnEditFocusGained", @@ -1252,7 +765,7 @@ do last_update = 0 SearchRecipes(SearchBox:GetText()) - ListFrame:Update(nil, false) + MainPanel.list_frame:Update(nil, false) self:Hide() end end) @@ -1300,7 +813,7 @@ ExpandButtonFrame.middle:SetTexture("Interface\\QuestFrame\\UI-QuestLogSortTab-M local ExpandButton = GenericCreateButton(nil, MainPanel, 16, 16, "GameFontNormalSmall", _G.ALL, "LEFT", L["EXPANDALL_DESC"], 2) -MainPanel.expand_all_button = ExpandButton +MainPanel.expand_button = ExpandButton ExpandButton:SetPoint("LEFT", ExpandButtonFrame.left, "RIGHT", -3, -3) @@ -1324,10 +837,10 @@ ExpandButton:SetScript("OnClick", table.wipe(current_tab[prof_name.." expanded"]) end - -- ListFrame:Update() must be called before the button can be expanded or contracted, since + -- MainPanel.list_frame:Update() must be called before the button can be expanded or contracted, since -- the button is contracted from there. -- If expand_mode is nil, that means expand nothing. - ListFrame:Update(expand_mode, false) + MainPanel.list_frame:Update(expand_mode, false) if expanded then self:Contract(current_tab) @@ -1372,7 +885,7 @@ SkillToggle.text:SetPoint("LEFT", SkillToggle, "RIGHT", 0, 0) SkillToggle:SetScript("OnClick", function(self, button, down) addon.db.profile.skill_view = not addon.db.profile.skill_view - ListFrame:Update(nil, false) + MainPanel.list_frame:Update(nil, false) end) SkillToggle:SetScript("OnShow", @@ -1403,7 +916,7 @@ ExcludeToggle.text:SetPoint("LEFT", ExcludeToggle, "RIGHT", 0, 0) ExcludeToggle:SetScript("OnClick", function(self, button, down) addon.db.profile.ignoreexclusionlist = not addon.db.profile.ignoreexclusionlist - ListFrame:Update(nil, false) + MainPanel.list_frame:Update(nil, false) end) ExcludeToggle:SetScript("OnShow", @@ -1561,7 +1074,7 @@ do if MainPanel:IsVisible() then MainPanel:UpdateTitle() UpdateFilterMarks() - ListFrame:Update(nil, false) + MainPanel.list_frame:Update(nil, false) end end MainPanel.filter_reset:SetScript("OnClick", ResetFilters) @@ -1578,7 +1091,7 @@ do FilterValueMap[script_val].svroot[script_val] = FilterValueMap[script_val].cb:GetChecked() and true or false MainPanel:UpdateTitle() - ListFrame:Update(nil, false) + MainPanel.list_frame:Update(nil, false) end local function CreateCheckButton(parent, ttText, scriptVal, row, col) @@ -1612,30 +1125,6 @@ do end -- do ------------------------------------------------------------------------------- --- Create the ListFrame and set its scripts. -------------------------------------------------------------------------------- -ListFrame = CreateFrame("Frame", "ARL_MainPanelScrollFrame", MainPanel) - -MainPanel.list_frame = ListFrame - -ListFrame:SetHeight(335) -ListFrame:SetWidth(295) -ListFrame:SetPoint("TOPLEFT", MainPanel, "TOPLEFT", 22, -75) -ListFrame:SetBackdrop({ - bgFile = [[Interface\DialogFrame\UI-DialogBox-Background-Dark]], - tile = true, - tileSize = 16, - }) -ListFrame:SetBackdropColor(1, 1, 1) -ListFrame:EnableMouse(true) -ListFrame:EnableMouseWheel(true) - -ListFrame.entries = {} -ListFrame.button_containers = {} -ListFrame.state_buttons = {} -ListFrame.entry_buttons = {} - -------------------------------------------------------------------------------- -- Sort-mode toggle button. ------------------------------------------------------------------------------- local SortToggle = GenericCreateButton(nil, MainPanel, 24, 24, nil, nil, nil, L["SORTING_DESC"], 2) @@ -1651,7 +1140,7 @@ SortToggle:SetScript("OnClick", addon.db.profile.sorting = (sort_type == "Ascending" and "Descending" or "Ascending") self:SetTextures() - ListFrame:Update(nil, false) + MainPanel.list_frame:Update(nil, false) end) SortToggle:SetHighlightTexture([[Interface\CHATFRAME\UI-ChatIcon-BlinkHilight]]) @@ -1671,1026 +1160,6 @@ function SortToggle:SetTextures() end ------------------------------------------------------------------------------- --- Create ListFrame.scroll_bar, and set its scripts. -------------------------------------------------------------------------------- -local ScrollBar = CreateFrame("Slider", nil, ListFrame) - -ScrollBar:SetPoint("TOPLEFT", ListFrame, "TOPRIGHT", 5, -11) -ScrollBar:SetPoint("BOTTOMLEFT", ListFrame, "BOTTOMRIGHT", 5, 12) -ScrollBar:SetWidth(24) - -ScrollBar:EnableMouseWheel(true) -ScrollBar:SetOrientation("VERTICAL") - -ScrollBar:SetThumbTexture("Interface\\Buttons\\UI-ScrollBar-Knob") -ScrollBar:SetMinMaxValues(0, 1) -ScrollBar:SetValueStep(1) - -ListFrame.scroll_bar = ScrollBar - -------------------------------------------------------------------------------- --- Create ListFrame.button_up, then set its scripts and textures. --- Parented to ScrollBar so it hides simultaneously. -------------------------------------------------------------------------------- -local ScrollUpButton = CreateFrame("Button", nil, ScrollBar, "UIPanelScrollUpButtonTemplate") - -ScrollUpButton:SetHeight(16) -ScrollUpButton:SetWidth(18) -ScrollUpButton:SetPoint("BOTTOM", ScrollBar, "TOP", 0, -4) - -------------------------------------------------------------------------------- --- Create ListFrame.button_down, then set its scripts and textures. --- Parented to ScrollBar so it hides simultaneously. -------------------------------------------------------------------------------- -local ScrollDownButton = CreateFrame("Button", nil, ScrollBar,"UIPanelScrollDownButtonTemplate") - -ScrollDownButton:SetHeight(16) -ScrollDownButton:SetWidth(18) -ScrollDownButton:SetPoint("TOP", ScrollBar, "BOTTOM", 0, 4) - -do - -- Number of visible lines in the scrollframe. - local NUM_RECIPE_LINES = 25 - local SCROLL_DEPTH = 5 - - local function ScrollBar_Scroll(delta) - if not ScrollBar:IsShown() then - return - end - local cur_val = ScrollBar:GetValue() - local min_val, max_val = ScrollBar:GetMinMaxValues() - - if delta < 0 and cur_val < max_val then - cur_val = math.min(max_val, cur_val + SCROLL_DEPTH) - ScrollBar:SetValue(cur_val) - elseif delta > 0 and cur_val > min_val then - cur_val = math.max(min_val, cur_val - SCROLL_DEPTH) - ScrollBar:SetValue(cur_val) - end - end - - ScrollUpButton:SetScript("OnClick", - function(self, button, down) - if _G.IsAltKeyDown() then - local min_val = ScrollBar:GetMinMaxValues() - ScrollBar:SetValue(min_val) - else - ScrollBar_Scroll(1) - end - end) - - ScrollDownButton:SetScript("OnClick", - function(self, button, down) - if _G.IsAltKeyDown() then - local _, max_val = ScrollBar:GetMinMaxValues() - ScrollBar:SetValue(max_val) - else - ScrollBar_Scroll(-1) - end - end) - - ScrollBar:SetScript("OnMouseWheel", - function(self, delta) - ScrollBar_Scroll(delta) - end) - - ListFrame:SetScript("OnMouseWheel", - function(self, delta) - ScrollBar_Scroll(delta) - end) - - -- This can be called either from ListFrame's OnMouseWheel script, manually - -- sliding the thumb, or from clicking the up/down buttons. - ScrollBar:SetScript("OnValueChanged", - function(self, value) - local min_val, max_val = self:GetMinMaxValues() - local current_tab = MainPanel.tabs[MainPanel.current_tab] - local member = "profession_"..MainPanel.profession.."_scroll_value" - - current_tab[member] = value - - if value == min_val then - ScrollUpButton:Disable() - ScrollDownButton:Enable() - elseif value == max_val then - ScrollUpButton:Enable() - ScrollDownButton:Disable() - else - ScrollUpButton:Enable() - ScrollDownButton:Enable() - end - ListFrame:Update(nil, true) - end) - - local function Button_OnEnter(self) - ListItem_ShowTooltip(self, ListFrame.entries[self.string_index]) - end - - local function Button_OnLeave() - QTip:Release(acquire_tip) - spell_tip:Hide() - end - - local function Bar_OnEnter(self) - ListItem_ShowTooltip(self, ListFrame.entries[self.string_index]) - end - - local function Bar_OnLeave() - QTip:Release(acquire_tip) - spell_tip:Hide() - end - - local function ListItem_OnClick(self, button, down) - local clickedIndex = self.string_index - - -- Don't do anything if they've clicked on an empty button - if not clickedIndex or clickedIndex == 0 then - return - end - local clicked_line = ListFrame.entries[clickedIndex] - local traverseIndex = 0 - - if not clicked_line then - return - end - -- First, check if this is a "modified" click, and react appropriately - if clicked_line.recipe_id and _G.IsModifierKeyDown() then - if _G.IsControlKeyDown() and _G.IsShiftKeyDown() then - addon:AddWaypoint(clicked_line.recipe_id, clicked_line.acquire_id, clicked_line.location_id, clicked_line.npc_id) - elseif _G.IsShiftKeyDown() then - local itemID = private.recipe_list[clicked_line.recipe_id].item_id - - if itemID then - local _, itemLink = _G.GetItemInfo(itemID) - - if itemLink then - local edit_box = _G.ChatEdit_ChooseBoxForSend() - - _G.ChatEdit_ActivateChat(edit_box) - edit_box:Insert(itemLink) - else - addon:Print(L["NoItemLink"]) - end - else - addon:Print(L["NoItemLink"]) - end - elseif _G.IsControlKeyDown() then - local edit_box = _G.ChatEdit_ChooseBoxForSend() - - _G.ChatEdit_ActivateChat(edit_box) - edit_box:Insert(GetSpellLink(private.recipe_list[clicked_line.recipe_id].spell_id)) - elseif _G.IsAltKeyDown() then - local exclusion_list = addon.db.profile.exclusionlist - local recipe_id = clicked_line.recipe_id - - exclusion_list[recipe_id] = (not exclusion_list[recipe_id] and true or nil) - ListFrame:Update(nil, false) - end - elseif clicked_line.type == "header" or clicked_line.type == "subheader" then - -- three possibilities here (all with no modifiers) - -- 1) We clicked on the recipe button on a closed recipe - -- 2) We clicked on the recipe button of an open recipe - -- 3) we clicked on the expanded text of an open recipe - if clicked_line.is_expanded then - traverseIndex = clickedIndex + 1 - - local check_type = clicked_line.type - local entry = ListFrame.entries[traverseIndex] - local current_tab = MainPanel.tabs[MainPanel.current_tab] - - -- get rid of our expanded lines - while entry and entry.type ~= check_type do - -- Headers are never removed. - if entry.type == "header" then - break - end - current_tab:ModifyEntry(entry, false) - ReleaseTable(table.remove(ListFrame.entries, traverseIndex)) - entry = ListFrame.entries[traverseIndex] - - if not entry then - break - end - end - current_tab:ModifyEntry(clicked_line, false) - clicked_line.is_expanded = false - else - ListFrame:ExpandEntry(clickedIndex) - clicked_line.is_expanded = true - end - else - -- clicked_line is an expanded entry - find the index for its parent, and remove all of the parent's child entries. - local parent = clicked_line.parent - - if parent then - local parent_index - local entries = ListFrame.entries - - for index = 1, #entries do - if entries[index] == parent then - parent_index = index - break - end - end - - if not parent_index then - addon:Debug("clicked_line (%s): parent wasn't found in ListFrame.entries", clicked_line.text) - return - end - local current_tab = MainPanel.tabs[MainPanel.current_tab] - - parent.is_expanded = false - current_tab:ModifyEntry(parent, false) - - local child_index = parent_index + 1 - - while entries[child_index] and entries[child_index].parent == parent do - ReleaseTable(table.remove(entries, child_index)) - end - else - addon:Debug("Error: clicked_line has no parent.") - end - end - QTip:Release(acquire_tip) - spell_tip:Hide() - - ListFrame:Update(nil, true) - end - local LISTFRAME_WIDTH = ListFrame:GetWidth() - - ------------------------------------------------------------------------------- - -- Create the state/entry buttons and the container frames which hold them. - ------------------------------------------------------------------------------- - for i = 1, NUM_RECIPE_LINES do - local cur_container = CreateFrame("Frame", nil, ListFrame) - - cur_container:SetHeight(16) - cur_container:SetWidth(LISTFRAME_WIDTH) - - local cur_state = GenericCreateButton(nil, ListFrame, 16, 16, nil, nil, nil, nil, 2) - local cur_entry = GenericCreateButton(nil, ListFrame, 16, LISTFRAME_WIDTH, "GameFontNormalSmall", "Blort", "LEFT", nil, 0) - - if i == 1 then - cur_container:SetPoint("TOPLEFT", ListFrame, "TOPLEFT", 0, 0) - cur_state:SetPoint("TOPLEFT", cur_container, "TOPLEFT", 0, 0) - cur_entry:SetPoint("TOPLEFT", cur_state, "TOPRIGHT", -3, 0) - else - local prev_container = ListFrame.button_containers[i - 1] - - cur_container:SetPoint("TOPLEFT", prev_container, "BOTTOMLEFT", 0, 3) - cur_state:SetPoint("TOPLEFT", cur_container, "TOPLEFT", 0, 0) - cur_entry:SetPoint("TOPLEFT", cur_state, "TOPRIGHT", -3, 0) - end - cur_state.container = cur_container - - cur_state:SetScript("OnClick", ListItem_OnClick) - cur_entry:SetScript("OnClick", ListItem_OnClick) - - ListFrame.button_containers[i] = cur_container - ListFrame.state_buttons[i] = cur_state - ListFrame.entry_buttons[i] = cur_entry - end - - function ListFrame:InsertEntry(entry, parent_entry, entry_index, entry_type, entry_expanded, expand_mode) - entry.type = entry_type - - if parent_entry then - if parent_entry ~= entry then - entry.parent = parent_entry - - local recipe_id = parent_entry.recipe_id - local acquire_id = parent_entry.acquire_id - local location_id = parent_entry.location_id - local npc_id = parent_entry.npc_id - - if recipe_id then - entry.recipe_id = recipe_id - end - - if acquire_id then - entry.acquire_id = acquire_id - end - - if location_id then - entry.location_id = location_id - end - - if npc_id then - entry.npc_id = npc_id - end - else - addon:Debug("Attempting to parent an entry to itself.") - end - elseif entry.type ~= "header" then - addon:Debug("Non-header entry without a parent: %s - %s", entry.type, entry.text) - end - local insert_index = entry_index - - -- If we have acquire information for this entry, push the data table into the list - -- and start processing the acquires. - if expand_mode then - local current_tab = MainPanel.tabs[MainPanel.current_tab] - - entry.is_expanded = true - table.insert(self.entries, insert_index, entry) - - current_tab:ModifyEntry(entry, entry_expanded) - - if entry_type == "header" or entry_type == "subheader" then - insert_index = self:ExpandEntry(insert_index, expand_mode) - else - insert_index = insert_index + 1 - end - else - entry.is_expanded = entry_expanded - table.insert(self.entries, insert_index, entry) - - insert_index = insert_index + 1 - end - return insert_index - end - - function ListFrame:Initialize(expand_mode) - for i = 1, #self.entries do - ReleaseTable(self.entries[i]) - end - table.wipe(self.entries) - - addon:UpdateFilters(MainPanel.is_linked) - - ------------------------------------------------------------------------------- - -- Mark all exclusions in the recipe database to not be displayed, and update - -- the player's known and unknown counts. - ------------------------------------------------------------------------------- - local exclusion_list = addon.db.profile.exclusionlist - local ignored = not addon.db.profile.ignoreexclusionlist - local recipe_list = private.recipe_list - local current_prof = ORDERED_PROFESSIONS[MainPanel.profession] - local known_count = 0 - local unknown_count = 0 - - for spell_id in pairs(exclusion_list) do - local recipe = recipe_list[spell_id] - - if recipe then - if recipe:HasState("KNOWN") and recipe.profession == current_prof then - known_count = known_count + 1 - elseif recipe_profession == current_prof then - unknown_count = unknown_count + 1 - end - end - end - Player.excluded_recipes_known = known_count - Player.excluded_recipes_unknown = unknown_count - - ------------------------------------------------------------------------------- - -- Initialize the expand button and entries for the current tab. - ------------------------------------------------------------------------------- - local current_tab = MainPanel.tabs[addon.db.profile.current_tab] - local expanded_button = current_tab["expand_button_"..MainPanel.profession] - - if expanded_button then - ExpandButton:Expand(current_tab) - else - ExpandButton:Contract(current_tab) - end - local recipe_count = current_tab:Initialize(expand_mode) - - ------------------------------------------------------------------------------- - -- Update the progress bar display. - ------------------------------------------------------------------------------- - local profile = addon.db.profile - local max_value = profile.includefiltered and Player.recipes_total or Player.recipes_total_filtered - local cur_value = profile.includefiltered and Player.recipes_known or Player.recipes_known_filtered - - if not profile.includeexcluded and not profile.ignoreexclusionlist then - max_value = max_value - Player.excluded_recipes_known - end - local progress_bar = MainPanel.progress_bar - - progress_bar:SetMinMaxValues(0, max_value) - progress_bar:SetValue(cur_value) - - local percentage = cur_value / max_value * 100 - - if (floor(percentage) < 101) and cur_value >= 0 and max_value >= 0 then - local results = string.format(_G.SINGLE_PAGE_RESULTS_TEMPLATE, recipe_count) - progress_bar.text:SetFormattedText("%d/%d - %1.2f%% (%s)", cur_value, max_value, percentage, results) - else - progress_bar.text:SetFormattedText("%s", L["NOT_YET_SCANNED"]) - end - end - - -- Reset the current buttons/lines - function ListFrame:ClearLines() - local font_object = addon.db.profile.frameopts.small_list_font and "GameFontNormalSmall" or "GameFontNormal" - - for i = 1, NUM_RECIPE_LINES do - local entry = self.entry_buttons[i] - local state = self.state_buttons[i] - - entry.string_index = 0 - entry.text:SetFontObject(font_object) - - entry:SetText("") - entry:SetScript("OnEnter", nil) - entry:SetScript("OnLeave", nil) - entry:SetWidth(LISTFRAME_WIDTH) - entry:Disable() - - state.string_index = 0 - - state:Hide() - state:SetScript("OnEnter", nil) - state:SetScript("OnLeave", nil) - state:Disable() - - state:ClearAllPoints() - end - end - - function ListFrame:Update(expand_mode, refresh) - if not refresh then - self:Initialize(expand_mode) - end - - local num_entries = #self.entries - - if num_entries == 0 then - self:ClearLines() - - -- disable expand button, it's useless here and would spam the same error again - ExpandButton:SetNormalFontObject("GameFontDisableSmall") - ExpandButton:Disable() - self.scroll_bar:Hide() - - local showpopup = false - - if not addon.db.profile.hidepopup then - showpopup = true - end - - -- If we haven't run this before we'll show pop-ups for the first time. - if addon.db.profile.addonversion ~= addon.version then - addon.db.profile.addonversion = addon.version - showpopup = true - end - local editbox_text = SearchBox:GetText() - - if Player.recipes_total == 0 then - if showpopup then - _G.StaticPopup_Show("ARL_NOTSCANNED") - end - elseif Player.recipes_known == Player.recipes_total then - if showpopup then - _G.StaticPopup_Show("ARL_ALLKNOWN") - end - elseif (Player.recipes_total_filtered - Player.recipes_known_filtered) == 0 then - if showpopup then - _G.StaticPopup_Show("ARL_ALLFILTERED") - end - elseif Player.excluded_recipes_unknown ~= 0 then - if showpopup then - _G.StaticPopup_Show("ARL_ALLEXCLUDED") - end - elseif editbox_text ~= "" and editbox_text ~= _G.SEARCH then - _G.StaticPopup_Show("ARL_SEARCHFILTERED") - else - addon:Print(L["NO_DISPLAY"]) - addon:Debug("Current tab is %s", tostring(addon.db.profile.current_tab)) - addon:Debug("recipes_total check for 0") - addon:Debug("recipes_total: " .. Player.recipes_total) - addon:Debug("recipes_total check for equal to recipes_total") - addon:Debug("recipes_known: " .. Player.recipes_known) - addon:Debug("recipes_total: " .. Player.recipes_total) - addon:Debug("recipes_total_filtered - recipes_known_filtered = 0") - addon:Debug("recipes_total_filtered: " .. Player.recipes_total_filtered) - addon:Debug("recipes_known_filtered: " .. Player.recipes_known_filtered) - addon:Debug("excluded_recipes_unknown ~= 0") - addon:Debug("excluded_recipes_unknown: " .. Player.excluded_recipes_unknown) - end - return - end - local offset = 0 - - addon:ClosePopups() - - ExpandButton:SetNormalFontObject("GameFontNormalSmall") - ExpandButton:Enable() - - if num_entries <= NUM_RECIPE_LINES then - self.scroll_bar:Hide() - else - local max_val = num_entries - NUM_RECIPE_LINES - local current_tab = MainPanel.tabs[MainPanel.current_tab] - local scroll_value = current_tab["profession_"..MainPanel.profession.."_scroll_value"] or 0 - - scroll_value = math.max(0, math.min(scroll_value, max_val)) - offset = scroll_value - - self.scroll_bar:SetMinMaxValues(0, math.max(0, max_val)) - self.scroll_bar:SetValue(scroll_value) - self.scroll_bar:Show() - end - self:ClearLines() - - local button_index = 1 - local string_index = button_index + offset - - -- Populate the buttons with new values - while button_index <= NUM_RECIPE_LINES and string_index <= num_entries do - local cur_state = self.state_buttons[button_index] - local cur_entry = self.entries[string_index] - - if cur_entry.type == "header" or cur_entry.type == "subheader" then - cur_state:Show() - - if cur_entry.is_expanded then - cur_state:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up") - cur_state:SetPushedTexture("Interface\\Buttons\\UI-MinusButton-Down") - cur_state:SetHighlightTexture("Interface\\Buttons\\UI-PlusButton-Hilight") - cur_state:SetDisabledTexture("Interface\\Buttons\\UI-MinusButton-Disabled") - else - cur_state:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up") - cur_state:SetPushedTexture("Interface\\Buttons\\UI-PlusButton-Down") - cur_state:SetHighlightTexture("Interface\\Buttons\\UI-PlusButton-Hilight") - cur_state:SetDisabledTexture("Interface\\Buttons\\UI-PlusButton-Disabled") - end - cur_state.string_index = string_index - cur_state:SetScript("OnEnter", Button_OnEnter) - cur_state:SetScript("OnLeave", Button_OnLeave) - cur_state:Enable() - else - cur_state:Hide() - cur_state:Disable() - end - local cur_container = cur_state.container - local cur_button = self.entry_buttons[button_index] - - if cur_entry.type == "header" or cur_entry.type == "entry" then - cur_state:SetPoint("TOPLEFT", cur_container, "TOPLEFT", 0, 0) - elseif cur_entry.type == "subheader" or cur_entry.type == "subentry" then - cur_state:SetPoint("TOPLEFT", cur_container, "TOPLEFT", 15, 0) - cur_button:SetWidth(LISTFRAME_WIDTH - 15) - end - cur_button.string_index = string_index - cur_button:SetText(cur_entry.text) - cur_button:SetScript("OnEnter", Bar_OnEnter) - cur_button:SetScript("OnLeave", Bar_OnLeave) - cur_button:Enable() - - button_index = button_index + 1 - string_index = string_index + 1 - end - button_index = 1 - string_index = button_index + offset - - -- This function could possibly have been called from a mouse click or by scrolling. - -- Since, in those cases, the list entries have changed, the mouse is likely over a different entry - a tooltip should be generated for it. - while button_index <= NUM_RECIPE_LINES and string_index <= num_entries do - local cur_state = self.state_buttons[button_index] - local cur_button = self.entry_buttons[button_index] - - if cur_state:IsMouseOver() then - Button_OnEnter(cur_state) - break - elseif cur_button:IsMouseOver() then - Bar_OnEnter(cur_button) - break - end - button_index = button_index + 1 - string_index = string_index + 1 - end - end - ------------------------------------------------------------------------------- - -- Functions and data pertaining to individual list entries. - ------------------------------------------------------------------------------- - local faction_strings - - local function CanDisplayFaction(faction) - if addon.db.profile.filters.general.faction then - return true - end - return (not faction or faction == BFAC[Player.faction] or faction == FACTION_NEUTRAL) - end - - -- Padding for list entries/subentries - local PADDING = " " - - -- Changes the color of "name" based on faction type. - local function ColorNameByFaction(name, faction) - if faction == FACTION_NEUTRAL then - name = SetTextColor(private.reputation_colors["neutral"], name) - elseif faction == BFAC[Player.faction] then - name = SetTextColor(private.reputation_colors["exalted"], name) - else - name = SetTextColor(private.reputation_colors["hated"], name) - end - return name - end - - local function ExpandTrainerData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) - local trainer = private.trainer_list[id_num] - - if not CanDisplayFaction(trainer.faction) then - return entry_index - end - - local name = ColorNameByFaction(trainer.name, trainer.faction) - local coord_text = "" - - if trainer.coord_x ~= 0 and trainer.coord_y ~= 0 then - coord_text = SetTextColor(CATEGORY_COLORS["coords"], "(" .. trainer.coord_x .. ", " .. trainer.coord_y .. ")") - end - local t = AcquireTable() - - t.text = string.format("%s%s %s", PADDING, hide_type and "" or SetTextColor(CATEGORY_COLORS["trainer"], L["Trainer"])..":", name) - t.recipe_id = recipe_id - t.npc_id = id_num - - entry_index = ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) - - if coord_text == "" and hide_location then - return entry_index - end - t = AcquireTable() - t.text = string.format("%s%s%s %s", PADDING, PADDING, hide_location and "" or SetTextColor(CATEGORY_COLORS["location"], trainer.location), coord_text) - t.recipe_id = recipe_id - t.npc_id = id_num - - return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) - end - - -- Right now PVP obtained items are located on vendors so they have the vendor and PVP flag. - -- We need to display the vendor in the drop down if we want to see vendors or if we want to see PVP - -- This allows us to select PVP only and to see just the PVP recipes - local function ExpandVendorData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) - local vendor = private.vendor_list[id_num] - - if not CanDisplayFaction(vendor.faction) then - return entry_index - end - - local name = ColorNameByFaction(vendor.name, vendor.faction) - local coord_text = "" - - if vendor.coord_x ~= 0 and vendor.coord_y ~= 0 then - coord_text = SetTextColor(CATEGORY_COLORS["coords"], "(" .. vendor.coord_x .. ", " .. vendor.coord_y .. ")") - end - local t = AcquireTable() - local quantity = vendor.item_list[recipe_id] - - t.text = string.format("%s%s %s%s", PADDING, - hide_type and "" or SetTextColor(CATEGORY_COLORS["vendor"], L["Vendor"])..":", name, - type(quantity) == "number" and SetTextColor(BASIC_COLORS["white"], string.format(" (%d)", quantity)) or "") - t.recipe_id = recipe_id - t.npc_id = id_num - - entry_index = ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) - - if coord_text == "" and hide_location then - return entry_index - end - t = AcquireTable() - t.text = string.format("%s%s%s %s", PADDING, PADDING, hide_location and "" or SetTextColor(CATEGORY_COLORS["location"], vendor.location), coord_text) - t.recipe_id = recipe_id - t.npc_id = id_num - - return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) - end - - -- Mobs can be in instances, raids, or specific mob related drops. - local function ExpandMobData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) - local mob = private.mob_list[id_num] - local coord_text = "" - - if mob.coord_x ~= 0 and mob.coord_y ~= 0 then - coord_text = SetTextColor(CATEGORY_COLORS["coords"], "(" .. mob.coord_x .. ", " .. mob.coord_y .. ")") - end - local t = AcquireTable() - - t.text = string.format("%s%s %s", PADDING, hide_type and "" or SetTextColor(CATEGORY_COLORS["mobdrop"], L["Mob Drop"])..":", SetTextColor(private.reputation_colors["hostile"], mob.name)) - t.recipe_id = recipe_id - t.npc_id = id_num - - entry_index = ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) - - if coord_text == "" and hide_location then - return entry_index - end - t = AcquireTable() - t.text = string.format("%s%s%s %s", PADDING, PADDING, hide_location and "" or SetTextColor(CATEGORY_COLORS["location"], mob.location), coord_text) - t.recipe_id = recipe_id - t.npc_id = id_num - - return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) - end - - local function ExpandQuestData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) - local quest = private.quest_list[id_num] - - if not CanDisplayFaction(quest.faction) then - return entry_index - end - - local name = ColorNameByFaction(private.quest_names[id_num], quest.faction) - local coord_text = "" - - if quest.coord_x ~= 0 and quest.coord_y ~= 0 then - coord_text = SetTextColor(CATEGORY_COLORS["coords"], "(" .. quest.coord_x .. ", " .. quest.coord_y .. ")") - end - local t = AcquireTable() - - t.text = string.format("%s%s %s", PADDING, hide_type and "" or SetTextColor(CATEGORY_COLORS["quest"], L["Quest"])..":", name) - t.recipe_id = recipe_id - - entry_index = ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) - - if coord_text == "" and hide_location then - return entry_index - end - t = AcquireTable() - t.text = string.format("%s%s%s %s", PADDING, PADDING, hide_location and "" or SetTextColor(CATEGORY_COLORS["location"], quest.location), coord_text) - t.recipe_id = recipe_id - - return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) - end - - local function ExpandSeasonalData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) - local t = AcquireTable() - - t.text = string.format("%s%s %s", PADDING, hide_type and "" or SetTextColor(CATEGORY_COLORS["seasonal"], private.acquire_names[A.SEASONAL])..":", - SetTextColor(CATEGORY_COLORS["seasonal"], private.seasonal_list[id_num].name)) - t.recipe_id = recipe_id - - return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) - end - - local function ExpandReputationData(entry_index, entry_type, parent_entry, vendor_id, rep_id, rep_level, recipe_id, hide_location, hide_type) - local rep_vendor = private.vendor_list[vendor_id] - - if not CanDisplayFaction(rep_vendor.faction) then - return entry_index - end - - if not faction_strings then - local rep_color = private.reputation_colors - - faction_strings = { - [0] = SetTextColor(rep_color["neutral"], FACTION_NEUTRAL .. " : "), - [1] = SetTextColor(rep_color["friendly"], BFAC["Friendly"] .. " : "), - [2] = SetTextColor(rep_color["honored"], BFAC["Honored"] .. " : "), - [3] = SetTextColor(rep_color["revered"], BFAC["Revered"] .. " : "), - [4] = SetTextColor(rep_color["exalted"], BFAC["Exalted"] .. " : ") - } - end - - local name = ColorNameByFaction(rep_vendor.name, rep_vendor.faction) - local t = AcquireTable() - - t.text = string.format("%s%s %s", PADDING, hide_type and "" or SetTextColor(CATEGORY_COLORS["reputation"], _G.REPUTATION)..":", - SetTextColor(CATEGORY_COLORS["repname"], private.reputation_list[rep_id].name)) - t.recipe_id = recipe_id - t.npc_id = vendor_id - - entry_index = ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) - - t = AcquireTable() - t.text = PADDING .. PADDING .. faction_strings[rep_level] .. name - t.recipe_id = recipe_id - t.npc_id = vendor_id - - entry_index = ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) - - local coord_text = "" - - if rep_vendor.coord_x ~= 0 and rep_vendor.coord_y ~= 0 then - coord_text = SetTextColor(CATEGORY_COLORS["coords"], "(" .. rep_vendor.coord_x .. ", " .. rep_vendor.coord_y .. ")") - end - - if coord_text == "" and hide_location then - return entry_index - end - t = AcquireTable() - t.text = string.format("%s%s%s%s %s", PADDING, PADDING, PADDING, hide_location and "" or SetTextColor(CATEGORY_COLORS["location"], rep_vendor.location), coord_text) - t.recipe_id = recipe_id - t.npc_id = vendor_id - - return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) - end - - local function ExpandWorldDropData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) - local _, _, _, hex_color = GetItemQualityColor(private.recipe_list[recipe_id].quality) - local drop_location = type(id_num) == "string" and BZ[id_num] or nil - - if drop_location then - drop_location = string.format(": %s", SetTextColor(CATEGORY_COLORS["location"], drop_location)) - else - drop_location = "" - end - local t = AcquireTable() - - t.text = string.format("%s%s%s|r%s", PADDING, hex_color, L["World Drop"], drop_location) - t.recipe_id = recipe_id - - return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) - end - - local function ExpandCustomData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) - local t = AcquireTable() - - t.text = PADDING .. SetTextColor(CATEGORY_COLORS["custom"], private.custom_list[id_num].name) - t.recipe_id = recipe_id - - return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) - end - - function ListFrame:ExpandAcquireData(entry_index, entry_type, parent_entry, acquire_type, acquire_data, recipe_id, hide_location, hide_type) - local obtain_filters = addon.db.profile.filters.obtain - - for id_num, info in pairs(acquire_data) do - if acquire_type == A.TRAINER and obtain_filters.trainer then - entry_index = ExpandTrainerData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) - elseif acquire_type == A.VENDOR and (obtain_filters.vendor or obtain_filters.pvp) then - entry_index = ExpandVendorData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) - elseif acquire_type == A.MOB_DROP and (obtain_filters.mobdrop or obtain_filters.instance or obtain_filters.raid) then - entry_index = ExpandMobData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) - elseif acquire_type == A.QUEST and obtain_filters.quest then - entry_index = ExpandQuestData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) - elseif acquire_type == A.SEASONAL and obtain_filters.seasonal then - entry_index = ExpandSeasonalData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) - elseif acquire_type == A.REPUTATION then - for rep_level, level_info in pairs(info) do - for vendor_id in pairs(level_info) do - entry_index = ExpandReputationData(entry_index, entry_type, parent_entry, vendor_id, id_num, rep_level, recipe_id, hide_location, hide_type) - end - end - elseif acquire_type == A.WORLD_DROP and obtain_filters.worlddrop then - if not hide_type then - entry_index = ExpandWorldDropData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) - end - elseif acquire_type == A.CUSTOM then - if not hide_type then - entry_index = ExpandCustomData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) - end - --@alpha@ - elseif acquire_type > A_MAX then - local t = AcquireTable() - - t.text = "Unhandled Acquire Case - Type: " .. acquire_type - t.recipe_id = recipe_id - - entry_index = self:InsertEntry(t, parent_entry, entry_index, entry_type, true) - --@end-alpha@ - end - end -- for - return entry_index - end - - -- This function is called when an un-expanded entry in the list has been clicked. - function ListFrame:ExpandEntry(entry_index, expand_mode) - local orig_index = entry_index - local current_entry = self.entries[orig_index] - local expand_all = expand_mode == "deep" - local search_box = MainPanel.search_editbox - local current_tab = MainPanel.tabs[MainPanel.current_tab] - local prof_name = ORDERED_PROFESSIONS[MainPanel.profession] - - -- Entry_index is the position in self.entries that we want to expand. Since we are expanding the current entry, the return - -- value should be the index of the next button after the expansion occurs - entry_index = entry_index + 1 - - current_tab:ModifyEntry(current_entry, true) - - -- This entry was generated using sorting based on Acquisition. - if current_entry.acquire_id then - local acquire_id = current_entry.acquire_id - - if current_entry.type == "header" then - local recipe_list = private.acquire_list[acquire_id].recipes - local sorted_recipes = addon.sorted_recipes - - private.SortRecipeList(recipe_list) - - for index = 1, #sorted_recipes do - local spell_id = sorted_recipes[index] - local recipe_entry = private.recipe_list[spell_id] - - if recipe_entry:HasState("VISIBLE") and search_box:MatchesRecipe(recipe_entry) then - local t = AcquireTable() - local expand = false - local type = "subheader" - - if acquire_id == A.WORLD_DROP or acquire_id == A.CUSTOM then - expand = true - type = "entry" - end - local is_expanded = current_tab[prof_name.." expanded"][spell_id] and current_tab[prof_name.." expanded"][private.acquire_names[acquire_id]] - - t.text = recipe_entry:GetDisplayName() - t.recipe_id = spell_id - t.acquire_id = acquire_id - - entry_index = self:InsertEntry(t, current_entry, entry_index, type, expand or is_expanded, expand_all or is_expanded) - end - end - elseif current_entry.type == "subheader" then - for acquire_type, acquire_data in pairs(private.recipe_list[current_entry.recipe_id].acquire_data) do - if acquire_type == acquire_id then - entry_index = self:ExpandAcquireData(entry_index, "subentry", current_entry, acquire_type, acquire_data, current_entry.recipe_id, false, true) - end - end - end - return entry_index - end - - -- This entry was generated using sorting based on Location. - if current_entry.location_id then - local location_id = current_entry.location_id - - if current_entry.type == "header" then - local recipe_list = private.location_list[location_id].recipes - local sorted_recipes = addon.sorted_recipes - - private.SortRecipeList(recipe_list) - - for index = 1, #sorted_recipes do - local spell_id = sorted_recipes[index] - local recipe_entry = private.recipe_list[spell_id] - - if recipe_entry:HasState("VISIBLE") and search_box:MatchesRecipe(recipe_entry) then - local expand = false - local type = "subheader" - local t = AcquireTable() - - -- Add World Drop entries as normal entries. - if recipe_list[spell_id] == "world_drop" then - expand = true - type = "entry" - end - local is_expanded = current_tab[prof_name.." expanded"][spell_id] and current_tab[prof_name.." expanded"][location_id] - - t.text = recipe_entry:GetDisplayName() - t.recipe_id = spell_id - t.location_id = location_id - - entry_index = self:InsertEntry(t, current_entry, entry_index, type, expand or is_expanded, expand_all or is_expanded) - end - end - elseif current_entry.type == "subheader" then - local recipe_entry = private.recipe_list[current_entry.recipe_id] - - -- World Drops are not handled here because they are of type "entry". - for acquire_type, acquire_data in pairs(recipe_entry.acquire_data) do - for id_num, info in pairs(acquire_data) do - -- Only expand an acquisition entry if it is from this location. - if acquire_type == A.TRAINER and private.trainer_list[id_num].location == location_id then - entry_index = ExpandTrainerData(entry_index, "subentry", current_entry, - id_num, current_entry.recipe_id, true) - elseif acquire_type == A.VENDOR and private.vendor_list[id_num].location == location_id then - entry_index = ExpandVendorData(entry_index, "subentry", current_entry, - id_num, current_entry.recipe_id, true) - elseif acquire_type == A.MOB_DROP and private.mob_list[id_num].location == location_id then - entry_index = ExpandMobData(entry_index, "subentry", current_entry, - id_num, current_entry.recipe_id, true) - elseif acquire_type == A.QUEST and private.quest_list[id_num].location == location_id then - entry_index = ExpandQuestData(entry_index, "subentry", current_entry, - id_num, current_entry.recipe_id, true) - elseif acquire_type == A.SEASONAL and private.seasonal_list[id_num].location == location_id then - -- Hide the acquire type for this - it will already show up in the location list as "World Events". - entry_index = ExpandSeasonalData(entry_index, "subentry", current_entry, - id_num, current_entry.recipe_id, true, true) - elseif acquire_type == A.CUSTOM and private.custom_list[id_num].location == location_id then - entry_index = ExpandCustomData(entry_index, "subentry", current_entry, - id_num, current_entry.recipe_id, true, true) - elseif acquire_type == A.REPUTATION then - for rep_level, level_info in pairs(info) do - for vendor_id in pairs(level_info) do - if private.vendor_list[vendor_id].location == location_id then - entry_index = ExpandReputationData(entry_index, "subentry", current_entry, - vendor_id, id_num, rep_level, current_entry.recipe_id, true) - end - end - end - end - end - end - end - return entry_index - end - - -- Normal entry - expand all acquire types. - local recipe_id = self.entries[orig_index].recipe_id - - for acquire_type, acquire_data in pairs(private.recipe_list[recipe_id].acquire_data) do - entry_index = self:ExpandAcquireData(entry_index, "entry", current_entry, - acquire_type, acquire_data, recipe_id) - end - return entry_index - end -end -- do - -------------------------------------------------------------------------------- -- Create MainPanel.progress_bar and set its scripts ------------------------------------------------------------------------------- do @@ -2933,6 +1402,7 @@ local function InitializeFrame() ------------------------------------------------------------------------------- -- Initialize components defined in other files. ------------------------------------------------------------------------------- + private.InitializeListFrame() private.InitializeTabs() ------------------------------------------------------------------------------- @@ -3153,7 +1623,7 @@ local function InitializeFrame() general_frame[class]:SetChecked(true) end MainPanel:UpdateTitle() - ListFrame:Update(nil, false) + MainPanel.list_frame:Update(nil, false) end) general_frame.class_toggle = class_toggle @@ -3244,7 +1714,7 @@ local function InitializeFrame() item_frame[armor]:SetChecked(toggle) end MainPanel:UpdateTitle() - ListFrame:Update(nil, false) + MainPanel.list_frame:Update(nil, false) end) item_frame.armor_toggle = armor_toggle @@ -3284,7 +1754,7 @@ local function InitializeFrame() end end MainPanel:UpdateTitle() - ListFrame:Update(nil, false) + MainPanel.list_frame:Update(nil, false) end) item_frame.weapon_toggle = weapon_toggle @@ -3520,7 +1990,7 @@ local function InitializeFrame() expansion0_frame[reputation]:SetChecked(filterdb[reputation]) end MainPanel:UpdateTitle() - ListFrame:Update(nil, false) + MainPanel.list_frame:Update(nil, false) end) end -- do-block @@ -3583,7 +2053,7 @@ local function InitializeFrame() expansion1_frame[reputation]:SetChecked(filterdb[reputation]) end MainPanel:UpdateTitle() - ListFrame:Update(nil, false) + MainPanel.list_frame:Update(nil, false) end) end -- do-block @@ -3656,7 +2126,7 @@ local function InitializeFrame() expansion2_frame[reputation]:SetChecked(filterdb[reputation]) end MainPanel:UpdateTitle() - ListFrame:Update(nil, false) + MainPanel.list_frame:Update(nil, false) end) end -- do-block @@ -3902,7 +2372,7 @@ do editbox:SetText(editbox.prev_search or _G.SEARCH) -- If there is no current tab, this is the first time the panel has been - -- shown so things must be initialized. In this case, ListFrame:Update() + -- shown so things must be initialized. In this case, MainPanel.list_frame:Update() -- will be called by the tab's OnClick handler. if not self.current_tab then local current_tab = self.tabs[addon.db.profile.current_tab] @@ -3912,7 +2382,7 @@ do self.current_tab = addon.db.profile.current_tab else - ListFrame:Update(nil, false) + MainPanel.list_frame:Update(nil, false) end self.sort_button:SetTextures() self.filter_toggle:SetTextures() diff --git a/Interface/List.lua b/Interface/List.lua new file mode 100644 index 0000000..da652ab --- /dev/null +++ b/Interface/List.lua @@ -0,0 +1,1566 @@ +------------------------------------------------------------------------------- +-- Localized Lua globals. +------------------------------------------------------------------------------- +local _G = getfenv(0) + +local string = _G.string +local table = _G.table + +------------------------------------------------------------------------------- +-- AddOn namespace. +------------------------------------------------------------------------------- +local LibStub = LibStub + +local MODNAME = "Ackis Recipe List" +local addon = LibStub("AceAddon-3.0"):GetAddon(MODNAME) + +local BFAC = LibStub("LibBabble-Faction-3.0"):GetLookupTable() +local BZ = LibStub("LibBabble-Zone-3.0"):GetLookupTable() +local L = LibStub("AceLocale-3.0"):GetLocale(MODNAME) +local QTip = LibStub("LibQTip-1.0") + +-- Set up the private intra-file namespace. +local private = select(2, ...) + +local Player = private.Player + +------------------------------------------------------------------------------- +-- Constants +------------------------------------------------------------------------------- +local NUM_RECIPE_LINES = 25 +local SCROLL_DEPTH = 5 +local LISTFRAME_WIDTH = 295 + +local CATEGORY_COLORS = private.category_colors +local BASIC_COLORS = private.basic_colors + +local SF = private.recipe_state_flags +local COMMON_FLAGS_1 = private.common_flags_word1 + +local A = private.acquire_types +local A_MAX = 9 + +local FACTION_NEUTRAL = BFAC["Neutral"] + +------------------------------------------------------------------------------- +-- Upvalues +------------------------------------------------------------------------------- +local ListItem_ShowTooltip + +local acquire_tip +local spell_tip + +local AcquireTable = private.AcquireTable +local ReleaseTable = private.ReleaseTable +local SetTextColor = private.SetTextColor +local GenericCreateButton = private.GenericCreateButton + +------------------------------------------------------------------------------- +-- Frame creation and anchoring +------------------------------------------------------------------------------- +function private.InitializeListFrame() + local MainPanel = addon.Frame + local ListFrame = CreateFrame("Frame", nil, MainPanel) + + MainPanel.list_frame = ListFrame + + ListFrame:SetHeight(335) + ListFrame:SetWidth(LISTFRAME_WIDTH) + ListFrame:SetPoint("TOPLEFT", MainPanel, "TOPLEFT", 22, -75) + ListFrame:SetBackdrop({ + bgFile = [[Interface\DialogFrame\UI-DialogBox-Background-Dark]], + tile = true, + tileSize = 16, + }) + ListFrame:SetBackdropColor(1, 1, 1) + ListFrame:EnableMouse(true) + ListFrame:EnableMouseWheel(true) + + ------------------------------------------------------------------------------- + -- Scroll bar. + ------------------------------------------------------------------------------- + local ScrollBar = CreateFrame("Slider", nil, ListFrame) + + ScrollBar:SetPoint("TOPLEFT", ListFrame, "TOPRIGHT", 5, -11) + ScrollBar:SetPoint("BOTTOMLEFT", ListFrame, "BOTTOMRIGHT", 5, 12) + ScrollBar:SetWidth(24) + + ScrollBar:EnableMouseWheel(true) + ScrollBar:SetOrientation("VERTICAL") + + ScrollBar:SetThumbTexture("Interface\\Buttons\\UI-ScrollBar-Knob") + ScrollBar:SetMinMaxValues(0, 1) + ScrollBar:SetValueStep(1) + + ListFrame.scroll_bar = ScrollBar + + local ScrollUpButton = CreateFrame("Button", nil, ScrollBar, "UIPanelScrollUpButtonTemplate") + + ScrollUpButton:SetHeight(16) + ScrollUpButton:SetWidth(18) + ScrollUpButton:SetPoint("BOTTOM", ScrollBar, "TOP", 0, -4) + + local ScrollDownButton = CreateFrame("Button", nil, ScrollBar,"UIPanelScrollDownButtonTemplate") + + ScrollDownButton:SetHeight(16) + ScrollDownButton:SetWidth(18) + ScrollDownButton:SetPoint("TOP", ScrollBar, "BOTTOM", 0, 4) + + local function ScrollBar_Scroll(delta) + if not ScrollBar:IsShown() then + return + end + local cur_val = ScrollBar:GetValue() + local min_val, max_val = ScrollBar:GetMinMaxValues() + + if delta < 0 and cur_val < max_val then + cur_val = math.min(max_val, cur_val + SCROLL_DEPTH) + ScrollBar:SetValue(cur_val) + elseif delta > 0 and cur_val > min_val then + cur_val = math.max(min_val, cur_val - SCROLL_DEPTH) + ScrollBar:SetValue(cur_val) + end + end + + ScrollUpButton:SetScript("OnClick", + function(self, button, down) + if _G.IsAltKeyDown() then + local min_val = ScrollBar:GetMinMaxValues() + ScrollBar:SetValue(min_val) + else + ScrollBar_Scroll(1) + end + end) + + ScrollDownButton:SetScript("OnClick", + function(self, button, down) + if _G.IsAltKeyDown() then + local _, max_val = ScrollBar:GetMinMaxValues() + ScrollBar:SetValue(max_val) + else + ScrollBar_Scroll(-1) + end + end) + + ScrollBar:SetScript("OnMouseWheel", + function(self, delta) + ScrollBar_Scroll(delta) + end) + + ListFrame:SetScript("OnMouseWheel", + function(self, delta) + ScrollBar_Scroll(delta) + end) + + -- This can be called either from ListFrame's OnMouseWheel script, manually + -- sliding the thumb, or from clicking the up/down buttons. + ScrollBar:SetScript("OnValueChanged", + function(self, value) + local min_val, max_val = self:GetMinMaxValues() + local current_tab = MainPanel.tabs[MainPanel.current_tab] + local member = "profession_"..MainPanel.profession.."_scroll_value" + + current_tab[member] = value + + if value == min_val then + ScrollUpButton:Disable() + ScrollDownButton:Enable() + elseif value == max_val then + ScrollUpButton:Enable() + ScrollDownButton:Disable() + else + ScrollUpButton:Enable() + ScrollDownButton:Enable() + end + ListFrame:Update(nil, true) + end) + + local function Button_OnEnter(self) + ListItem_ShowTooltip(self, ListFrame.entries[self.string_index]) + end + + local function Button_OnLeave() + QTip:Release(acquire_tip) + spell_tip:Hide() + end + + local function Bar_OnEnter(self) + ListItem_ShowTooltip(self, ListFrame.entries[self.string_index]) + end + + local function Bar_OnLeave() + QTip:Release(acquire_tip) + spell_tip:Hide() + end + + local function ListItem_OnClick(self, button, down) + local clickedIndex = self.string_index + + -- Don't do anything if they've clicked on an empty button + if not clickedIndex or clickedIndex == 0 then + return + end + local clicked_line = ListFrame.entries[clickedIndex] + local traverseIndex = 0 + + if not clicked_line then + return + end + -- First, check if this is a "modified" click, and react appropriately + if clicked_line.recipe_id and _G.IsModifierKeyDown() then + if _G.IsControlKeyDown() and _G.IsShiftKeyDown() then + addon:AddWaypoint(clicked_line.recipe_id, clicked_line.acquire_id, clicked_line.location_id, clicked_line.npc_id) + elseif _G.IsShiftKeyDown() then + local itemID = private.recipe_list[clicked_line.recipe_id].item_id + + if itemID then + local _, itemLink = _G.GetItemInfo(itemID) + + if itemLink then + local edit_box = _G.ChatEdit_ChooseBoxForSend() + + _G.ChatEdit_ActivateChat(edit_box) + edit_box:Insert(itemLink) + else + addon:Print(L["NoItemLink"]) + end + else + addon:Print(L["NoItemLink"]) + end + elseif _G.IsControlKeyDown() then + local edit_box = _G.ChatEdit_ChooseBoxForSend() + + _G.ChatEdit_ActivateChat(edit_box) + edit_box:Insert(GetSpellLink(private.recipe_list[clicked_line.recipe_id].spell_id)) + elseif _G.IsAltKeyDown() then + local exclusion_list = addon.db.profile.exclusionlist + local recipe_id = clicked_line.recipe_id + + exclusion_list[recipe_id] = (not exclusion_list[recipe_id] and true or nil) + ListFrame:Update(nil, false) + end + elseif clicked_line.type == "header" or clicked_line.type == "subheader" then + -- three possibilities here (all with no modifiers) + -- 1) We clicked on the recipe button on a closed recipe + -- 2) We clicked on the recipe button of an open recipe + -- 3) we clicked on the expanded text of an open recipe + if clicked_line.is_expanded then + traverseIndex = clickedIndex + 1 + + local check_type = clicked_line.type + local entry = ListFrame.entries[traverseIndex] + local current_tab = MainPanel.tabs[MainPanel.current_tab] + + -- get rid of our expanded lines + while entry and entry.type ~= check_type do + -- Headers are never removed. + if entry.type == "header" then + break + end + current_tab:ModifyEntry(entry, false) + ReleaseTable(table.remove(ListFrame.entries, traverseIndex)) + entry = ListFrame.entries[traverseIndex] + + if not entry then + break + end + end + current_tab:ModifyEntry(clicked_line, false) + clicked_line.is_expanded = false + else + ListFrame:ExpandEntry(clickedIndex) + clicked_line.is_expanded = true + end + else + -- clicked_line is an expanded entry - find the index for its parent, and remove all of the parent's child entries. + local parent = clicked_line.parent + + if parent then + local parent_index + local entries = ListFrame.entries + + for index = 1, #entries do + if entries[index] == parent then + parent_index = index + break + end + end + + if not parent_index then + addon:Debug("clicked_line (%s): parent wasn't found in ListFrame.entries", clicked_line.text) + return + end + local current_tab = MainPanel.tabs[MainPanel.current_tab] + + parent.is_expanded = false + current_tab:ModifyEntry(parent, false) + + local child_index = parent_index + 1 + + while entries[child_index] and entries[child_index].parent == parent do + ReleaseTable(table.remove(entries, child_index)) + end + else + addon:Debug("Error: clicked_line has no parent.") + end + end + QTip:Release(acquire_tip) + spell_tip:Hide() + + ListFrame:Update(nil, true) + end + + ------------------------------------------------------------------------------- + -- The state and entry buttons and the container frames which hold them. + ------------------------------------------------------------------------------- + ListFrame.entries = {} + ListFrame.button_containers = {} + ListFrame.state_buttons = {} + ListFrame.entry_buttons = {} + + for i = 1, NUM_RECIPE_LINES do + local cur_container = CreateFrame("Frame", nil, ListFrame) + + cur_container:SetHeight(16) + cur_container:SetWidth(LISTFRAME_WIDTH) + + local cur_state = GenericCreateButton(nil, ListFrame, 16, 16, nil, nil, nil, nil, 2) + local cur_entry = GenericCreateButton(nil, ListFrame, 16, LISTFRAME_WIDTH, "GameFontNormalSmall", "Blort", "LEFT", nil, 0) + + if i == 1 then + cur_container:SetPoint("TOPLEFT", ListFrame, "TOPLEFT", 0, 0) + cur_state:SetPoint("TOPLEFT", cur_container, "TOPLEFT", 0, 0) + cur_entry:SetPoint("TOPLEFT", cur_state, "TOPRIGHT", -3, 0) + else + local prev_container = ListFrame.button_containers[i - 1] + + cur_container:SetPoint("TOPLEFT", prev_container, "BOTTOMLEFT", 0, 3) + cur_state:SetPoint("TOPLEFT", cur_container, "TOPLEFT", 0, 0) + cur_entry:SetPoint("TOPLEFT", cur_state, "TOPRIGHT", -3, 0) + end + cur_state.container = cur_container + + cur_state:SetScript("OnClick", ListItem_OnClick) + cur_entry:SetScript("OnClick", ListItem_OnClick) + + ListFrame.button_containers[i] = cur_container + ListFrame.state_buttons[i] = cur_state + ListFrame.entry_buttons[i] = cur_entry + end + + function ListFrame:InsertEntry(entry, parent_entry, entry_index, entry_type, entry_expanded, expand_mode) + entry.type = entry_type + + if parent_entry then + if parent_entry ~= entry then + entry.parent = parent_entry + + local recipe_id = parent_entry.recipe_id + local acquire_id = parent_entry.acquire_id + local location_id = parent_entry.location_id + local npc_id = parent_entry.npc_id + + if recipe_id then + entry.recipe_id = recipe_id + end + + if acquire_id then + entry.acquire_id = acquire_id + end + + if location_id then + entry.location_id = location_id + end + + if npc_id then + entry.npc_id = npc_id + end + else + addon:Debug("Attempting to parent an entry to itself.") + end + elseif entry.type ~= "header" then + addon:Debug("Non-header entry without a parent: %s - %s", entry.type, entry.text) + end + local insert_index = entry_index + + -- If we have acquire information for this entry, push the data table into the list + -- and start processing the acquires. + if expand_mode then + local current_tab = MainPanel.tabs[MainPanel.current_tab] + + entry.is_expanded = true + table.insert(self.entries, insert_index, entry) + + current_tab:ModifyEntry(entry, entry_expanded) + + if entry_type == "header" or entry_type == "subheader" then + insert_index = self:ExpandEntry(insert_index, expand_mode) + else + insert_index = insert_index + 1 + end + else + entry.is_expanded = entry_expanded + table.insert(self.entries, insert_index, entry) + + insert_index = insert_index + 1 + end + return insert_index + end + + function ListFrame:Initialize(expand_mode) + for i = 1, #self.entries do + ReleaseTable(self.entries[i]) + end + table.wipe(self.entries) + + addon:UpdateFilters(MainPanel.is_linked) + + ------------------------------------------------------------------------------- + -- Mark all exclusions in the recipe database to not be displayed, and update + -- the player's known and unknown counts. + ------------------------------------------------------------------------------- + local exclusion_list = addon.db.profile.exclusionlist + local ignored = not addon.db.profile.ignoreexclusionlist + local recipe_list = private.recipe_list + local current_prof = private.ordered_professions[MainPanel.profession] + local known_count = 0 + local unknown_count = 0 + + for spell_id in pairs(exclusion_list) do + local recipe = recipe_list[spell_id] + + if recipe then + if recipe:HasState("KNOWN") and recipe.profession == current_prof then + known_count = known_count + 1 + elseif recipe_profession == current_prof then + unknown_count = unknown_count + 1 + end + end + end + Player.excluded_recipes_known = known_count + Player.excluded_recipes_unknown = unknown_count + + ------------------------------------------------------------------------------- + -- Initialize the expand button and entries for the current tab. + ------------------------------------------------------------------------------- + local current_tab = MainPanel.tabs[addon.db.profile.current_tab] + local expanded_button = current_tab["expand_button_"..MainPanel.profession] + + if expanded_button then + MainPanel.expand_button:Expand(current_tab) + else + MainPanel.expand_button:Contract(current_tab) + end + local recipe_count = current_tab:Initialize(expand_mode) + + ------------------------------------------------------------------------------- + -- Update the progress bar display. + ------------------------------------------------------------------------------- + local profile = addon.db.profile + local max_value = profile.includefiltered and Player.recipes_total or Player.recipes_total_filtered + local cur_value = profile.includefiltered and Player.recipes_known or Player.recipes_known_filtered + + if not profile.includeexcluded and not profile.ignoreexclusionlist then + max_value = max_value - Player.excluded_recipes_known + end + local progress_bar = MainPanel.progress_bar + + progress_bar:SetMinMaxValues(0, max_value) + progress_bar:SetValue(cur_value) + + local percentage = cur_value / max_value * 100 + + if (floor(percentage) < 101) and cur_value >= 0 and max_value >= 0 then + local results = string.format(_G.SINGLE_PAGE_RESULTS_TEMPLATE, recipe_count) + progress_bar.text:SetFormattedText("%d/%d - %1.2f%% (%s)", cur_value, max_value, percentage, results) + else + progress_bar.text:SetFormattedText("%s", L["NOT_YET_SCANNED"]) + end + end + + -- Reset the current buttons/lines + function ListFrame:ClearLines() + local font_object = addon.db.profile.frameopts.small_list_font and "GameFontNormalSmall" or "GameFontNormal" + + for i = 1, NUM_RECIPE_LINES do + local entry = self.entry_buttons[i] + local state = self.state_buttons[i] + + entry.string_index = 0 + entry.text:SetFontObject(font_object) + + entry:SetText("") + entry:SetScript("OnEnter", nil) + entry:SetScript("OnLeave", nil) + entry:SetWidth(LISTFRAME_WIDTH) + entry:Disable() + + state.string_index = 0 + + state:Hide() + state:SetScript("OnEnter", nil) + state:SetScript("OnLeave", nil) + state:Disable() + + state:ClearAllPoints() + end + end + + function ListFrame:Update(expand_mode, refresh) + if not refresh then + self:Initialize(expand_mode) + end + + local num_entries = #self.entries + + if num_entries == 0 then + self:ClearLines() + + -- disable expand button, it's useless here and would spam the same error again + MainPanel.expand_button:SetNormalFontObject("GameFontDisableSmall") + MainPanel.expand_button:Disable() + self.scroll_bar:Hide() + + local showpopup = false + + if not addon.db.profile.hidepopup then + showpopup = true + end + + -- If we haven't run this before we'll show pop-ups for the first time. + if addon.db.profile.addonversion ~= addon.version then + addon.db.profile.addonversion = addon.version + showpopup = true + end + local editbox_text = SearchBox:GetText() + + if Player.recipes_total == 0 then + if showpopup then + _G.StaticPopup_Show("ARL_NOTSCANNED") + end + elseif Player.recipes_known == Player.recipes_total then + if showpopup then + _G.StaticPopup_Show("ARL_ALLKNOWN") + end + elseif (Player.recipes_total_filtered - Player.recipes_known_filtered) == 0 then + if showpopup then + _G.StaticPopup_Show("ARL_ALLFILTERED") + end + elseif Player.excluded_recipes_unknown ~= 0 then + if showpopup then + _G.StaticPopup_Show("ARL_ALLEXCLUDED") + end + elseif editbox_text ~= "" and editbox_text ~= _G.SEARCH then + _G.StaticPopup_Show("ARL_SEARCHFILTERED") + else + addon:Print(L["NO_DISPLAY"]) + addon:Debug("Current tab is %s", tostring(addon.db.profile.current_tab)) + addon:Debug("recipes_total check for 0") + addon:Debug("recipes_total: " .. Player.recipes_total) + addon:Debug("recipes_total check for equal to recipes_total") + addon:Debug("recipes_known: " .. Player.recipes_known) + addon:Debug("recipes_total: " .. Player.recipes_total) + addon:Debug("recipes_total_filtered - recipes_known_filtered = 0") + addon:Debug("recipes_total_filtered: " .. Player.recipes_total_filtered) + addon:Debug("recipes_known_filtered: " .. Player.recipes_known_filtered) + addon:Debug("excluded_recipes_unknown ~= 0") + addon:Debug("excluded_recipes_unknown: " .. Player.excluded_recipes_unknown) + end + return + end + local offset = 0 + + addon:ClosePopups() + + MainPanel.expand_button:SetNormalFontObject("GameFontNormalSmall") + MainPanel.expand_button:Enable() + + if num_entries <= NUM_RECIPE_LINES then + self.scroll_bar:Hide() + else + local max_val = num_entries - NUM_RECIPE_LINES + local current_tab = MainPanel.tabs[MainPanel.current_tab] + local scroll_value = current_tab["profession_"..MainPanel.profession.."_scroll_value"] or 0 + + scroll_value = math.max(0, math.min(scroll_value, max_val)) + offset = scroll_value + + self.scroll_bar:SetMinMaxValues(0, math.max(0, max_val)) + self.scroll_bar:SetValue(scroll_value) + self.scroll_bar:Show() + end + self:ClearLines() + + local button_index = 1 + local string_index = button_index + offset + + -- Populate the buttons with new values + while button_index <= NUM_RECIPE_LINES and string_index <= num_entries do + local cur_state = self.state_buttons[button_index] + local cur_entry = self.entries[string_index] + + if cur_entry.type == "header" or cur_entry.type == "subheader" then + cur_state:Show() + + if cur_entry.is_expanded then + cur_state:SetNormalTexture("Interface\\Buttons\\UI-MinusButton-Up") + cur_state:SetPushedTexture("Interface\\Buttons\\UI-MinusButton-Down") + cur_state:SetHighlightTexture("Interface\\Buttons\\UI-PlusButton-Hilight") + cur_state:SetDisabledTexture("Interface\\Buttons\\UI-MinusButton-Disabled") + else + cur_state:SetNormalTexture("Interface\\Buttons\\UI-PlusButton-Up") + cur_state:SetPushedTexture("Interface\\Buttons\\UI-PlusButton-Down") + cur_state:SetHighlightTexture("Interface\\Buttons\\UI-PlusButton-Hilight") + cur_state:SetDisabledTexture("Interface\\Buttons\\UI-PlusButton-Disabled") + end + cur_state.string_index = string_index + cur_state:SetScript("OnEnter", Button_OnEnter) + cur_state:SetScript("OnLeave", Button_OnLeave) + cur_state:Enable() + else + cur_state:Hide() + cur_state:Disable() + end + local cur_container = cur_state.container + local cur_button = self.entry_buttons[button_index] + + if cur_entry.type == "header" or cur_entry.type == "entry" then + cur_state:SetPoint("TOPLEFT", cur_container, "TOPLEFT", 0, 0) + elseif cur_entry.type == "subheader" or cur_entry.type == "subentry" then + cur_state:SetPoint("TOPLEFT", cur_container, "TOPLEFT", 15, 0) + cur_button:SetWidth(LISTFRAME_WIDTH - 15) + end + cur_button.string_index = string_index + cur_button:SetText(cur_entry.text) + cur_button:SetScript("OnEnter", Bar_OnEnter) + cur_button:SetScript("OnLeave", Bar_OnLeave) + cur_button:Enable() + + button_index = button_index + 1 + string_index = string_index + 1 + end + button_index = 1 + string_index = button_index + offset + + -- This function could possibly have been called from a mouse click or by scrolling. + -- Since, in those cases, the list entries have changed, the mouse is likely over a different entry - a tooltip should be generated for it. + while button_index <= NUM_RECIPE_LINES and string_index <= num_entries do + local cur_state = self.state_buttons[button_index] + local cur_button = self.entry_buttons[button_index] + + if cur_state:IsMouseOver() then + Button_OnEnter(cur_state) + break + elseif cur_button:IsMouseOver() then + Bar_OnEnter(cur_button) + break + end + button_index = button_index + 1 + string_index = string_index + 1 + end + end + + ------------------------------------------------------------------------------- + -- Functions and data pertaining to individual list entries. + ------------------------------------------------------------------------------- + local faction_strings + + local function CanDisplayFaction(faction) + if addon.db.profile.filters.general.faction then + return true + end + return (not faction or faction == BFAC[Player.faction] or faction == FACTION_NEUTRAL) + end + + -- Padding for list entries/subentries + local PADDING = " " + + -- Changes the color of "name" based on faction type. + local function ColorNameByFaction(name, faction) + if faction == FACTION_NEUTRAL then + name = SetTextColor(private.reputation_colors["neutral"], name) + elseif faction == BFAC[Player.faction] then + name = SetTextColor(private.reputation_colors["exalted"], name) + else + name = SetTextColor(private.reputation_colors["hated"], name) + end + return name + end + + local function ExpandTrainerData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) + local trainer = private.trainer_list[id_num] + + if not CanDisplayFaction(trainer.faction) then + return entry_index + end + + local name = ColorNameByFaction(trainer.name, trainer.faction) + local coord_text = "" + + if trainer.coord_x ~= 0 and trainer.coord_y ~= 0 then + coord_text = SetTextColor(CATEGORY_COLORS["coords"], "(" .. trainer.coord_x .. ", " .. trainer.coord_y .. ")") + end + local t = AcquireTable() + + t.text = string.format("%s%s %s", PADDING, hide_type and "" or SetTextColor(CATEGORY_COLORS["trainer"], L["Trainer"])..":", name) + t.recipe_id = recipe_id + t.npc_id = id_num + + entry_index = ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) + + if coord_text == "" and hide_location then + return entry_index + end + t = AcquireTable() + t.text = string.format("%s%s%s %s", PADDING, PADDING, hide_location and "" or SetTextColor(CATEGORY_COLORS["location"], trainer.location), coord_text) + t.recipe_id = recipe_id + t.npc_id = id_num + + return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) + end + + -- Right now PVP obtained items are located on vendors so they have the vendor and PVP flag. + -- We need to display the vendor in the drop down if we want to see vendors or if we want to see PVP + -- This allows us to select PVP only and to see just the PVP recipes + local function ExpandVendorData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) + local vendor = private.vendor_list[id_num] + + if not CanDisplayFaction(vendor.faction) then + return entry_index + end + + local name = ColorNameByFaction(vendor.name, vendor.faction) + local coord_text = "" + + if vendor.coord_x ~= 0 and vendor.coord_y ~= 0 then + coord_text = SetTextColor(CATEGORY_COLORS["coords"], "(" .. vendor.coord_x .. ", " .. vendor.coord_y .. ")") + end + local t = AcquireTable() + local quantity = vendor.item_list[recipe_id] + + t.text = string.format("%s%s %s%s", PADDING, + hide_type and "" or SetTextColor(CATEGORY_COLORS["vendor"], L["Vendor"])..":", name, + type(quantity) == "number" and SetTextColor(BASIC_COLORS["white"], string.format(" (%d)", quantity)) or "") + t.recipe_id = recipe_id + t.npc_id = id_num + + entry_index = ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) + + if coord_text == "" and hide_location then + return entry_index + end + t = AcquireTable() + t.text = string.format("%s%s%s %s", PADDING, PADDING, hide_location and "" or SetTextColor(CATEGORY_COLORS["location"], vendor.location), coord_text) + t.recipe_id = recipe_id + t.npc_id = id_num + + return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) + end + + -- Mobs can be in instances, raids, or specific mob related drops. + local function ExpandMobData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) + local mob = private.mob_list[id_num] + local coord_text = "" + + if mob.coord_x ~= 0 and mob.coord_y ~= 0 then + coord_text = SetTextColor(CATEGORY_COLORS["coords"], "(" .. mob.coord_x .. ", " .. mob.coord_y .. ")") + end + local t = AcquireTable() + + t.text = string.format("%s%s %s", PADDING, hide_type and "" or SetTextColor(CATEGORY_COLORS["mobdrop"], L["Mob Drop"])..":", SetTextColor(private.reputation_colors["hostile"], mob.name)) + t.recipe_id = recipe_id + t.npc_id = id_num + + entry_index = ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) + + if coord_text == "" and hide_location then + return entry_index + end + t = AcquireTable() + t.text = string.format("%s%s%s %s", PADDING, PADDING, hide_location and "" or SetTextColor(CATEGORY_COLORS["location"], mob.location), coord_text) + t.recipe_id = recipe_id + t.npc_id = id_num + + return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) + end + + local function ExpandQuestData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) + local quest = private.quest_list[id_num] + + if not CanDisplayFaction(quest.faction) then + return entry_index + end + + local name = ColorNameByFaction(private.quest_names[id_num], quest.faction) + local coord_text = "" + + if quest.coord_x ~= 0 and quest.coord_y ~= 0 then + coord_text = SetTextColor(CATEGORY_COLORS["coords"], "(" .. quest.coord_x .. ", " .. quest.coord_y .. ")") + end + local t = AcquireTable() + + t.text = string.format("%s%s %s", PADDING, hide_type and "" or SetTextColor(CATEGORY_COLORS["quest"], L["Quest"])..":", name) + t.recipe_id = recipe_id + + entry_index = ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) + + if coord_text == "" and hide_location then + return entry_index + end + t = AcquireTable() + t.text = string.format("%s%s%s %s", PADDING, PADDING, hide_location and "" or SetTextColor(CATEGORY_COLORS["location"], quest.location), coord_text) + t.recipe_id = recipe_id + + return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) + end + + local function ExpandSeasonalData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) + local t = AcquireTable() + + t.text = string.format("%s%s %s", PADDING, hide_type and "" or SetTextColor(CATEGORY_COLORS["seasonal"], private.acquire_names[A.SEASONAL])..":", + SetTextColor(CATEGORY_COLORS["seasonal"], private.seasonal_list[id_num].name)) + t.recipe_id = recipe_id + + return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) + end + + local function ExpandReputationData(entry_index, entry_type, parent_entry, vendor_id, rep_id, rep_level, recipe_id, hide_location, hide_type) + local rep_vendor = private.vendor_list[vendor_id] + + if not CanDisplayFaction(rep_vendor.faction) then + return entry_index + end + + if not faction_strings then + local rep_color = private.reputation_colors + + faction_strings = { + [0] = SetTextColor(rep_color["neutral"], FACTION_NEUTRAL .. " : "), + [1] = SetTextColor(rep_color["friendly"], BFAC["Friendly"] .. " : "), + [2] = SetTextColor(rep_color["honored"], BFAC["Honored"] .. " : "), + [3] = SetTextColor(rep_color["revered"], BFAC["Revered"] .. " : "), + [4] = SetTextColor(rep_color["exalted"], BFAC["Exalted"] .. " : ") + } + end + + local name = ColorNameByFaction(rep_vendor.name, rep_vendor.faction) + local t = AcquireTable() + + t.text = string.format("%s%s %s", PADDING, hide_type and "" or SetTextColor(CATEGORY_COLORS["reputation"], _G.REPUTATION)..":", + SetTextColor(CATEGORY_COLORS["repname"], private.reputation_list[rep_id].name)) + t.recipe_id = recipe_id + t.npc_id = vendor_id + + entry_index = ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) + + t = AcquireTable() + t.text = PADDING .. PADDING .. faction_strings[rep_level] .. name + t.recipe_id = recipe_id + t.npc_id = vendor_id + + entry_index = ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) + + local coord_text = "" + + if rep_vendor.coord_x ~= 0 and rep_vendor.coord_y ~= 0 then + coord_text = SetTextColor(CATEGORY_COLORS["coords"], "(" .. rep_vendor.coord_x .. ", " .. rep_vendor.coord_y .. ")") + end + + if coord_text == "" and hide_location then + return entry_index + end + t = AcquireTable() + t.text = string.format("%s%s%s%s %s", PADDING, PADDING, PADDING, hide_location and "" or SetTextColor(CATEGORY_COLORS["location"], rep_vendor.location), coord_text) + t.recipe_id = recipe_id + t.npc_id = vendor_id + + return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) + end + + local function ExpandWorldDropData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) + local _, _, _, hex_color = GetItemQualityColor(private.recipe_list[recipe_id].quality) + local drop_location = type(id_num) == "string" and BZ[id_num] or nil + + if drop_location then + drop_location = string.format(": %s", SetTextColor(CATEGORY_COLORS["location"], drop_location)) + else + drop_location = "" + end + local t = AcquireTable() + + t.text = string.format("%s%s%s|r%s", PADDING, hex_color, L["World Drop"], drop_location) + t.recipe_id = recipe_id + + return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) + end + + local function ExpandCustomData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) + local t = AcquireTable() + + t.text = PADDING .. SetTextColor(CATEGORY_COLORS["custom"], private.custom_list[id_num].name) + t.recipe_id = recipe_id + + return ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) + end + + local function ExpandAcquireData(entry_index, entry_type, parent_entry, acquire_type, acquire_data, recipe_id, hide_location, hide_type) + local obtain_filters = addon.db.profile.filters.obtain + + for id_num, info in pairs(acquire_data) do + if acquire_type == A.TRAINER and obtain_filters.trainer then + entry_index = ExpandTrainerData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) + elseif acquire_type == A.VENDOR and (obtain_filters.vendor or obtain_filters.pvp) then + entry_index = ExpandVendorData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) + elseif acquire_type == A.MOB_DROP and (obtain_filters.mobdrop or obtain_filters.instance or obtain_filters.raid) then + entry_index = ExpandMobData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) + elseif acquire_type == A.QUEST and obtain_filters.quest then + entry_index = ExpandQuestData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) + elseif acquire_type == A.SEASONAL and obtain_filters.seasonal then + entry_index = ExpandSeasonalData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) + elseif acquire_type == A.REPUTATION then + for rep_level, level_info in pairs(info) do + for vendor_id in pairs(level_info) do + entry_index = ExpandReputationData(entry_index, entry_type, parent_entry, vendor_id, id_num, rep_level, recipe_id, hide_location, hide_type) + end + end + elseif acquire_type == A.WORLD_DROP and obtain_filters.worlddrop then + if not hide_type then + entry_index = ExpandWorldDropData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) + end + elseif acquire_type == A.CUSTOM then + if not hide_type then + entry_index = ExpandCustomData(entry_index, entry_type, parent_entry, id_num, recipe_id, hide_location, hide_type) + end + --@alpha@ + elseif acquire_type > A_MAX then + local t = AcquireTable() + + t.text = "Unhandled Acquire Case - Type: " .. acquire_type + t.recipe_id = recipe_id + + entry_index = ListFrame:InsertEntry(t, parent_entry, entry_index, entry_type, true) + --@end-alpha@ + end + end -- for + return entry_index + end + + -- This function is called when an un-expanded entry in the list has been clicked. + function ListFrame:ExpandEntry(entry_index, expand_mode) + local orig_index = entry_index + local current_entry = self.entries[orig_index] + local expand_all = expand_mode == "deep" + local search_box = MainPanel.search_editbox + local current_tab = MainPanel.tabs[MainPanel.current_tab] + local prof_name = private.ordered_professions[MainPanel.profession] + + -- Entry_index is the position in self.entries that we want to expand. Since we are expanding the current entry, the return + -- value should be the index of the next button after the expansion occurs + entry_index = entry_index + 1 + + current_tab:ModifyEntry(current_entry, true) + + -- This entry was generated using sorting based on Acquisition. + if current_entry.acquire_id then + local acquire_id = current_entry.acquire_id + + if current_entry.type == "header" then + local recipe_list = private.acquire_list[acquire_id].recipes + local sorted_recipes = addon.sorted_recipes + + private.SortRecipeList(recipe_list) + + for index = 1, #sorted_recipes do + local spell_id = sorted_recipes[index] + local recipe_entry = private.recipe_list[spell_id] + + if recipe_entry:HasState("VISIBLE") and search_box:MatchesRecipe(recipe_entry) then + local t = AcquireTable() + local expand = false + local type = "subheader" + + if acquire_id == A.WORLD_DROP or acquire_id == A.CUSTOM then + expand = true + type = "entry" + end + local is_expanded = current_tab[prof_name.." expanded"][spell_id] and current_tab[prof_name.." expanded"][private.acquire_names[acquire_id]] + + t.text = recipe_entry:GetDisplayName() + t.recipe_id = spell_id + t.acquire_id = acquire_id + + entry_index = self:InsertEntry(t, current_entry, entry_index, type, expand or is_expanded, expand_all or is_expanded) + end + end + elseif current_entry.type == "subheader" then + for acquire_type, acquire_data in pairs(private.recipe_list[current_entry.recipe_id].acquire_data) do + if acquire_type == acquire_id then + entry_index = ExpandAcquireData(entry_index, "subentry", current_entry, acquire_type, acquire_data, current_entry.recipe_id, false, true) + end + end + end + return entry_index + end + + -- This entry was generated using sorting based on Location. + if current_entry.location_id then + local location_id = current_entry.location_id + + if current_entry.type == "header" then + local recipe_list = private.location_list[location_id].recipes + local sorted_recipes = addon.sorted_recipes + + private.SortRecipeList(recipe_list) + + for index = 1, #sorted_recipes do + local spell_id = sorted_recipes[index] + local recipe_entry = private.recipe_list[spell_id] + + if recipe_entry:HasState("VISIBLE") and search_box:MatchesRecipe(recipe_entry) then + local expand = false + local type = "subheader" + local t = AcquireTable() + + -- Add World Drop entries as normal entries. + if recipe_list[spell_id] == "world_drop" then + expand = true + type = "entry" + end + local is_expanded = current_tab[prof_name.." expanded"][spell_id] and current_tab[prof_name.." expanded"][location_id] + + t.text = recipe_entry:GetDisplayName() + t.recipe_id = spell_id + t.location_id = location_id + + entry_index = self:InsertEntry(t, current_entry, entry_index, type, expand or is_expanded, expand_all or is_expanded) + end + end + elseif current_entry.type == "subheader" then + local recipe_entry = private.recipe_list[current_entry.recipe_id] + + -- World Drops are not handled here because they are of type "entry". + for acquire_type, acquire_data in pairs(recipe_entry.acquire_data) do + for id_num, info in pairs(acquire_data) do + -- Only expand an acquisition entry if it is from this location. + if acquire_type == A.TRAINER and private.trainer_list[id_num].location == location_id then + entry_index = ExpandTrainerData(entry_index, "subentry", current_entry, + id_num, current_entry.recipe_id, true) + elseif acquire_type == A.VENDOR and private.vendor_list[id_num].location == location_id then + entry_index = ExpandVendorData(entry_index, "subentry", current_entry, + id_num, current_entry.recipe_id, true) + elseif acquire_type == A.MOB_DROP and private.mob_list[id_num].location == location_id then + entry_index = ExpandMobData(entry_index, "subentry", current_entry, + id_num, current_entry.recipe_id, true) + elseif acquire_type == A.QUEST and private.quest_list[id_num].location == location_id then + entry_index = ExpandQuestData(entry_index, "subentry", current_entry, + id_num, current_entry.recipe_id, true) + elseif acquire_type == A.SEASONAL and private.seasonal_list[id_num].location == location_id then + -- Hide the acquire type for this - it will already show up in the location list as "World Events". + entry_index = ExpandSeasonalData(entry_index, "subentry", current_entry, + id_num, current_entry.recipe_id, true, true) + elseif acquire_type == A.CUSTOM and private.custom_list[id_num].location == location_id then + entry_index = ExpandCustomData(entry_index, "subentry", current_entry, + id_num, current_entry.recipe_id, true, true) + elseif acquire_type == A.REPUTATION then + for rep_level, level_info in pairs(info) do + for vendor_id in pairs(level_info) do + if private.vendor_list[vendor_id].location == location_id then + entry_index = ExpandReputationData(entry_index, "subentry", current_entry, + vendor_id, id_num, rep_level, current_entry.recipe_id, true) + end + end + end + end + end + end + end + return entry_index + end + + -- Normal entry - expand all acquire types. + local recipe_id = self.entries[orig_index].recipe_id + + for acquire_type, acquire_data in pairs(private.recipe_list[recipe_id].acquire_data) do + entry_index = ExpandAcquireData(entry_index, "entry", current_entry, acquire_type, acquire_data, recipe_id) + end + return entry_index + end +end -- InitializeListFrame() + +------------------------------------------------------------------------------- +-- Tooltip functions and data. +------------------------------------------------------------------------------- +spell_tip = CreateFrame("GameTooltip", "AckisRecipeList_SpellTooltip", UIParent, "GameTooltipTemplate") + +-- Font Objects needed for acquire_tip +local narrowFont +local normalFont + +do + -- Fallback in case the user doesn't have LSM-3.0 installed + if not LibStub:GetLibrary("LibSharedMedia-3.0", true) then + + local locale = GetLocale() + -- Fix for font issues on koKR + if locale == "koKR" then + narrowFont = "Fonts\\2002.TTF" + normalFont = "Fonts\\2002.TTF" + else + narrowFont = "Fonts\\ARIALN.TTF" + normalFont = "Fonts\\FRIZQT__.TTF" + end + else + -- Register LSM 3.0 + local LSM3 = LibStub("LibSharedMedia-3.0") + + narrowFont = LSM3:Fetch(LSM3.MediaType.FONT, "Arial Narrow") + normalFont = LSM3:Fetch(LSM3.MediaType.FONT, "Friz Quadrata TT") + end + local narrowFontObj = CreateFont(MODNAME.."narrowFontObj") + local normalFontObj = CreateFont(MODNAME.."normalFontObj") + + -- I want to do a bit more comprehensive tooltip processing. Things like changing font sizes, + -- adding padding to the left hand side, and using better color handling. So... this function + -- will do that for me. + local function ttAdd( + leftPad, -- number of times to pad two spaces on left side + textSize, -- add to or subtract from addon.db.profile.tooltip.acquire_fontsize to get fontsize + narrow, -- if 1, use ARIALN instead of FRITZQ + str1, -- left-hand string + hexcolor1, -- hex color code for left-hand side + str2, -- if present, this is the right-hand string + hexcolor2) -- if present, hex color code for right-hand side + + -- are we changing fontsize or narrow? + local fontSize + + if narrow or textSize ~= 0 then + local font = narrow and narrowFont or normalFont + local fontObj = narrow and narrowFontObj or normalFontObj + + fontSize = addon.db.profile.tooltip.acquire_fontsize + textSize + + fontObj:SetFont(font, fontSize) + acquire_tip:SetFont(fontObj) + end + + -- Add in our left hand padding + local loopPad = leftPad + local leftStr = str1 + + while loopPad > 0 do + leftStr = " " .. leftStr + loopPad = loopPad - 1 + end + -- Set maximum width to match fontSize to maintain uniform tooltip size. -Torhal + local width = math.ceil(fontSize * 37.5) + local line = acquire_tip:AddLine() + + if str2 then + width = width / 2 + + acquire_tip:SetCell(line, 1, "|cff"..hexcolor1..leftStr.."|r", "LEFT", nil, nil, 0, 0, width, width) + acquire_tip:SetCell(line, 2, "|cff"..hexcolor2..str2.."|r", "RIGHT", nil, nil, 0, 0, width, width) + else + acquire_tip:SetCell(line, 1, "|cff"..hexcolor1..leftStr.."|r", nil, "LEFT", 2, nil, 0, 0, width, width) + end + end + + local function SetSpellTooltip(owner, loc, link) + spell_tip:SetOwner(owner, "ANCHOR_NONE") + spell_tip:ClearAllPoints() + + if loc == "Top" then + spell_tip:SetPoint("BOTTOMLEFT", owner, "TOPLEFT") + elseif loc == "Bottom" then + spell_tip:SetPoint("TOPLEFT", owner, "BOTTOMLEFT") + elseif loc == "Left" then + spell_tip:SetPoint("TOPRIGHT", owner, "TOPLEFT") + elseif loc == "Right" then + spell_tip:SetPoint("TOPLEFT", owner, "TOPRIGHT") + end + + -- Add TipTac Support + if _G.TipTac and _G.TipTac.AddModifiedTip and not spell_tip.tiptac then + _G.TipTac:AddModifiedTip(spell_tip) + spell_tip.tiptac = true + end + + -- Set the spell tooltip's scale, and copy its other values from GameTooltip so AddOns which modify it will work. + spell_tip:SetBackdrop(GameTooltip:GetBackdrop()) + spell_tip:SetBackdropColor(GameTooltip:GetBackdropColor()) + spell_tip:SetBackdropBorderColor(GameTooltip:GetBackdropBorderColor()) + spell_tip:SetScale(addon.db.profile.tooltip.scale) + spell_tip:SetClampedToScreen(true) + spell_tip:SetHyperlink(link) + spell_tip:Show() + end + + local function GetTipFactionInfo(comp_faction) + local display_tip + local color + + if comp_faction == FACTION_NEUTRAL then + color = private.reputation_colors["neutral"] + display_tip = true + elseif comp_faction == BFAC[Player.faction] then + color = private.reputation_colors["exalted"] + display_tip = true + else + color = private.reputation_colors["hated"] + display_tip = addon.db.profile.filters.general.faction + end + return display_tip, color + end + + ------------------------------------------------------------------------------- + -- Functions for adding individual acquire type data to the tooltip. + ------------------------------------------------------------------------------- + local function Tooltip_AddTrainer(id_num, location, addline_func) + local trainer = private.trainer_list[id_num] + + if location and trainer.location ~= location then + return + end + local display_tip, name_color = GetTipFactionInfo(trainer.faction) + + if display_tip then + local coord_text = "" + + if trainer.coord_x ~= 0 and trainer.coord_y ~= 0 then + coord_text = "(" .. trainer.coord_x .. ", " .. trainer.coord_y .. ")" + end + addline_func(0, -2, false, L["Trainer"], CATEGORY_COLORS["trainer"], trainer.name, name_color) + addline_func(1, -2, true, trainer.location, CATEGORY_COLORS["location"], coord_text, CATEGORY_COLORS["coords"]) + end + end + + local function Tooltip_AddVendor(recipe_id, id_num, location, addline_func) + local vendor = private.vendor_list[id_num] + + if location and vendor.location ~= location then + return + end + local type_color = CATEGORY_COLORS["vendor"] + local display_tip, name_color = GetTipFactionInfo(vendor.faction) + + if display_tip then + local coord_text = "" + + if vendor.coord_x ~= 0 and vendor.coord_y ~= 0 then + coord_text = "(" .. vendor.coord_x .. ", " .. vendor.coord_y .. ")" + end + addline_func(0, -1, false, L["Vendor"], type_color, vendor.name, name_color) + addline_func(1, -2, true, vendor.location, CATEGORY_COLORS["location"], coord_text, CATEGORY_COLORS["coords"]) + + local quantity = vendor.item_list[recipe_id] + + if type(quantity) == "number" then + addline_func(2, -2, true, L["LIMITED_SUPPLY"], type_color, string.format("(%d)", quantity), BASIC_COLORS["white"]) + end + end + end + + local function Tooltip_AddMobDrop(id_num, location, addline_func) + local mob = private.mob_list[id_num] + + if location and mob.location ~= location then + return + end + local coord_text = "" + + if mob.coord_x ~= 0 and mob.coord_y ~= 0 then + coord_text = "(" .. mob.coord_x .. ", " .. mob.coord_y .. ")" + end + addline_func(0, -1, false, L["Mob Drop"], CATEGORY_COLORS["mobdrop"], mob.name, private.reputation_colors["hostile"]) + addline_func(1, -2, true, mob.location, CATEGORY_COLORS["location"], coord_text, CATEGORY_COLORS["coords"]) + end + + local function Tooltip_AddQuest(id_num, location, addline_func) + local quest = private.quest_list[id_num] + + if location and quest.location ~= location then + return + end + local type_color = CATEGORY_COLORS["quest"] + local display_tip, name_color = GetTipFactionInfo(quest.faction) + + if display_tip then + local coord_text = "" + + if quest.coord_x ~= 0 and quest.coord_y ~= 0 then + coord_text = "(" .. quest.coord_x .. ", " .. quest.coord_y .. ")" + end + addline_func(0, -1, false, L["Quest"], type_color, private.quest_names[id_num], name_color) + addline_func(1, -2, true, quest.location, CATEGORY_COLORS["location"], coord_text, CATEGORY_COLORS["coords"]) + end + end + + local function Tooltip_AddRepVendor(id_num, location, rep_id, rep_level, vendor_id, addline_func) + local rep_vendor = private.vendor_list[vendor_id] + + if location and rep_vendor.location ~= location then + return + end + local display_tip, name_color = GetTipFactionInfo(rep_vendor.faction) + + if display_tip then + local rep_color = private.reputation_colors + local rep_str = "" + local type_color + + if rep_level == 0 then + rep_str = FACTION_NEUTRAL + type_color = rep_color["neutral"] + elseif rep_level == 1 then + rep_str = BFAC["Friendly"] + type_color = rep_color["friendly"] + elseif rep_level == 2 then + rep_str = BFAC["Honored"] + type_color = rep_color["honored"] + elseif rep_level == 3 then + rep_str = BFAC["Revered"] + type_color = rep_color["revered"] + else + rep_str = BFAC["Exalted"] + type_color = rep_color["exalted"] + end + addline_func(0, -1, false, _G.REPUTATION, CATEGORY_COLORS["reputation"], private.reputation_list[id_num].name, CATEGORY_COLORS["repname"]) + addline_func(1, -2, false, rep_str, type_color, rep_vendor.name, name_color) + + local coord_text = "" + + if rep_vendor.coord_x ~= 0 and rep_vendor.coord_y ~= 0 then + coord_text = "(" .. rep_vendor.coord_x .. ", " .. rep_vendor.coord_y .. ")" + end + addline_func(2, -2, true, rep_vendor.location, CATEGORY_COLORS["location"], coord_text, CATEGORY_COLORS["coords"]) + end + end + + local function Tooltip_AddWorldDrop(recipe_id, id_num, location, addline_func) + local drop_location = type(id_num) == "string" and BZ[id_num] or nil + + if location and drop_location ~= location then + return + end + local item_id = private.spell_to_recipe_map[recipe_id] + local _, item_level + + if item_id then + _, _, _, item_level = GetItemInfo(item_id) + end + local _, _, _, quality_color = GetItemQualityColor(private.recipe_list[recipe_id].quality) + local type_color = string.gsub(quality_color, "|cff", "") + + if type(id_num) == "string" then + local location_text = item_level and string.format("%s (%d - %d)", drop_location, item_level - 5, item_level + 5) or drop_location + + addline_func(0, -1, false, L["World Drop"], type_color, location_text, CATEGORY_COLORS["location"]) + else + local location_text = item_level and string.format("%s (%d - %d)", _G.UNKNOWN, item_level - 5, item_level + 5) or _G.UNKNOWN + + addline_func(0, -1, false, L["World Drop"], type_color, location_text, CATEGORY_COLORS["location"]) + end + end + + ------------------------------------------------------------------------------- + -- Public API function for displaying a recipe's acquire data. + -- * The addline_func paramater must be a function which accepts the same + -- * arguments as ARL's ttAdd function. + ------------------------------------------------------------------------------- + function addon:DisplayAcquireData(recipe_id, acquire_id, location, addline_func) + local recipe = private.recipe_list[recipe_id] + + if not recipe then + return + end + + for acquire_type, acquire_data in pairs(recipe.acquire_data) do + local can_display = (not acquire_id or acquire_type == acquire_id) + + if can_display then + for id_num, info in pairs(acquire_data) do + if acquire_type == A.TRAINER then + Tooltip_AddTrainer(id_num, location, addline_func) + elseif acquire_type == A.VENDOR then + Tooltip_AddVendor(recipe_id, id_num, location, addline_func) + elseif acquire_type == A.MOB_DROP then + Tooltip_AddMobDrop(id_num, location, addline_func) + elseif acquire_type == A.QUEST then + Tooltip_AddQuest(id_num, location, addline_func) + elseif acquire_type == A.SEASONAL then + color_1 = CATEGORY_COLORS["seasonal"] + addline_func(0, -1, 0, private.acquire_names[A.SEASONAL], color_1, private.seasonal_list[id_num].name, color_1) + elseif acquire_type == A.REPUTATION then + for rep_level, level_info in pairs(info) do + for vendor_id in pairs(level_info) do + Tooltip_AddRepVendor(id_num, location, rep_id, rep_level, vendor_id, addline_func) + end + end + elseif acquire_type == A.WORLD_DROP then + Tooltip_AddWorldDrop(recipe_id, id_num, location, addline_func) + elseif acquire_type == A.CUSTOM then + addline_func(0, -1, false, private.custom_list[id_num].name, CATEGORY_COLORS["custom"]) + --@alpha@ + elseif can_display then + -- Unhandled + addline_func(0, -1, 0, L["Unhandled Recipe"], BASIC_COLORS["normal"]) + --@end-alpha@ + end + end -- for id_num + end -- if can_display + end -- for acquire_type + end + + ------------------------------------------------------------------------------- + -- Main tooltip-generating function. + ------------------------------------------------------------------------------- + local BINDING_FLAGS = { + [COMMON_FLAGS_1.IBOE] = L["BOEFilter"], + [COMMON_FLAGS_1.IBOP] = L["BOPFilter"], + [COMMON_FLAGS_1.IBOA] = L["BOAFilter"], + [COMMON_FLAGS_1.RBOE] = L["RecipeBOEFilter"], + [COMMON_FLAGS_1.RBOP] = L["RecipeBOPFilter"], + [COMMON_FLAGS_1.RBOA] = L["RecipeBOAFilter"] + } + + function ListItem_ShowTooltip(owner, list_entry) + if not list_entry then + return + end + local recipe_id = list_entry.recipe_id + local recipe = private.recipe_list[recipe_id] + + if not recipe then + return + end + local spell_tip_anchor = addon.db.profile.spelltooltiplocation + local acquire_tip_anchor = addon.db.profile.acquiretooltiplocation + local spell_link = GetSpellLink(recipe.spell_id) + local MainPanel = addon.Frame + + if acquire_tip_anchor == _G.OFF then + QTip:Release(acquire_tip) + + -- If we have the spell link tooltip, anchor it to MainPanel instead so it shows + if spell_tip_anchor ~= _G.OFF and spell_link then + SetSpellTooltip(MainPanel, spell_tip_anchor, spell_link) + else + spell_tip:Hide() + end + return + end + acquire_tip = QTip:Acquire(MODNAME.." Tooltip", 2, "LEFT", "LEFT") + acquire_tip:ClearAllPoints() + + if acquire_tip_anchor == "Right" then + acquire_tip:SetPoint("TOPLEFT", MainPanel, "TOPRIGHT", MainPanel.is_expanded and -90 or -35, 0) + elseif acquire_tip_anchor == "Left" then + acquire_tip:SetPoint("TOPRIGHT", MainPanel, "TOPLEFT") + elseif acquire_tip_anchor == "Top" then + acquire_tip:SetPoint("BOTTOMLEFT", MainPanel, "TOPLEFT") + elseif acquire_tip_anchor == "Bottom" then + acquire_tip:SetPoint("TOPLEFT", MainPanel, "BOTTOMLEFT", 0, 55) + elseif acquire_tip_anchor == "Mouse" then + local x, y = GetCursorPosition() + local uiscale = UIParent:GetEffectiveScale() + + acquire_tip:SetPoint("BOTTOMLEFT", UIParent, "BOTTOMLEFT", x / uiscale, y / uiscale) + end + acquire_tip:SetClampedToScreen(true) + + if _G.TipTac and _G.TipTac.AddModifiedTip then + -- Pass true as second parameter because hooking OnHide causes C stack overflows -Torhal + _G.TipTac:AddModifiedTip(acquire_tip, true) + end + local _, _, _, quality_color = GetItemQualityColor(recipe.quality) + + acquire_tip:Clear() + acquire_tip:SetScale(addon.db.profile.tooltip.scale) + acquire_tip:AddHeader() + acquire_tip:SetCell(1, 1, quality_color..recipe.name, "CENTER", 2) + + -- check if the recipe is excluded + if addon.db.profile.exclusionlist[recipe_id] then + ttAdd(0, -1, true, L["RECIPE_EXCLUDED"], "ff0000") + end + + -- Add in skill level requirement, colored correctly + local color_1 = BASIC_COLORS["normal"] + local color_2 + + local skill_level = Player["ProfessionLevel"] + local recipe_level = recipe.skill_level + local optimal_level = recipe.optimal_level + local medium_level = recipe.medium_level + local easy_level = recipe.easy_level + local trivial_level = recipe.trivial_level + local difficulty = private.difficulty_colors + + if recipe_level > skill_level then + color_2 = difficulty["impossible"] + elseif skill_level >= trivial_level then + color_2 = difficulty["trivial"] + elseif skill_level >= easy_level then + color_2 = difficulty["easy"] + elseif skill_level >= medium_level then + color_2 = difficulty["medium"] + elseif skill_level >= optimal_level then + color_2 = difficulty["optimal"] + else + color_2 = difficulty["trivial"] + end + ttAdd(0, -1, false, string.format("%s:", _G.SKILL_LEVEL), color_1, recipe.skill_level, color_2) + + -- Binding info + acquire_tip:AddSeparator() + color_1 = BASIC_COLORS["normal"] + + for flag, label in pairs(BINDING_FLAGS) do + if bit.band(recipe.flags.common1, flag) == flag then + ttAdd(0, -1, true, label, color_1) + end + end + acquire_tip:AddSeparator() + + if recipe.specialty then + local spec = recipe.specialty + local spec_name = GetSpellInfo(spec) + local known = (spec == Player["Specialty"]) + + ttAdd(0, -1, false, string.format(_G.ITEM_REQ_SKILL, spec_name), known and BASIC_COLORS["white"] or difficulty["impossible"]) + acquire_tip:AddSeparator() + end + + ttAdd(0, -1, false, L["Obtained From"] .. " : ", BASIC_COLORS["normal"]) + + local acquire_id = list_entry.acquire_id + local location = list_entry.location_id + + addon:DisplayAcquireData(recipe_id, acquire_id, location, ttAdd) + + if not addon.db.profile.hide_tooltip_hint then + -- Give the tooltip hint a unique color. + color_1 = "c9c781" + + acquire_tip:AddSeparator() + acquire_tip:AddSeparator() + + ttAdd(0, -1, 0, L["ALT_CLICK"], color_1) + ttAdd(0, -1, 0, L["CTRL_CLICK"], color_1) + ttAdd(0, -1, 0, L["SHIFT_CLICK"], color_1) + + if acquire_id ~= A.WORLD_DROP and acquire_id ~= A.CUSTOM and (_G.TomTom or _G.Cartographer_Waypoints) and (addon.db.profile.worldmap or addon.db.profile.minimap) then + ttAdd(0, -1, 0, L["CTRL_SHIFT_CLICK"], color_1) + end + end + acquire_tip:Show() + + -- If we have the spell link tooltip, link it to the acquire tooltip. + if spell_tip_anchor ~= _G.OFF and spell_link then + SetSpellTooltip(acquire_tip, spell_tip_anchor, spell_link) + else + spell_tip:Hide() + end + end +end -- do diff --git a/interface.xml b/interface.xml index 84fe4d4..3dd469a 100644 --- a/interface.xml +++ b/interface.xml @@ -4,5 +4,6 @@ + -- 1.7.9.5