diff options
Diffstat (limited to 'plugins/dragdropselected.lua')
-rw-r--r-- | plugins/dragdropselected.lua | 240 |
1 files changed, 126 insertions, 114 deletions
diff --git a/plugins/dragdropselected.lua b/plugins/dragdropselected.lua index ec998aa..3c6583b 100644 --- a/plugins/dragdropselected.lua +++ b/plugins/dragdropselected.lua @@ -1,13 +1,13 @@ -- mod-version:3 --[[ - dragdropselected.lua - provides basic drag and drop of selected text (in same document) - version: 20200627_133351 - originally by SwissalpS - - TODO: use OS drag and drop events - TODO: change mouse cursor when duplicating - TODO: add dragging image + dragdropselected.lua + provides basic drag and drop of selected text (in same document) + version: 20200627_133351 + originally by SwissalpS + + TODO: use OS drag and drop events + TODO: change mouse cursor when duplicating + TODO: add dragging image --]] local DocView = require "core.docview" local core = require "core" @@ -22,16 +22,16 @@ local style = require "core.style" -- iSelLine2 is line number where selection ends -- iSelCol2 is column where selection ends local function isInSelection(iLine, iCol, iSelLine1, iSelCol1, iSelLine2, iSelCol2) - if iLine < iSelLine1 then return false end - if iLine > iSelLine2 then return false end - if (iLine == iSelLine1) and (iCol < iSelCol1) then return false end - if (iLine == iSelLine2) and (iCol > iSelCol2) then return false end - return true + if iLine < iSelLine1 then return false end + if iLine > iSelLine2 then return false end + if (iLine == iSelLine1) and (iCol < iSelCol1) then return false end + if (iLine == iSelLine2) and (iCol > iSelCol2) then return false end + return true end -- isInSelection -- distance between two points local function distance(x1, y1, x2, y2) - return math.sqrt(math.pow(x2-x1, 2)+math.pow(y2-y1, 2)) + return math.sqrt(math.pow(x2-x1, 2)+math.pow(y2-y1, 2)) end local min_drag = style.code_font:get_width(" ") @@ -40,126 +40,138 @@ local min_drag = style.code_font:get_width(" ") local on_mouse_moved = DocView.on_mouse_moved function DocView:on_mouse_moved(x, y, ...) - local sCursor = nil - - -- make sure we only act if previously on_mouse_pressed was in selection - if self.bClickedIntoSelection and - ( -- we are already dragging or we moved enough to start dragging - not self.drag_start_loc or - distance(self.drag_start_loc[1],self.drag_start_loc[2], x, y) > min_drag - ) then - self.drag_start_loc = nil - - -- show that we are dragging something - sCursor = 'hand' - - -- calculate line and column for current mouse position - local iLine, iCol = self:resolve_screen_position(x, y) - local iSelLine1 = self.dragged_selection[1] - local iSelCol1 = self.dragged_selection[2] - local iSelLine2 = self.dragged_selection[3] - local iSelCol2 = self.dragged_selection[4] - self.doc:set_selection(iSelLine1, iSelCol1, iSelLine2, iSelCol2) - if not isInSelection(iLine, iCol, iSelLine1, iSelCol1, iSelLine2, iSelCol2) then - -- show cursor only if outside selection - self.doc:add_selection(iLine, iCol) - end - -- update scroll position - self:scroll_to_line(iLine, true) - end -- if previously clicked into selection + local sCursor = nil + + -- make sure we only act if previously on_mouse_pressed was in selection + if + self.bClickedIntoSelection + and + ( -- we are already dragging or we moved enough to start dragging + not self.drag_start_loc or + distance(self.drag_start_loc[1],self.drag_start_loc[2], x, y) > min_drag + ) + then + self.drag_start_loc = nil - -- hand off to 'old' on_mouse_moved() - on_mouse_moved(self, x, y, ...) - -- override cursor as needed - if sCursor then self.cursor = sCursor end + -- show that we are dragging something + sCursor = 'hand' + + -- calculate line and column for current mouse position + local iLine, iCol = self:resolve_screen_position(x, y) + local iSelLine1 = self.dragged_selection[1] + local iSelCol1 = self.dragged_selection[2] + local iSelLine2 = self.dragged_selection[3] + local iSelCol2 = self.dragged_selection[4] + self.doc:set_selection(iSelLine1, iSelCol1, iSelLine2, iSelCol2) + if not isInSelection(iLine, iCol, iSelLine1, iSelCol1, iSelLine2, iSelCol2) then + -- show cursor only if outside selection + self.doc:add_selection(iLine, iCol) + end + -- update scroll position + self:scroll_to_line(iLine, true) + end -- if previously clicked into selection + + -- hand off to 'old' on_mouse_moved() + on_mouse_moved(self, x, y, ...) + -- override cursor as needed + if sCursor then self.cursor = sCursor end end -- DocView:on_mouse_moved -- override DocView:on_mouse_pressed local on_mouse_pressed = DocView.on_mouse_pressed function DocView:on_mouse_pressed(button, x, y, clicks) - local caught = DocView.super.on_mouse_pressed(self, button, x, y, clicks) - if caught then - return caught - end - -- no need to proceed if not left button or has no selection - if ('left' ~= button) - or (not self.doc:has_selection()) - or (1 < clicks) then - return on_mouse_pressed(self, button, x, y, clicks) - end - -- convert pixel coordinates to line and column coordinates - local iLine, iCol = self:resolve_screen_position(x, y) - -- get selection coordinates - local iSelLine1, iSelCol1, iSelLine2, iSelCol2 = self.doc:get_selection(true) - -- set flag for on_mouse_released and on_mouse_moved() methods to detect dragging - self.bClickedIntoSelection = isInSelection(iLine, iCol, iSelLine1, iSelCol1, - iSelLine2, iSelCol2) - if self.bClickedIntoSelection then - self.drag_start_loc = { x, y } - -- stash selection for inserting later - self.sDraggedText = self.doc:get_text(self.doc:get_selection()) - self.dragged_selection = { iSelLine1, iSelCol1, iSelLine2, iSelCol2 } - else - self.bClickedIntoSelection = nil - self.dragged_selection = nil - -- let 'old' on_mouse_pressed() do whatever it needs to do - on_mouse_pressed(self, button, x, y, clicks) - end + local caught = DocView.super.on_mouse_pressed(self, button, x, y, clicks) + if caught then + return caught + end + -- no need to proceed if not left button or has no selection + if + ('left' ~= button) + or (not self.doc:has_selection()) + or (1 < clicks) + then + return on_mouse_pressed(self, button, x, y, clicks) + end + -- convert pixel coordinates to line and column coordinates + local iLine, iCol = self:resolve_screen_position(x, y) + -- get selection coordinates + local iSelLine1, iSelCol1, iSelLine2, iSelCol2 = self.doc:get_selection(true) + -- set flag for on_mouse_released and on_mouse_moved() methods to detect dragging + self.bClickedIntoSelection = isInSelection(iLine, iCol, iSelLine1, iSelCol1, + iSelLine2, iSelCol2) + if self.bClickedIntoSelection then + self.drag_start_loc = { x, y } + -- stash selection for inserting later + self.sDraggedText = self.doc:get_text(self.doc:get_selection()) + self.dragged_selection = { iSelLine1, iSelCol1, iSelLine2, iSelCol2 } + else + self.bClickedIntoSelection = nil + self.dragged_selection = nil + -- let 'old' on_mouse_pressed() do whatever it needs to do + on_mouse_pressed(self, button, x, y, clicks) + end end -- DocView:on_mouse_pressed -- override DocView:on_mouse_released() local on_mouse_released = DocView.on_mouse_released function DocView:on_mouse_released(button, x, y) - local iLine, iCol = self:resolve_screen_position(x, y) - if self.bClickedIntoSelection then - local iSelLine1, iSelCol1, iSelLine2, iSelCol2 = table.unpack(self.dragged_selection) - if not self.drag_start_loc - and not isInSelection(iLine, iCol, iSelLine1, iSelCol1, iSelLine2, iSelCol2) then - -- insert stashed selected text at current position - if iLine < iSelLine1 or (iLine == iSelLine1 and iCol < iSelCol1) then - -- delete first - self.doc:set_selection(iSelLine1, iSelCol1, iSelLine2, iSelCol2) - if not keymap.modkeys['ctrl'] then - self.doc:delete_to(0) - end - self.doc:set_selection(iLine, iCol) - self.doc:text_input(self.sDraggedText) - else - -- insert first - self.doc:set_selection(iLine, iCol) - self.doc:text_input(self.sDraggedText) - self.doc:set_selection(iSelLine1, iSelCol1, iSelLine2, iSelCol2) - if not keymap.modkeys['ctrl'] then - self.doc:delete_to(0) - end - self.doc:set_selection(iLine, iCol) - end - elseif self.drag_start_loc then - -- deselect only if the drag never happened - self.doc:set_selection(iLine, iCol) + local iLine, iCol = self:resolve_screen_position(x, y) + if self.bClickedIntoSelection then + local iSelLine1, iSelCol1, iSelLine2, iSelCol2 = table.unpack(self.dragged_selection) + if + not self.drag_start_loc + and + not isInSelection(iLine, iCol, iSelLine1, iSelCol1, iSelLine2, iSelCol2) + then + -- insert stashed selected text at current position + if iLine < iSelLine1 or (iLine == iSelLine1 and iCol < iSelCol1) then + -- delete first + self.doc:set_selection(iSelLine1, iSelCol1, iSelLine2, iSelCol2) + if not keymap.modkeys['ctrl'] then + self.doc:delete_to(0) end - -- unset stash and flag(s) TODO: - self.sDraggedText = '' - self.bClickedIntoSelection = nil + self.doc:set_selection(iLine, iCol) + self.doc:text_input(self.sDraggedText) + else + -- insert first + self.doc:set_selection(iLine, iCol) + self.doc:text_input(self.sDraggedText) + self.doc:set_selection(iSelLine1, iSelCol1, iSelLine2, iSelCol2) + if not keymap.modkeys['ctrl'] then + self.doc:delete_to(0) + end + self.doc:set_selection(iLine, iCol) + end + elseif self.drag_start_loc then + -- deselect only if the drag never happened + self.doc:set_selection(iLine, iCol) end + -- unset stash and flag(s) TODO: + self.sDraggedText = '' + self.bClickedIntoSelection = nil + end - -- hand over to old handler - on_mouse_released(self, button, x, y) + -- hand over to old handler + on_mouse_released(self, button, x, y) end -- DocView:on_mouse_released -- override DocView:draw_caret() local draw_caret = DocView.draw_caret function DocView:draw_caret(x, y) - if self.bClickedIntoSelection then - local iLine, iCol = self:resolve_screen_position(x, y) - -- don't show carets inside selections - if isInSelection(iLine, iCol, - self.dragged_selection[1], self.dragged_selection[2], - self.dragged_selection[3], self.dragged_selection[4]) then - return - end + if self.bClickedIntoSelection then + local iLine, iCol = self:resolve_screen_position(x, y) + -- don't show carets inside selections + if + isInSelection( + iLine, iCol, + self.dragged_selection[1], self.dragged_selection[2], + self.dragged_selection[3], self.dragged_selection[4] + ) + then + return end - draw_caret(self, x, y) + end + draw_caret(self, x, y) end -- DocView:draw_caret() |