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.

473 lines
21 KiB

local _,rematch = ...
local L = rematch.localization
local C = rematch.constants
local settings = rematch.settings
rematch.dragFrame = RematchDragFrame
--[[ for dragging teams, groups (and maybe targets) ]]
rematch.events:Register(rematch.dragFrame,"PLAYER_LOGIN",function(self)
-- confirmation to combine groups (move from one to another and delete old)
-- note: there's no option to auto-confirm since this involves multiple teams, probably will be a rare event,
-- and it would not give an option to not delete the old group
rematch.dialog:Register("CombineGroups",{
title = L["Combine Groups"],
accept = YES,
cancel = NO,
prompt = L["Combine team groups?"],
layout = {"Text","CheckButton","Help"},
refreshFunc = function(self,info,subject,firstRun)
-- neither group:favorites or group:none can be deleted, they can just be emptied
local cantDelete = subject.fromID=="group:favorites" or subject.fromID=="group:none"
local instructions = cantDelete and L["This will move all teams from %s to %s, leaving the %s group empty."] or L["This will move all teams from %s to %s and then delete the emptied %s group afterwards."]
local fromName = rematch.utils:GetFormattedGroupName(subject.fromID)
local toName = rematch.utils:GetFormattedGroupName(subject.toID)
self.Text:SetText(format(instructions,fromName,toName,fromName))
self.CheckButton:SetText(L["Don't Delete Empty Group"])
self.Help:SetText(L["You can also selectively move many teams with the Team Herder tool from the Teams button"])
self.CheckButton:SetChecked(settings.DontDeleteOnCombine or cantDelete)
self.CheckButton:SetEnabled(not cantDelete)
end,
changeFunc = function(self,info,subject)
settings.DontDeleteOnCombine = self.CheckButton:GetChecked()
end,
acceptFunc = function(self,info,subject)
if subject.fromID~=subject.toID and rematch.savedGroups[subject.fromID] and rematch.savedGroups[subject.toID] then
-- go through all teams and move any from fromID to toID
for teamID,team in rematch.savedTeams:AllTeams() do
if team.groupID==subject.fromID then
if subject.toID=="group:favorites" then -- moving team to favorites, save homeID
team.homeID = team.groupID
team.favorite = true
elseif team.groupID=="group:favorites" then -- moving team out of favorites, nil homeID
team.homeID = nil
team.favorite = nil
end
team.groupID = subject.toID
if settings.EchoTeamDrag then
rematch.utils:Write(rematch.utils:GetFormattedTeamName(teamID),"moved to",rematch.utils:GetFormattedGroupName(subject.toID))
end
end
end
-- here all of teams should be out of subject.fromID group, delete group if checkbutton unchecked (and a deletable group)
if not settings.DontDeleteOnCombine and subject.fromID~="group:favorites" and subject.fromID~="group:none" then
rematch.savedGroups:Delete(subject.fromID)
end
-- doing an immediate TeamsChanged
rematch.savedTeams:TeamsChanged(true) -- true will update UI immediately
rematch.teamsPanel.List:BlingData(subject.toID) -- bling the group teams were moved to
end
end
})
end)
-- returns the type of thing on the cursor (C.CURSOR_TYPE_GROUP or C.CURSOR_TYPE_TEAM) and the groupID/teamID
-- if an actual item, spell or pet is on the cursor, this should return nil
function rematch.dragFrame:GetCursorInfo()
return self.cursorType,self.cursorID
end
-- returns a C.DRAG_DIRECTION_PREV or C.DRAG_DIRECTION_NEXT
function rematch.dragFrame:GetCursorDirection()
if self.GlowFrame.GlowLine:IsVisible() then
return self.GlowFrame.GlowLine.direction
end
end
function rematch.dragFrame:OnShow()
SetCursor("ITEM_CURSOR")
--self:GetScript("OnUpdate")(self,0)
end
function rematch.dragFrame:OnHide()
self.cursorType = nil
self.cursorID = nil
SetCursor(nil)
self.GlowFrame:Hide()
rematch.teamsPanel.List:UnlockHeaders()
rematch.teamsPanel.List:Select("Moving")
rematch.teamsPanel.List.needsRefresh = true
rematch.events:Unregister(self,"GLOBAL_MOUSE_UP")
end
function rematch.dragFrame:OnUpdate(elapsed)
if GetCursorInfo() then -- something real was picked up on cursor
self:Hide()
elseif self:GetCursorInfo() then
if not rematch.teamsPanel:IsVisible() then -- if not on teams panel, drop whatever group/team on cursor
self:ClearCursor()
else
local x,y = GetCursorPosition()
local scale = UIParent:GetEffectiveScale()
self[self.cursorType==C.CURSOR_TYPE_GROUP and "Group" or "Team"]:SetPoint("TOPLEFT",UIParent,"BOTTOMLEFT",x/scale,y/scale)
SetCursor("ITEM_CURSOR")
end
end
end
function rematch.dragFrame:OnClick(button)
self:ClearCursor()
end
-- OnReceiveDrag is unreliable because if a team/group is picked up and the list collapses, then no button receives
-- the drag. To work around this, when a team/group is picked up via dragging, GLOBAL_MOUSE_UP is registered, and
-- then a OnReceiveDrag is simulated based on what's beneath the mouse when the mouse button is released
function rematch.dragFrame:GLOBAL_MOUSE_UP()
local focus = GetMouseFocus()
if focus then
-- if mouse is over teamsPanel(GlowFrame) then any team/group combination safe to handle
if MouseIsOver(self.GlowFrame) and rematch.teamsPanel:IsVisible() and (focus.groupID or focus.teamID or focus==rematch.teamsPanel.List.CaptureButton) then
self:HandleReceiveDrag(focus)
end
-- but if mouse is over teamTabs it can only be a team on the cursor
if MouseIsOver(rematch.teamTabs) and rematch.teamTabs:IsVisible() and focus.groupID and self:GetCursorInfo()==C.CURSOR_TYPE_TEAM then
self:HandleReceiveDrag(focus)
end
end
rematch.events:Unregister(self,"GLOBAL_MOUSE_UP")
end
--[[ pickup/clear ]]
function rematch.dragFrame:ClearCursor()
self:Hide()
rematch.teamsPanel.List:Select("Moving")
end
-- picks up a groupID onto the cursor; fromDrag is true if it was picked up from OnDragStart
function rematch.dragFrame:PickupGroup(groupID,fromDrag)
ClearCursor()
if rematch.savedGroups[groupID] then
rematch.utils:HideWidgets()
rematch.dialog:Hide()
self.cursorType = C.CURSOR_TYPE_GROUP
self.cursorID = groupID
self.Group.Name:SetWidth(0) -- initially allow unbounded width
self.Group.Name:SetText(rematch.utils:GetFormattedGroupName(groupID))
local nameWidth = self.Group.Name:GetStringWidth()
if nameWidth > 120 then
self.Group.Name:SetWidth(120)
nameWidth = 120
end
self.Group:SetWidth(nameWidth+6+4+18+4)
self.Group.Icon:SetTexture(rematch.savedGroups[groupID].icon or C.EMPTY_ICON)
self.Team:Hide()
self.Group:Show()
-- if not in teams tab, go to it
if rematch.layout:GetMode()~=0 and rematch.layout:GetView()~="teams" then
rematch.layout:ChangeView("teams")
end
-- if searching, clear search
if rematch.teamsPanel.List:IsSearching() then
rematch.teamsPanel.Top.SearchBox.Clear:Click()
end
-- collapse any expanded headers and lock them to prevent expanding
rematch.teamsPanel.List:CollapseAllHeaders()
rematch.teamsPanel.List:LockHeaders()
self:Show() -- show dragFrame to begin dragging
self:ShowGlowFrame(rematch.teamsPanel.List)
PlaySound(C.SOUND_DRAG_START)
if fromDrag and not settings.ClickToDrag then
rematch.events:Register(self,"GLOBAL_MOUSE_UP",self.GLOBAL_MOUSE_UP)
end
rematch.teamsPanel.List:Select("Moving",groupID)
end
end
-- picks up a teamID onto the cursor; fromDrag is true if it was picked up from OnDragStart
function rematch.dragFrame:PickupTeam(teamID,fromDrag)
ClearCursor()
if rematch.savedTeams[teamID] then
rematch.utils:HideWidgets()
rematch.dialog:Hide()
self.cursorType = C.CURSOR_TYPE_TEAM
self.cursorID = teamID
for i=1,3 do
local petID = rematch.savedTeams[teamID].pets[i]
local petInfo = rematch.petInfo:Fetch(petID)
self.Team.Pets[i]:SetTexture(petInfo.icon)
self.Team.Pets[i]:SetDesaturated(petInfo.idType=="species")
end
self.Group:Hide()
self.Team:Show()
-- if searching, clear search and all headers
if rematch.teamsPanel.List:IsSearching() then
rematch.teamsPanel.Top.SearchBox.Clear:Click()
rematch.teamsPanel.List:CollapseAllHeaders()
else -- if not searching, collapse all other headers but keep data in view
rematch.teamsPanel.List:CollapseAllButData(teamID)
end
-- lock headers so they can't be expanded/collapsed while dragging
rematch.teamsPanel.List:LockHeaders()
self:Show() -- show dragFrame to begin dragging
self:ShowGlowFrame(rematch.teamsPanel.List)
PlaySound(C.SOUND_DRAG_START)
if fromDrag and not settings.ClickToDrag then
rematch.events:Register(self,"GLOBAL_MOUSE_UP",self.GLOBAL_MOUSE_UP)
end
rematch.teamsPanel.List:Select("Moving",teamID)
end
end
--[[ glow frame ]]
function rematch.dragFrame:ShowGlowFrame(parent)
self.GlowFrame:SetPoint("TOPLEFT",parent,"TOPLEFT")
self.GlowFrame:SetPoint("BOTTOMRIGHT",parent,"BOTTOMRIGHT")
self.GlowFrame.GlowLine:Hide()
if rematch.layout:GetMode()==1 then
self.GlowFrame.GlowLine:SetWidth(C.LIST_BUTTON_WIDE_WIDTH-2)
else
self.GlowFrame.GlowLine:SetWidth(C.LIST_BUTTON_NORMAL_WIDTH-2)
end
self.GlowFrame.GlowLine.Animation:Play()
self.GlowFrame.GlowArea.Animation:Play()
self.GlowFrame:SetScript("OnUpdate",self.GlowFrame.OnUpdate)
self.GlowFrame:Show()
end
function rematch.dragFrame.GlowFrame:OnUpdate(elapsed)
local cursorType,cursorID = rematch.dragFrame:GetCursorInfo()
local focus = GetMouseFocus()
if not focus then
return -- while scrolling, focus becomes nil at times
end
local cursorX,cursorY = GetCursorPosition()
local scale = focus:GetEffectiveScale()
local centerX,centerY = focus:GetCenter()
local showGlowLine = false
local showGlowArea = false
local isMouseOver = MouseIsOver(self) -- is mouse over GlowFrame
self.GlowLine.direction = nil -- potentially one of C.DRAG_DIRECTION_PREV/NEXT/END
-- if group on cursor, and mouse is over a group, put GlowLine above/below group
if cursorType==C.CURSOR_TYPE_GROUP and isMouseOver then
if focus and focus.groupID then
-- if group combine key modifier is down, then showGlowArea and not line
if rematch.dragFrame:IsCombineGroupKeyUsed() then
self.GlowArea:SetPoint("TOPLEFT",focus,"TOPLEFT")
self.GlowArea:SetPoint("BOTTOMRIGHT",focus,"BOTTOMRIGHT")
showGlowArea = true
else -- combine key is not down, so we're reording groups
-- if cursor is in top half of button, anchor to top
if (cursorY/scale)>centerY then
self.GlowLine:SetPoint("CENTER",focus,"TOP")
self.GlowLine.direction = C.DRAG_DIRECTION_PREV
else
self.GlowLine:SetPoint("CENTER",focus,"BOTTOM")
self.GlowLine.direction = C.DRAG_DIRECTION_NEXT
end
showGlowLine = true
end
elseif focus==rematch.teamsPanel.List.CaptureButton then -- if over capturebutton, then move glow to last button
if not rematch.dragFrame:IsCombineGroupKeyUsed() then -- make sure combine key not down over capture button
local lastListButton = rematch.teamsPanel.List:GetLastListButton()
if lastListButton and lastListButton.groupID then
self.GlowLine:SetPoint("CENTER",lastListButton,"BOTTOM")
else -- no last button, put glow at top of frame
self.GlowLine:SetPoint("CENTER",self,"TOP")
end
self.GlowLine.direction = C.DRAG_DIRECTION_END
showGlowLine = true
end
end
elseif cursorType==C.CURSOR_TYPE_TEAM and isMouseOver then
if focus and focus.teamID then
-- if cursor is in top half of button, anchor to top
if (cursorY/scale)>centerY then
self.GlowLine:SetPoint("CENTER",focus,"TOP")
self.GlowLine.direction = C.DRAG_DIRECTION_PREV
else
self.GlowLine:SetPoint("CENTER",focus,"BOTTOM")
self.GlowLine.direction = C.DRAG_DIRECTION_NEXT
end
showGlowLine = true
elseif focus and focus.groupID then
self.GlowArea:SetPoint("TOPLEFT",focus,"TOPLEFT")
self.GlowArea:SetPoint("BOTTOMRIGHT",focus,"BOTTOMRIGHT")
showGlowArea = true
end
end
self.GlowLine:SetShown(showGlowLine)
self.GlowArea:SetShown(showGlowArea)
end
--[[ HandleReceiveDrag ]]
-- handles the various ways things can receive drags (OnReceiveDrag, OnClick, OnMouseUp) and returns true if it was handled
-- button is the button that received the drag, and mouseButton is the LeftButton/RightButton/etc where appropriate
function rematch.dragFrame:HandleReceiveDrag(button,mouseButton)
local cursorType,cursorID = self:GetCursorInfo()
if not cursorType then -- nothing on cursor, nothing to handle
return false
end
if mouseButton=="RightButton" then -- something on cursor, but right-clicked to drop it
self:ClearCursor()
return true
end
local direction = self:GetCursorDirection()
if cursorType==C.CURSOR_TYPE_GROUP then -- a groupID is on the cursor
if button.groupID then -- dropping group onto group
PlaySound(C.SOUND_DRAG_STOP)
rematch.dragFrame:ReceiveGroupToGroup(cursorID,button.groupID,direction)
return true
elseif direction==C.DRAG_DIRECTION_END then -- dropping group onto capture area
PlaySound(C.SOUND_DRAG_STOP)
rematch.dragFrame:ReceiveGroupToCapture(cursorID)
return true
end
elseif cursorType==C.CURSOR_TYPE_TEAM then -- a teamID is on the cursor
if button.groupID then -- dropping team onto group
PlaySound(C.SOUND_DRAG_STOP)
rematch.dragFrame:ReceiveTeamToGroup(cursorID,button.groupID)
return true
elseif button.teamID then -- dropping team onto team
PlaySound(C.SOUND_DRAG_STOP)
rematch.dragFrame:ReceiveTeamToTeam(cursorID,button.teamID,direction)
return true
end
end
return false -- if reached here, nothing was done, nothing handled
end
-- dropping groupID(cursorID) before/after a groupID
function rematch.dragFrame:ReceiveGroupToGroup(cursorID,groupID,direction)
if cursorID==groupID then
-- do nothing, trying to move a group before/after itself
rematch.dragFrame:ClearCursor()
rematch.teamsPanel.List:BlingData(cursorID)
elseif rematch.dragFrame:IsCombineGroupKeyUsed() then -- if combining groups, show dialog
rematch.dialog:ShowDialog("CombineGroups",{fromID=cursorID,toID=groupID})
rematch.dragFrame:ClearCursor()
elseif direction then
-- remove cursorID from settings.GroupOrder
rematch.utils:TableRemoveByValue(settings.GroupOrder,cursorID)
-- and then put it before/after groupID
if groupID then
for i=1,#settings.GroupOrder do
if settings.GroupOrder[i]==groupID then
if direction==C.DRAG_DIRECTION_PREV then
tinsert(settings.GroupOrder,i,cursorID)
elseif direction==C.DRAG_DIRECTION_NEXT then
tinsert(settings.GroupOrder,i+1,cursorID)
end
break
end
end
end
-- if no groupID or direction was C.DRAG_DIRECTION_END, add it back to end
if not groupID or direction==C.DRAG_DIRECTION_END then
tinsert(settings.GroupOrder,cursorID)
end
rematch.dragFrame:ClearCursor()
rematch.teamsPanel:Update()
rematch.teamTabs:Update()
rematch.teamsPanel.List:BlingData(cursorID)
end
end
-- dropping groupID(cursorID) onto the capture area/empty space after list
function rematch.dragFrame:ReceiveGroupToCapture(cursorID)
self:ReceiveGroupToGroup(cursorID,nil,C.DRAG_DIRECTION_END)
end
-- dropping teamID(cursorID) onto groupID
function rematch.dragFrame:ReceiveTeamToGroup(cursorID,groupID,noBling)
local teamName = rematch.utils:GetFormattedTeamName(cursorID)
local team = rematch.savedTeams[cursorID]
local teamMoved = false
if team and team.groupID==groupID then
-- do nothing, dragging team to group it already belongs to
rematch.dragFrame:ClearCursor()
elseif team then
if groupID=="group:favorites" then
team.homeID = team.groupID -- moving team to favorites, saved homeID
team.favorite = true
elseif team.groupID=="group:favorites" then
team.homeID = nil -- moving team out of favorites, nil homeID
team.favorite = nil
end
team.groupID = groupID
rematch.dragFrame:ClearCursor()
-- call TeamsChanged when moving teamID to new group so its group.teams can be handled/sorted
rematch.savedTeams:TeamsChanged(true) -- true will update UI immediately
teamMoved = true
end
if not noBling then
rematch.teamsPanel.List:BlingData(groupID)
end
if settings.EchoTeamDrag and teamMoved then
rematch.utils:Write(teamName,"moved to",rematch.utils:GetFormattedGroupName(groupID))
end
end
-- dropping teamID(cursorID) before/after a teamID
function rematch.dragFrame:ReceiveTeamToTeam(cursorID,teamID,direction)
local team = rematch.savedTeams[cursorID]
local group = rematch.savedGroups[team.groupID]
if cursorID==teamID then
rematch.dragFrame:ClearCursor() -- team being moved before/after itself, do nothing
else
-- if team is sorted (alpha or wins), change to custom sort
if group.sortMode==C.GROUP_SORT_ALPHA or group.sortMode==C.GROUP_SORT_WINS then
group.sortMode = C.GROUP_SORT_CUSTOM
end
-- remove cursorID from settings.GroupOrder
rematch.utils:TableRemoveByValue(group.teams,cursorID)
-- and then put it before/after teamID
if teamID then
for i=1,#group.teams do
if group.teams[i]==teamID then
if direction==C.DRAG_DIRECTION_PREV then
tinsert(group.teams,i,cursorID)
elseif direction==C.DRAG_DIRECTION_NEXT then
tinsert(group.teams,i+1,cursorID)
end
break
end
end
rematch.dragFrame:ClearCursor()
rematch.teamsPanel:Update() -- don't need to do a TeamsChanged really
end
end
rematch.teamsPanel.List:BlingData(cursorID)
end
-- returns true if the modifier key assigned to the group combine key is down; or if key is given then whether that was a modifier key
function rematch.dragFrame:IsCombineGroupKeyUsed(key)
local combineKey = settings.CombineGroupKey
if not key then -- if no key given, then check if a modifier key is down
key = (IsAltKeyDown() and "ALT") or (IsShiftKeyDown() and "SHIFT") or (IsControlKeyDown() and "CTRL")
end
if combineKey=="None" then
return false -- if combineKey is "None", don't bother
elseif combineKey=="Alt" then
return key=="LALT" or key=="RALT" or key=="ALT"
elseif combineKey=="Shift" then
return key=="LSHIFT" or key=="RSHIFT" or key=="SHIFT"
elseif combineKey=="Ctrl" then
return key=="LCTRL" or key=="RCTRL" or key=="CTRL"
end
end