You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

486 lines
18 KiB

local _,L = ...
local rematch = Rematch
local loadoutPanel = RematchLoadoutPanel
local panel = loadoutPanel.TargetPanel
local settings
-- workingList is a simple list of headers and indexes into rematch.targetData to reflect
-- the currently displayed targets. because this gets wiped and repopulated it should not be
-- nested tables. instead, the values will be one of four things:
-- 1. "A~All" (string) the "All Targets" expand/collapse item at the top of the unfiltered list
-- 2. "X~expansionID" (string) an expansion header where expansionID is from targetData
-- 3. "M~expansionID~mapID" (string) an expansion+map header where expansionID and mapID are from targetData
-- 4. something (number) an index into rematch.targetData
local workingList = {}
local HEADER_ALL = "A~All"
local HEADER_EXP_FORMAT = "X~%s"
local HEADER_MAP_FORMAT = "M~%s~%s"
local HELP_TAG = "help"
local searchPattern = nil -- desensitized text entered in search box
local headersMade = {} -- lookup table to see if a header was made yet when building workingList
function panel:Initialize()
settings = RematchSettings
settings.ExpandedTargetHeaders = settings.ExpandedTargetHeaders or {}
-- if 'Remember Expanded Lists' not checked, then start each session with all lists collapsed
if not settings.RememberExpandedLists then
wipe(settings.ExpandedTargetHeaders)
end
panel.Top.SearchBox.Instructions:SetText(L["Search Targets"])
local scrollFrame = panel.List
scrollFrame.template = settings.SlimListButtons and "RematchCompactTargetListButtonTemplate" or "RematchTargetListButtonTemplate"
scrollFrame.templateType = "RematchCompositeButton"
scrollFrame.list = workingList
scrollFrame.callback = panel.FillTargetListButton
scrollFrame.dynamicButtonHeight = panel.GetButtonHeight
panel.Top.BackButton.Arrow:Hide()
end
function panel:Update()
if panel:IsVisible() then
panel:PopulateTargetList()
panel.List:Update()
end
end
-- back button has an OnKeyDown to capture ESC keys; anything else is propagated through
-- this OnKeyDown is only active while the target panel is up, so ESC will close the panel if nothing else
function panel:OnBackButtonKeyDown(key)
if key==GetBindingKey("TOGGLEGAMEMENU") then
-- if "Close Lists On ESC" is checked, see if anything is expanded and close it if so rather than closing panel
if settings.CollapseListsOnESC then
-- if pet card is up (and if we got here, then card is floating and unlocked), dismiss without closing target
if rematch.PetCard:IsVisible() then
rematch.PetCard:Hide()
return
end
-- otherwise look for any expanded headers
for k,isExpanded in pairs(settings.ExpandedTargetHeaders) do
if isExpanded then -- checking this way rather than next(setting.etc) because a value could be false
wipe(settings.ExpandedTargetHeaders)
panel:Update()
self:SetPropagateKeyboardInput(false)
return
end
end
end
panel:CloseTargetPanel()
self:SetPropagateKeyboardInput(false)
return
else
self:SetPropagateKeyboardInput(true)
end
end
function panel:Toggle()
loadoutPanel.targetMode = not loadoutPanel.targetMode
rematch:Configure()
end
function panel:CloseTargetPanel()
loadoutPanel.targetMode = false
rematch:Configure()
end
-- updates the non-UI workingList which is a list of indexes into rematch.targetData
function panel:PopulateTargetList()
wipe(workingList)
wipe(headersMade)
panel.somethingExpanded = false -- until proven otherwise, assume all headers collapsed
local searchPattern = (panel.searchPattern and panel.searchPattern:trim():len()>0) and panel.searchPattern:trim()
-- if a search isn't happening, start workingList with "all" to mark an All Targets collapsible header
if not searchPattern then
panel:AddHeader("all")
end
-- add headers and targets to workingList based on currently expanded headers
for index,info in ipairs(rematch.targetData) do
if panel:ShouldIndexShow(index,searchPattern) then
panel:AddHeader("exp",index)
local expTag = panel:GetHeaderTag("exp",index)
if searchPattern or settings.ExpandedTargetHeaders[expTag] then
panel.somethingExpanded = true
panel:AddHeader("map",index)
local mapTag = panel:GetHeaderTag("map",index)
if searchPattern or settings.ExpandedTargetHeaders[mapTag] then
tinsert(workingList,index)
end
end
end
end
-- adds a "Targets with a (green check) have a saved team" entry if extra help not disabled
if not settings.HideMenuHelp and #workingList>0 then
tinsert(workingList,HELP_TAG)
end
end
-- returns a header tag where headerType is "all", "exp" or "map" and targetIndex is an index
-- into rematch.targetData. a header tag is a short string used in workingList to defined a
-- header. X~8 is an expansion (exp) header for expansionID 8, M~8~123 is a map header
-- for expansionID 8 and mapID 123.
function panel:GetHeaderTag(headerType,index)
if headerType=="all" then
return HEADER_ALL
end
local info = index and rematch.targetData[index]
if info and headerType=="exp" then
return format(HEADER_EXP_FORMAT,info[1])
elseif info and headerType=="map" then
return format(HEADER_MAP_FORMAT,info[1],info[2])
end
end
-- adds a header to workingList from a targetData index if it hasn't been added yet
-- headerType is "all", "exp" or "map"; index is an index into rematch.targetData
function panel:AddHeader(headerType,index)
local tag = panel:GetHeaderTag(headerType,index)
if not headersMade[tag] then
headersMade[tag] = true
tinsert(workingList,tag)
end
end
function panel:GetExpansionNameFromHeader(header)
if header==HEADER_ALL then
return L["All Targets"]
end
local expansionID = header:match("[XA]~(.+)")
if expansionID then
local expansionName = _G["EXPANSION_NAME"..expansionID]
if expansionName then
return expansionName
else
return expansionID or UNKNOWN
end
end
return UNKNOWN
end
function panel:GetMapNameFromHeader(header)
local mapID = header:match("M~.-~(.+)")
if mapID then
if tonumber(mapID) then
mapInfo = C_Map.GetMapInfo(tonumber(mapID))
return mapInfo and mapInfo.name or UNKNOWN
else
return mapID or UNKNOWN
end
end
return UNKNOWN
end
-- styles a list button to be a header (with compact mode and without, these are 26px high)
function panel:FillHeader(button,targetIndex)
local isMapHeader = targetIndex:sub(1,2)=="M~"
local isExpHeader = not isMapHeader
local isExpanded = settings.ExpandedTargetHeaders[targetIndex]
if targetIndex==HEADER_ALL then -- "All Targets" has expanded state saved in panel.somethingExpanded, not settings.ExpandedTargetHeaders
isExpanded = panel.somethingExpanded
end
local expandOffset = isExpanded and 0 or 0.5
button.Expand:SetTexCoord(0,1,expandOffset,expandOffset+0.5)
button.Expand:SetShown(not panel.searchPattern)
button.npcID = nil
button.Back:SetTexCoord(0,1,0.5,1)
button.Back:SetPoint("TOPLEFT",0,0)
button.Back:SetPoint("BOTTOMRIGHT",0,0)
button.Name:ClearAllPoints()
button.Name:SetPoint("TOPLEFT",28,0)
button.Name:SetPoint("BOTTOMRIGHT",-2,0)
button.HasTeam:Hide()
if isExpHeader then -- expansion header
button.Back:SetVertexColor(0.25,0.25,0.25)
button.Name:SetTextColor(1,0.82,0)
button.Name:SetText(panel:GetExpansionNameFromHeader(targetIndex))
button.Expand:SetDesaturated(false)
button.Expand:SetVertexColor(1,1,1)
elseif isMapHeader then -- map header
button.Back:SetVertexColor(0.2,0.2,0.2)
button.Name:SetTextColor(0.5,0.75,1)
button.Name:SetText(panel:GetMapNameFromHeader(targetIndex))
button.Expand:SetDesaturated(true)
button.Expand:SetVertexColor(0.5,0.75,1)
end
end
-- styles a list button to display the "Targets with a (green check) have a saved team."
function panel:FillHelp(button,targetIndex)
button.Name:ClearAllPoints()
button.Name:SetPoint("LEFT",8,0)
button.Name:SetPoint("RIGHT",-2,0)
button.Name:SetText(L["Targets with a \124TInterface\\AddOns\\Rematch\\Textures\\hasteam:18\124t have a saved team."])
button.Expand:Hide()
button.Name:Show()
button.Name:SetTextColor(0.65,0.65,0.65)
button.HasTeam:Hide()
end
function panel:FillRemainingNormalTarget(button,targetIndex)
local info = rematch.targetData[targetIndex]
local numPets = info and #info-6 or 0 -- number of pets displayed (on assumption [6] through [8] are pets)
if button.Border and numPets and numPets>=0 and numPets<=3 then
button.Border:Show()
button.Border:SetWidth(numPets*30)
if numPets==3 then
button.Border:SetWidth(90)
button.Border:SetTexCoord(0,0.703125,0.5,0.84375)
elseif numPets==2 then
button.Border:SetWidth(61)
button.Border:SetTexCoord(0.5234375,1.0,0,0.34375)
else
button.Border:SetWidth(32)
button.Border:SetTexCoord(0.75,1.0,0.5,0.84375)
end
end
local nameYOffset = 0
if button.SubName then
local questName = rematch:GetQuestNameFromTarget(targetIndex)
if questName and questName~=rematch:GetNpcNameFromTarget(targetIndex) then
button.SubName:SetText(questName)
button.SubName:Show()
nameYOffset = 16
end
end
button.Back:SetPoint("TOPLEFT",(30*numPets)+(3-numPets)+1,0)
button.Name:ClearAllPoints()
button.Name:SetPoint("TOPLEFT",(30*numPets)+(3-numPets)+4,0)
button.Name:SetPoint("BOTTOMRIGHT",button.hasTeamShown and -22 or -2,nameYOffset)
end
function panel:FillRemainingCompactTarget(button,targetIndex)
local info = rematch.targetData[targetIndex]
local numPets = info and #info-6 or 0 -- number of pets displayed (on assumption [7] through [8] are pets)
button.Back:SetPoint("TOPLEFT",(26*numPets)+2,0)
button.Name:SetPoint("TOPLEFT",(26*numPets)+4,0)
button.Name:SetPoint("BOTTOMRIGHT",button.hasTeamShown and -22 or -2,0)
end
function panel:FillTargetListButton()
local targetIndex = self.index and workingList[self.index]
if targetIndex then
self.Name:SetFontObject((settings.SlimListButtons and settings.SlimListSmallText) and GameFontNormalSmall or GameFontNormal)
self.Name:SetText(targetIndex)
local isHeader = type(targetIndex)=="string"
self.isHeader = isHeader
local info = rematch.targetData[targetIndex]
local numPets = info and #info-6 or 0 -- number of pets displayed (on assumption [7] through [9] are pets)
for i=1,3 do
self.Pets[i]:Hide()
end
if self.Border then
self.Border:Hide()
self.SubName:Hide()
end
-- "Targets with a (green check) have a saved team." list item
self.Back:SetShown(targetIndex~=HELP_TAG)
self:EnableMouse(targetIndex~=HELP_TAG)
if targetIndex==HELP_TAG then
panel:FillHelp(self)
return
end
if isHeader then -- a header, show expand +/- button
panel:FillHeader(self,targetIndex)
else -- a regular target listing, display pets
-- common stuff for both normal and compact target list buttons
self.Back:SetTexCoord(0,1,0,0.5)
self.Back:SetVertexColor(1,1,1)
self.Name:SetTextColor(1,1,1)
self.Name:SetText(rematch:GetNpcNameFromTarget(targetIndex))
self.Expand:Hide()
local npcID = info and info[3]
self.hasTeamShown = npcID and RematchSaved[npcID] and true
self.HasTeam:SetShown(self.hasTeamShown)
self.npcID = npcID
if info then
for i=1,3 do
if info[6+i] then
local petInfo = rematch.petInfo:Fetch(info[6+i])
-- if 3 pets, i=1, petIndex=1; if 1 pet, i=1, petIndex=3
-- (this is so pets are displayed in order left-right but remain right justified)
--local petIndex = (4-numPets)+i-1
self.Pets[i]:SetTexture(petInfo.icon)
self.Pets[i].petID = petInfo.petID
self.Pets[i]:Show()
end
end
end
if settings.SlimListButtons then
panel:FillRemainingCompactTarget(self,targetIndex)
else
panel:FillRemainingNormalTarget(self,targetIndex)
end
end
local focus = GetMouseFocus()
if focus==self and focus:GetScript("OnEnter") then
rematch:HideTextureHighlight()
self.Back:SetBlendMode("BLEND")
self:GetScript("OnEnter")(self)
end
end
end
--[[ listbutton script handlers ]]
-- for the following TargetListButtonOnLoad, to avoid creating new functions for every button
local function showPetCard(self) rematch:ShowPetCard(self,self.petID) end
local function hidePetCard(self) rematch:HidePetCard(true) end
local function lockPetCard(self) rematch:LockPetCard(self,self.petID) end
-- when a composite button is created, hook up script handlers for the pet "buttons"
function panel:TargetListButtonOnLoad()
for i=1,3 do
self:SetTextureScript(self.Pets[i],"OnEnter",showPetCard)
self:SetTextureScript(self.Pets[i],"OnLeave",hidePetCard)
self:SetTextureScript(self.Pets[i],"OnClick",lockPetCard)
end
end
function panel:TargetListButtonOnClick()
local index = self.index -- index into workingList
local workingIndex = workingList[index]
if workingIndex==HEADER_ALL then -- if "All Targets" clicked
if panel.somethingExpanded then
wipe(settings.ExpandedTargetHeaders)
else -- nothing expanded, now expand them all
for targetIndex,info in ipairs(rematch.targetData) do -- expand all headers that exist
settings.ExpandedTargetHeaders[panel:GetHeaderTag("exp",targetIndex)] = true
settings.ExpandedTargetHeaders[panel:GetHeaderTag("map",targetIndex)] = true
end
end
panel:Update()
elseif type(workingIndex)=="string" then -- this is a header
if panel.searchPattern then -- clicking a header while searching should do nothing
return
end
local tag = workingIndex
if tag:sub(1,1)=="X" then -- expansion header
for targetIndex,info in ipairs(rematch.targetData) do -- collapse all map headers for this expansion
if panel:GetHeaderTag("exp",targetIndex):match(tag) then
settings.ExpandedTargetHeaders[panel:GetHeaderTag("map",targetIndex)] = nil
end
end
end
settings.ExpandedTargetHeaders[tag] = not settings.ExpandedTargetHeaders[tag]
panel:Update()
else
panel:CloseTargetPanel()
rematch.PickNpcID(self)
end
if self.isHeader and GetMouseFocus()==self then
rematch:ShowTextureHighlight(self.Expand)
end
end
function panel:TargetListButtonOnEnter()
if self.isHeader then
if not panel.searchPattern then
rematch:ShowTextureHighlight(self.Expand)
end
else
self.Back:SetBlendMode("ADD")
end
end
function panel:TargetListButtonOnLeave()
if self.isHeader then
rematch:HideTextureHighlight()
else
self.Back:SetBlendMode("BLEND")
end
end
function panel:TargetListButtonOnMouseDown()
if self.isHeader then
rematch:HideTextureHighlight()
elseif self:HasFocus() then
-- if mouse is down while over an active texture, don't "press" the main button
self.Back:SetBlendMode("BLEND")
end
end
function panel:TargetListButtonOnMouseUp()
if GetMouseFocus()==self then
if self.isHeader then
if not panel.searchPattern then
rematch:ShowTextureHighlight(self.Expand)
end
else
-- if mouse goes up after it left button, don't "unpress" it
self.Back:SetBlendMode("ADD")
end
end
end
--[[ search ]]
function panel:SearchBoxOnTextChanged()
local oldPattern = panel.searchPattern
local text = self:GetText():trim()
panel.searchPattern = text:len()>0 and rematch:DesensitizeText(text)
if panel.searchPattern~=oldPattern then
panel:Update()
end
end
-- returns true if the targetData at the given index contains the given searchText
function panel:ShouldIndexShow(index,searchPattern)
if not searchPattern then
return true -- no searches happening, display all
elseif rematch:GetExpansionNameFromTarget(index):match(searchPattern) then
return true -- search matched an expansion name
elseif rematch:GetMapNameFromTarget(index):match(searchPattern) then
return true -- search matched a map name
elseif rematch:GetNpcNameFromTarget(index):match(searchPattern) then
return true -- search matched an npc name
elseif (rematch:GetQuestNameFromTarget(index) or ""):match(searchPattern) then
return true -- search matched a quest name
else
local info = rematch.targetData[index]
for i=7,9 do
if info[i] then
local petInfo = rematch.petInfo:Fetch(info[i])
if petInfo.name and petInfo.name:match(searchPattern) then
return true
end
end
end
end
-- if reached here, search failed
return false
end
-- for AutoScrollFrame's dynamicButtonHeight, returns the intended height of the button at the given index
function panel:GetButtonHeight(index)
if settings.SlimListButtons then
return 26
else
local targetIndex = index and workingList[index]
if targetIndex and type(targetIndex)=="string" then
return 26
else
return 44
end
end
end