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.

384 lines
16 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) ]]
-- 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 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==rematch.teamsPanel.List.CaptureButton then -- if over capturebutton, then move glow to last 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
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()
else
-- 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()
end
rematch.teamsPanel.List:BlingData(cursorID)
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