myspace / CommonLua /X /XDragAndDrop.lua
sirnii's picture
Upload 1816 files
b6a38d7 verified
raw
history blame
6.8 kB
DefineClass.XDragAndDropControl = {
__parents = { "XContextControl" },
properties = {
{ category = "Interaction", id = "ClickToDrag", editor = "bool", default = false, help = "By default dragging starts when the window is clicked and dragged. With this option dragging will begin on click instead." },
{ category = "Interaction", id = "ClickToDrop", editor = "bool", default = false, help = "By default dragging stops when the button is let go. With this option dragging will stop on a second click instead." },
{ category = "Interaction", id = "NavigateScrollArea", editor = "bool", default = true, help = "Use scroll area, scroll with scrollbars and mouse wheel while draging" },
},
MouseCursor = "CommonAssets/UI/HandCursor.tga",
drag_win = false,
drag_target = false,
drag_button = false,
pt_pressed = false,
drag_origin = false,
dist_tostart_drag = 7, -- Unscaled pixels
ChildrenHandleMouse = false,
}
if FirstLoad then
DragSource = false
DragScrollbar = false
end
-- Drag callbacks
function XDragAndDropControl:OnDragStart(pt, button)
end
function XDragAndDropControl:OnDragNewTarget(target, drag_win, drop_res, pt)
end
function XDragAndDropControl:OnDragDrop(target, drag_win, drop_res, pt)
end
function XDragAndDropControl:OnDragEnded(drag_win, last_target, drag_res)
end
-- Drop callbacks
function XDragAndDropControl:IsDropTarget(drag_win, pt, drag_source_win)
end
function XDragAndDropControl:OnDrop(drag_win, pt, drag_source_win)
end
function XDragAndDropControl:OnDropEnter(drag_win, pt, drag_source_win)
end
function XDragAndDropControl:OnDropLeave(drag_win)
end
-- Drag functions
function XDragAndDropControl:StartDrag(drag_win, pt)
self.drag_win = drag_win
DragSource = self
drag_win:AddDynamicPosModifier{
id = "Drag",
target = Platform.console and "gamepad" or "mouse",
}
local winRelativePt = point(drag_win.box:minx() - pt:x(), drag_win.box:miny() - pt:y())
drag_win:AddInterpolation{
id = "Move",
type = const.intRect,
duration = 0,
originalRect = drag_win.box,
-- target rect is relative to the mouse position in this case.
targetRect = box(winRelativePt:x(), winRelativePt:y(), drag_win.box:sizex() + winRelativePt:x(), drag_win.box:sizey() + winRelativePt:y()),
}
drag_win:SetDock("ignore")
drag_win:SetParent(self.desktop)
drag_win.DrawOnTop = true
self:UpdateDrag(drag_win, pt)
self.desktop:SetMouseCapture(self)
end
function XDragAndDropControl:InternalDragStart(pt)
if self.drag_win then
self:StopDrag()
end
local drag_win = self:OnDragStart(pt, self.drag_button)
if not drag_win then
return
end
self:StartDrag(drag_win, pt)
self.pt_pressed = false
return "break"
end
function XDragAndDropControl:InternalDragStop(pt)
local drag_win = self.drag_win
self:UpdateDrag(drag_win, pt)
local target = self.drag_target
local drop_res = target and target:OnDrop(drag_win, pt, self)
self:OnDragDrop(target, drag_win, drop_res, pt)
self:StopDrag(drop_res)
end
function XDragAndDropControl:StopDrag(drag_res)
local drag_win = self.drag_win
if drag_win then
local last_target = self.drag_target
self:UpdateDropTarget(nil, drag_win)
self:OnDragEnded(drag_win, last_target, drag_res)
drag_win:RemoveModifier("Drag")
drag_win:RemoveModifier("Move")
end
DragSource = false
self.drag_win = nil
self.drag_target = nil
self.desktop:SetMouseCapture()
end
function XDragAndDropControl:UpdateDrag(drag_win, pt)
local target = self:GetDropTarget(drag_win, pt)
self:UpdateDropTarget(target, drag_win, pt)
end
function XDragAndDropControl:UpdateDropTarget(target, drag_win, pt)
if (target or false) ~= self.drag_target then
if self.drag_target then
self.drag_target:OnDropLeave(drag_win, pt)
end
local drop_res
if target then
drop_res = target:OnDropEnter(drag_win, pt, self)
end
self.drag_target = target or nil
-- !!! update mouse cursor
self:OnDragNewTarget(target, drag_win, drop_res, pt)
end
end
function XDragAndDropControl:OnTargetDragWnd(drag_win, pt)
return self
end
function XDragAndDropControl:GetDropTarget(drag_win, pt)
local target = self.desktop.modal_window:GetMouseTarget(pt)
if target == drag_win then
target = self:OnTargetDragWnd(drag_win, pt)
end
while target and not target:IsDropTarget(drag_win, pt, self) do
target = target.parent
end
return target
end
-- XWindow functions
function XDragAndDropControl:OnMouseButtonDown(pt, button)
if not self.enabled then
return "break"
end
if self.drag_win then
if self.NavigateScrollArea then
-- simulate scrollbar mouse capture (it is captured by drag_win) by saving it in DragScrollbar and calling its mouse functions
local target = self.desktop.modal_window:GetMouseTarget(pt)
if target and IsKindOf(target,"XScrollControl") then
DragScrollbar = target
target:StartScroll(pt)
target:OnMousePos(pt)
end
end
if self.ClickToDrop and button == self.drag_button then
self:InternalDragStop(pt)
end
return "break"
end
self.pt_pressed = pt
self.drag_button = button
if self.ClickToDrag then
return self:InternalDragStart(pt)
end
end
function XDragAndDropControl:OnMouseButtonUp(pt, button)
if not self.enabled then return "break" end
if self.pt_pressed and self.drag_button == button then
self.pt_pressed = false
self.drag_button = false
return "break"
end
local drag_win = self.drag_win
if drag_win and DragScrollbar then
DragScrollbar:OnMousePos(pt)
DragScrollbar = false
end
if not drag_win and self.drag_button ~= button then
return "break"
end
if not self.ClickToDrop then
self:InternalDragStop(pt)
return "break"
end
end
function XDragAndDropControl:OnMousePos(pt)
if not self.enabled then return "break" end
local scaledDistance = ScaleXY(self.scale, self.dist_tostart_drag)
if self.pt_pressed and pt:Dist2D(self.pt_pressed)>=scaledDistance then
self:InternalDragStart(self.pt_pressed)
return "break"
end
local drag_win = self.drag_win
if drag_win then
self:UpdateDrag(drag_win, pt)
if DragScrollbar then
DragScrollbar:OnMousePos(pt)
end
return "break"
end
end
function XDragAndDropControl:OnMouseWheelForward(pt)
if self.NavigateScrollArea and self.drag_win then
local target = self.desktop.modal_window:GetMouseTarget(pt)
local wnd = GetParentOfKind(target,"XScrollArea")
if wnd then
wnd:OnMouseWheelForward()
return "break"
end
end
end
function XDragAndDropControl:OnMouseWheelBack(pt)
if self.NavigateScrollArea and self.drag_win then
local target = self.desktop.modal_window:GetMouseTarget(pt)
local wnd = GetParentOfKind(target,"XScrollArea")
if wnd then
wnd:OnMouseWheelBack()
return "break"
end
end
end
function XDragAndDropControl:OnCaptureLost()
if self.drag_win then
self:StopDrag("capture_lost")
end
self:Invalidate()
end