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.
519 lines
16 KiB
519 lines
16 KiB
local _,L = ...
|
|
local rematch = Rematch
|
|
local panel = RematchTeamPanel
|
|
local settings, saved
|
|
|
|
local workingList = {} -- list of teams (keys) being displayed
|
|
local searchText = nil -- desensitized text (or petID) entered in search box
|
|
local searchTabs = {} -- lookup table of tabs that have a search match
|
|
|
|
rematch:InitModule(function()
|
|
rematch.TeamPanel = panel
|
|
settings = RematchSettings
|
|
saved = RematchSaved
|
|
|
|
local scrollFrame = panel.List
|
|
scrollFrame.template = settings.SlimListButtons and "RematchCompactTeamListButtonTemplate" or "RematchTeamListButtonTemplate"
|
|
scrollFrame.templateType = "RematchCompositeButton"
|
|
scrollFrame.list = workingList
|
|
scrollFrame.callback = panel.FillTeamListButton
|
|
scrollFrame.preUpdateFunc = panel.PreUpdate
|
|
|
|
panel.Top.SearchBox.Instructions:SetText(L["Search Teams"])
|
|
|
|
panel.Top.Teams:SetText(L["Teams"])
|
|
rematch:UpdateAutoLoadState()
|
|
end)
|
|
|
|
-- for the following TeamListButtonOnLoad, 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
|
|
|
|
-- when a composite button is created, hook up script handlers for its textures
|
|
function panel:TeamListButtonOnLoad()
|
|
-- Notes button
|
|
self:SetTextureScript(self.Notes,"OnEnter",rematch.Notes.OnEnter)
|
|
self:SetTextureScript(self.Notes,"OnLeave",rematch.Notes.OnLeave)
|
|
self:SetTextureScript(self.Notes,"OnClick",rematch.Notes.OnClick)
|
|
-- preferences button
|
|
self:SetTextureScript(self.Preferences,"OnEnter",rematch.ShowPreferencesTooltip)
|
|
self:SetTextureScript(self.Preferences,"OnLeave",rematch.HideTooltip)
|
|
self:SetTextureScript(self.Preferences,"OnClick",rematch.ShowPreferencesDialog)
|
|
-- winrecord
|
|
self:SetTextureScript(self.WinRecordBack,"OnEnter",rematch.WinRecordOnEnter)
|
|
self:SetTextureScript(self.WinRecordBack,"OnLeave",rematch.WinRecordOnLeave)
|
|
self:SetTextureScript(self.WinRecordBack,"OnClick",rematch.WinRecordOnClick)
|
|
-- pets
|
|
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",panel.PetButtonOnClick)
|
|
end
|
|
end
|
|
|
|
function panel:Update()
|
|
if panel:IsVisible() then
|
|
panel:PopulateTeamList()
|
|
panel.List:Update()
|
|
local searching = panel.Top.SearchBox:GetText():len()>0
|
|
panel.Top.SearchBox.Clear:SetShown(searching)
|
|
panel.Top.SearchBox.Instructions:SetShown(not searching)
|
|
end
|
|
end
|
|
|
|
--[[ Working List ]]
|
|
|
|
-- normal sort: favorite -> name -> targeted -> untargeted
|
|
-- before doing this sort, set panel.sortByWins to try to sort by wins.
|
|
-- wins: favorite -> %wins -> #wins -> name -> targeted -> untargeted
|
|
function rematch.TeamSort(e1,e2)
|
|
if e1 and not e2 then
|
|
return true
|
|
elseif not e1 and e2 then
|
|
return false
|
|
end
|
|
local fav1 = saved[e1].favorite
|
|
local fav2 = saved[e2].favorite
|
|
if fav1 and not fav2 then
|
|
return true
|
|
elseif not fav1 and fav2 then
|
|
return false
|
|
end
|
|
|
|
-- sort by wins if panel.sortByWins set before sort began (remember to turn it off afterwards!)
|
|
if panel.sortByWins then
|
|
local w1,_,_,b1 = rematch:GetTeamWinRecord(e1)
|
|
local w2,_,_,b2 = rematch:GetTeamWinRecord(e2)
|
|
local p1 = b1>0 and w1/b1
|
|
local p2 = b2>0 and w2/b2
|
|
if p1 and not p2 then
|
|
return true
|
|
elseif not p1 and p2 then
|
|
return false
|
|
elseif p1 and p2 then -- sort by win% if both have a win%
|
|
if settings.AlternateWinRecord then
|
|
if w1~=w2 then
|
|
return w1>w2
|
|
end
|
|
end
|
|
if p1~=p2 then
|
|
return p1>p2
|
|
elseif w1~=w2 then
|
|
return w1>w2
|
|
end
|
|
end
|
|
end
|
|
|
|
local title1 = rematch:GetTeamTitle(e1):lower()
|
|
local title2 = rematch:GetTeamTitle(e2):lower()
|
|
if title1==title2 then
|
|
local type1 = type(e1)
|
|
local type2 = type(e2)
|
|
if type1=="number" and type2~="number" then
|
|
return true
|
|
elseif type2=="number" and type1~="number" then
|
|
return false
|
|
else
|
|
return e1<e2
|
|
end
|
|
else
|
|
return title1<title2
|
|
end
|
|
end
|
|
|
|
|
|
function panel:PopulateTeamList()
|
|
local selected = rematch.TeamTabs:GetSelectedTab()
|
|
local numTabs = #settings.TeamGroups
|
|
|
|
local forPet = searchText and rematch:GetIDType(searchText)=="pet"
|
|
|
|
wipe(workingList)
|
|
wipe(searchTabs)
|
|
|
|
for key,data in pairs(saved) do
|
|
local tab = data.tab
|
|
if tab and tab>numTabs then
|
|
saved[key].tab = nil
|
|
tab = nil
|
|
end
|
|
if key==1 then
|
|
-- do nothing for imported teams; don't list them
|
|
elseif not searchText then -- not searching for a team, fill with teams in the selected tab
|
|
if (tab and tab==selected) or (not tab and selected==1) then
|
|
tinsert(workingList,key)
|
|
end
|
|
else -- there's a search happening
|
|
if forPet then -- this is a search for a petID BattlePet-0-000etc
|
|
for i=1,3 do
|
|
if data[i][1]==searchText then
|
|
tinsert(workingList,key)
|
|
searchTabs[data.tab or 1] = true
|
|
break
|
|
end
|
|
end
|
|
else -- this is a traditional [Ss][Ee][Aa][Rr][Cc][Hh]
|
|
if panel:TeamMatchesSearch(key,data) then
|
|
tinsert(workingList,key)
|
|
searchTabs[data.tab or 1] = true
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
local custom = settings.TeamGroups[selected][3] -- whether tab is custom sorted
|
|
|
|
-- sort the teams (yes even if a custom sort)
|
|
-- sort by wins if enabled and we're not looking at search results and it's not a custom sort
|
|
panel.sortByWins = not searchText and not custom and settings.TeamGroups[selected][5]
|
|
table.sort(workingList,rematch.TeamSort)
|
|
panel.sortByWins = nil -- minimap button also uses this TeamSort function and never sorts by wins
|
|
|
|
-- a custom-sorted tab can have teams moved/added (in bulk in the case of deleting a tab
|
|
-- or turning on custom sort), so custom sort requires the leftover teams to be sorted.
|
|
-- So the above sort still has to happen. After the above sort, the teams not present in the
|
|
-- defined custom sort are added in the order they appear above. Then the workingList is wiped
|
|
-- and a new complete custom sort is filled in its place.
|
|
if not searchText and custom then
|
|
-- remove any teams from custom sort that don't belong in this tab
|
|
for i=#custom,1,-1 do
|
|
local key = custom[i]
|
|
local team = saved[key]
|
|
if not team or not ((team.tab and team.tab==selected) or (not team.tab and selected==1)) then
|
|
tremove(custom,i)
|
|
end
|
|
end
|
|
-- add any in workinglist that belong in custom sort but don't already
|
|
for i=1,#workingList do
|
|
if not tContains(custom,workingList[i]) then
|
|
tinsert(custom,workingList[i])
|
|
end
|
|
end
|
|
-- wipe workinglist and fill with custom
|
|
wipe(workingList)
|
|
for i=1,#custom do
|
|
tinsert(workingList,custom[i])
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
-- returns true if the key,data team matches the searchText
|
|
function panel:TeamMatchesSearch(key,data)
|
|
-- look for match in team name
|
|
if rematch:match(rematch:GetTeamTitle(key),searchText) then
|
|
return true
|
|
end
|
|
-- look for match with npc name
|
|
if type(key)=="number" and rematch:match(rematch:GetNameFromNpcID(key),searchText) then
|
|
return true
|
|
end
|
|
-- look for match in notes
|
|
if data.notes and rematch:match(data.notes,searchText) then
|
|
return true
|
|
end
|
|
-- look for match in pet names
|
|
for i=1,3 do
|
|
local petID = data[i][1]
|
|
local idType = rematch:GetIDType(petID)
|
|
if idType=="pet" then
|
|
local _,customName,_,_,_,_,_,name = C_PetJournal.GetPetInfoByPetID(petID)
|
|
if customName and rematch:match(customName,searchText) then
|
|
return true
|
|
elseif name and rematch:match(name,searchText) then
|
|
return true
|
|
end
|
|
elseif idType=="species" then
|
|
local name = C_PetJournal.GetPetInfoBySpeciesID(petID)
|
|
if name and rematch:match(name,searchText) then
|
|
return true
|
|
end
|
|
elseif idType=="leveling" and (L["Leveling"]):match(searchText) then
|
|
return true
|
|
end
|
|
end
|
|
end
|
|
|
|
-- for use by separate tab panel
|
|
function panel:GetTeamSearchInfo()
|
|
return searchText,searchTabs
|
|
end
|
|
|
|
-- export needs access to this doh
|
|
function panel:GetWorkingList()
|
|
return workingList
|
|
end
|
|
|
|
--[[ List UI ]]
|
|
|
|
function panel:PreUpdate()
|
|
panel.SelectedOverlay:Hide()
|
|
end
|
|
|
|
-- this fills out both the normal and compact list buttons
|
|
function panel:FillTeamListButton(key)
|
|
|
|
local teamInfo = rematch.teamInfo:Fetch(key)
|
|
|
|
if not teamInfo.key then
|
|
return -- this isn't a valid team
|
|
end
|
|
|
|
self.key = teamInfo.key
|
|
|
|
-- place border around team if it's currently loaded
|
|
if teamInfo.key == settings.loadedTeam then
|
|
panel.SelectedOverlay:SetParent(self)
|
|
panel.SelectedOverlay:SetPoint("TOPLEFT",self.Back,"TOPLEFT")
|
|
panel.SelectedOverlay:SetPoint("BOTTOMRIGHT",self.Back,"BOTTOMRIGHT")
|
|
panel.SelectedOverlay:Show()
|
|
end
|
|
|
|
-- update pets to the left
|
|
for i=1,3 do
|
|
local petID = teamInfo.petIDs[i]
|
|
local petInfo = rematch.petInfo:Fetch(petID)
|
|
self.Pets[i].petID = petID
|
|
self.Pets[i]:SetTexture(petInfo.icon)
|
|
self.Pets[i]:SetDesaturated(petInfo.idType=="species")
|
|
end
|
|
|
|
-- show favorites star if a favorite team
|
|
self.Favorite:SetShown(teamInfo.isFavorite)
|
|
|
|
-- rightOffset will decide where to anchor Name's RIGHT edge, depending on winrecord
|
|
-- and footnotes; it's adjusted differently for normal and compact modes
|
|
local rightOffset = self.compact and -2 or -8
|
|
|
|
-- winrecord first
|
|
if not settings.HideWinRecord and teamInfo.battles > 0 then
|
|
-- both alternate and normal display need percent calculated to choose background
|
|
local percent = floor(teamInfo.wins*100 / teamInfo.battles + 0.5)
|
|
self.WinRecordText:SetText(settings.AlternateWinRecord and teamInfo.wins or format("%d%%", percent))
|
|
local left,right,top,bottom
|
|
if percent>=60 then
|
|
left,right,top,bottom = 0,0.296875,0,0.28125
|
|
elseif percent<=40 then
|
|
left,right,top,bottom = 0,0.296875,0.375,0.65625
|
|
else
|
|
left,right,top,bottom = 0,0.296875,0.71875,1
|
|
end
|
|
self.WinRecordBack:SetTexCoord(left,right,top,bottom)
|
|
self.WinRecordBack:Show()
|
|
self.WinRecordText:Show()
|
|
rightOffset = self.slim and -41 or -44
|
|
else
|
|
self.WinRecordBack:Hide()
|
|
self.WinRecordText:Hide()
|
|
end
|
|
|
|
-- notes button
|
|
if teamInfo.hasNotes then
|
|
if self.compact then
|
|
self.Notes:SetPoint("RIGHT", rightOffset, 0)
|
|
rightOffset = rightOffset - 21
|
|
else -- normal mode: notes button never changes position
|
|
rightOffset = min(rightOffset, -22)
|
|
end
|
|
self.Notes:Show()
|
|
else
|
|
self.Notes:Hide()
|
|
end
|
|
|
|
-- preferences button
|
|
if teamInfo.hasPreferences then
|
|
if self.compact then
|
|
self.Preferences:SetPoint("RIGHT", rightOffset, 0)
|
|
rightOffset = rightOffset - 20
|
|
else
|
|
self.Preferences:SetPoint("TOPRIGHT",teamInfo.hasNotes and -22 or -2, -3)
|
|
rightOffset = min(rightOffset, teamInfo.hasNotes and -44 or -22)
|
|
end
|
|
self.Preferences:Show()
|
|
else
|
|
self.Preferences:Hide()
|
|
end
|
|
|
|
-- finally, name of the team
|
|
self.Name:SetText(teamInfo.coloredName)
|
|
if self.compact then
|
|
self.Name:SetPoint("RIGHT", rightOffset-2, 0)
|
|
self.Name:SetFontObject(settings.SlimListSmallText and GameFontNormalSmall or GameFontNormal)
|
|
else -- normal list mode potentially has subnames (name of target)
|
|
local nameYOffset = 0
|
|
if teamInfo.needsSubName then
|
|
self.SubName:SetText(teamInfo.targetName)
|
|
self.SubName:Show()
|
|
nameYOffset = 16
|
|
else
|
|
self.SubName:Hide()
|
|
end
|
|
self.Name:SetPoint("BOTTOMRIGHT", rightOffset, nameYOffset)
|
|
end
|
|
|
|
end
|
|
|
|
-- this flashes the button containing the given team
|
|
function panel:BlingKey(key)
|
|
for _,button in ipairs(panel.List.ScrollFrame.Buttons) do
|
|
if key and button.key == key then
|
|
panel.List:BlingIndex(button.index)
|
|
return
|
|
end
|
|
end
|
|
end
|
|
|
|
-- single click of a team now loads teams
|
|
function panel:TeamOnClick(button)
|
|
local key = self.key
|
|
if button=="RightButton" then
|
|
rematch:SetMenuSubject(key)
|
|
rematch:ShowMenu("TeamMenu","cursor")
|
|
else
|
|
rematch:LoadTeam(key)
|
|
if type(key)=="number" then
|
|
rematch.recentTarget = key
|
|
end
|
|
rematch:UpdateUI()
|
|
end
|
|
end
|
|
|
|
function panel:SearchBoxOnTextChanged()
|
|
searchText = nil
|
|
local text = self:GetText()
|
|
self:SetTextColor(1,1,1)
|
|
if text and text:len()>0 then
|
|
if rematch:GetIDType(text)=="pet" then -- this is a search for a petID (BattlePet-0-0000etc)
|
|
searchText = text
|
|
self:SetTextColor(0.5,0.5,0.5)
|
|
else -- this is a normal search
|
|
searchText = rematch:DesensitizeText(text)
|
|
end
|
|
end
|
|
panel:Update()
|
|
rematch.TeamTabs:Update()
|
|
end
|
|
|
|
-- use this to set a search (aside from the user typing in the searchbox) to handle searchbox bits
|
|
function panel:SetTeamSearch(text)
|
|
local searchBox = panel.Top.SearchBox
|
|
searchBox:ClearFocus()
|
|
searchBox.Instructions:SetShown(not text)
|
|
searchBox.Clear:SetShown(text and true)
|
|
searchBox:SetText(text or "")
|
|
end
|
|
|
|
-- regardless whether in journal or standalone, go to a team tab
|
|
-- if key is given, go to the team
|
|
function rematch:ShowTeam(key)
|
|
if settings.Minimized and key then
|
|
return
|
|
end
|
|
-- if key given, switch to the tab that contains the team (if it's not already selected)
|
|
if key and saved[key] then -- and settings.SelectedTab~=(saved[key].tab or 1) then
|
|
rematch.TeamTabs:SelectTeamTab(saved[key].tab or 1)
|
|
end
|
|
-- team panel not visible, show it
|
|
if not panel:IsVisible() then
|
|
if rematch.Frame:IsVisible() then
|
|
settings.Minimized = nil
|
|
settings.ActivePanel = 2
|
|
rematch.Frame:ConfigureFrame()
|
|
elseif rematch.Journal:IsVisible() then
|
|
settings.JournalPanel = 1
|
|
rematch:SelectPanelTab(rematch.Journal.PanelTabs,1)
|
|
rematch.Journal:ConfigureJournal()
|
|
else
|
|
return -- neither frame or journal on screen
|
|
end
|
|
end
|
|
-- if key provided, scroll to team (which should be on the team panel workingList at this point)
|
|
if key and saved[key] then
|
|
local index
|
|
for i=1,#workingList do
|
|
if workingList[i]==key then
|
|
index = i
|
|
end
|
|
end
|
|
if index then
|
|
if not panel.List:IsIndexVisible(index) then
|
|
panel.List:ScrollToIndex(index)
|
|
end
|
|
panel.List:BlingIndex(index)
|
|
elseif not panel.retryShowTeam then
|
|
-- if index not found then we didn't scroll to team yet, try again once things settle
|
|
panel.retryShowTeam = true
|
|
C_Timer.After(0.1,function() rematch:ShowTeam(key) end)
|
|
return
|
|
end
|
|
end
|
|
panel.retryShowTeam = nil
|
|
end
|
|
|
|
-- this registers/unregisters for UPDATE_MOUSEOVER_UNIT depending on settings
|
|
-- if off is true, turn off regardless of its settings (entering combat)
|
|
function rematch:UpdateAutoLoadState(off)
|
|
if not off and settings.AutoLoad and not settings.AutoLoadTargetOnly then
|
|
rematch:RegisterEvent("UPDATE_MOUSEOVER_UNIT")
|
|
else
|
|
rematch:UnregisterEvent("UPDATE_MOUSEOVER_UNIT")
|
|
end
|
|
end
|
|
|
|
-- ordinarily done in PetClicks template; handles special handling of team list pet buttons
|
|
-- to display team menu instead of pet menu
|
|
function panel:PetButtonOnClick(button)
|
|
if button=="RightButton" then
|
|
rematch:SetMenuSubject(self:GetParent().key)
|
|
rematch:ShowMenu("TeamMenu","cursor")
|
|
elseif IsModifiedClick("CHATLINK") then
|
|
if rematch:GetIDType(self.petID)=="pet" then
|
|
ChatEdit_InsertLink(C_PetJournal.GetBattlePetLink(self.petID))
|
|
end
|
|
else
|
|
rematch:LockPetCard(self,self.petID)
|
|
end
|
|
end
|
|
|
|
function panel:Resize(width)
|
|
panel.width = width
|
|
panel:SetWidth(width)
|
|
panel.Top:SetWidth(width)
|
|
panel:Update()
|
|
end
|
|
|
|
function panel:TeamOnEnter()
|
|
self.Backplate:SetColorTexture(0.25,0.5,0.75)
|
|
-- if the name of the team (or its target) is truncated then show a tooltip
|
|
if self.Name:IsTruncated() or (self.SubName and self.SubName:IsVisible() and self.SubName:IsTruncated()) then
|
|
local teamName = rematch:GetTeamTitle(self.key)
|
|
if type(self.key)=="number" then
|
|
local npcName = rematch:GetNameFromNpcID(self.key)
|
|
rematch.ShowTooltip(self,teamName,self.key~=npcName and npcName)
|
|
else
|
|
rematch.ShowTooltip(self,format("%s%s",rematch.hexGold,teamName))
|
|
end
|
|
else
|
|
rematch:HideTooltip() -- this is due to OnEnter()s called during scroll without a hide
|
|
end
|
|
-- highlight the team tab to show where the team is from
|
|
local team = saved[self.key]
|
|
local tab = team and (team.tab or 1)
|
|
rematch:HighlightTeamTab(tab)
|
|
end
|
|
|
|
function panel:TeamOnLeave()
|
|
self.Backplate:SetColorTexture(0.15,0.15,0.15)
|
|
rematch:HideTooltip()
|
|
rematch:HighlightTeamTab() -- unlock all highlights
|
|
end
|
|
|
|
-- returns the number of teams saved
|
|
function rematch:GetNumTeams()
|
|
local numTeams = 0
|
|
for k,v in pairs(saved) do
|
|
numTeams = numTeams + 1
|
|
end
|
|
return numTeams
|
|
end
|
|
|
|
|