diff --git a/frontend/ui/widget/inputdialog.lua b/frontend/ui/widget/inputdialog.lua index f5195bb81..ddf9ce687 100644 --- a/frontend/ui/widget/inputdialog.lua +++ b/frontend/ui/widget/inputdialog.lua @@ -128,6 +128,8 @@ local InputDialog = InputContainer:new{ -- note that the text widget can be scrolled with Swipe North/South even when no button keyboard_hidden = false, -- start with keyboard hidden in full fullscreen mode -- needs add_nav_bar to have a Show keyboard button to get it back + scroll_by_pan = false, -- allow scrolling by lines with Pan (= Swipe, but wait a bit at end + -- of gesture before releasing) (may conflict with movable) -- If save_callback provided, a Save and a Close buttons will be added to the first row -- if reset_callback provided, a Reset button will be added (before Save) to the first row @@ -359,6 +361,7 @@ function InputDialog:init() edit_callback = self._buttons_edit_callback, -- nil if no Save/Close buttons scroll_callback = self._buttons_scroll_callback, -- nil if no Nav or Scroll buttons scroll = true, + scroll_by_pan = self.scroll_by_pan, cursor_at_end = self.cursor_at_end, readonly = self.readonly, parent = self, diff --git a/frontend/ui/widget/inputtext.lua b/frontend/ui/widget/inputtext.lua index 31750d1d8..9f91a6f8c 100644 --- a/frontend/ui/widget/inputtext.lua +++ b/frontend/ui/widget/inputtext.lua @@ -30,6 +30,7 @@ local InputText = InputContainer:new{ parent = nil, -- parent dialog that will be set dirty edit_callback = nil, -- called with true when text modified, false on init or text re-set scroll_callback = nil, -- called with (low, high) when view is scrolled (cf ScrollTextWidget) + scroll_by_pan = false, -- allow scrolling by lines with Pan (needs scroll=true) width = nil, height = nil, -- when nil, will be set to original text height (possibly @@ -322,6 +323,7 @@ function InputText:initTextBox(text, char_added) height = self.height, dialog = self.parent, scroll_callback = self.scroll_callback, + scroll_by_pan = self.scroll_by_pan, } else self.text_widget = TextBoxWidget:new{ diff --git a/frontend/ui/widget/scrolltextwidget.lua b/frontend/ui/widget/scrolltextwidget.lua index 683796899..ffca59ec4 100644 --- a/frontend/ui/widget/scrolltextwidget.lua +++ b/frontend/ui/widget/scrolltextwidget.lua @@ -9,6 +9,7 @@ local GestureRange = require("ui/gesturerange") local HorizontalGroup = require("ui/widget/horizontalgroup") local HorizontalSpan = require("ui/widget/horizontalspan") local InputContainer = require("ui/widget/container/inputcontainer") +local Math = require("optmath") local TextBoxWidget = require("ui/widget/textboxwidget") local VerticalScrollBar = require("ui/widget/verticalscrollbar") local UIManager = require("ui/uimanager") @@ -22,6 +23,8 @@ local ScrollTextWidget = InputContainer:new{ top_line_num = nil, editable = false, justified = false, + scroll_callback = nil, -- called with (low, high) when view is scrolled + scroll_by_pan = false, -- allow scrolling by lines with Pan face = nil, fgcolor = Blitbuffer.COLOR_BLACK, width = Screen:scaleBySize(400), @@ -79,6 +82,20 @@ function ScrollTextWidget:init() }, }, } + if self.scroll_by_pan then + self.ges_events.PanText = { + GestureRange:new{ + ges = "pan", + range = function() return self.dimen end, + }, + } + self.ges_events.PanReleaseText = { + GestureRange:new{ + ges = "pan_release", + range = function() return self.dimen end, + }, + } + end end if Device:hasKeyboard() or Device:hasKeys() then self.key_events = { @@ -235,4 +252,26 @@ function ScrollTextWidget:onScrollUp() return true end +function ScrollTextWidget:onPanText(arg, ges) + self._pan_direction = ges.direction + self._pan_relative_x = ges.relative.x + self._pan_relative_y = ges.relative.y + return true +end + +function ScrollTextWidget:onPanReleaseText(arg, ges) + if self._pan_direction and self._pan_relative_y then -- went thru onPanText + if self._pan_direction == "north" or self._pan_direction == "south" then + local nb_lines = Math.round(self._pan_relative_y / self:getLineHeight()) + self.text_widget:scrollLines(-nb_lines) + self:updateScrollBar(true) + end + self._pan_direction = nil + self._pan_relative_x = nil + self._pan_relative_y = nil + return true + end + return false +end + return ScrollTextWidget diff --git a/frontend/ui/widget/textboxwidget.lua b/frontend/ui/widget/textboxwidget.lua index 82be75258..c442572bb 100644 --- a/frontend/ui/widget/textboxwidget.lua +++ b/frontend/ui/widget/textboxwidget.lua @@ -684,6 +684,32 @@ function TextBoxWidget:scrollUp() end end +function TextBoxWidget:scrollLines(nb_lines) + -- nb_lines can be negative + if nb_lines == 0 then + return + end + self.image_show_alt_text = nil + local new_line_num = self.virtual_line_num + nb_lines + if new_line_num < 1 then + new_line_num = 1 + end + if new_line_num > #self.vertical_string_list - self.lines_per_page + 1 then + new_line_num = #self.vertical_string_list - self.lines_per_page + 1 + end + self.virtual_line_num = new_line_num + self:free() + self:_renderText(self.virtual_line_num, self.virtual_line_num + self.lines_per_page - 1) + if self.editable then + local x, y = self:_getXYForCharPos() -- luacheck: no unused + if y < 0 or y >= self.text_height then + -- move cursor to first line of visible area + local ln = self.height == nil and 1 or self.virtual_line_num + self:moveCursorToCharPos(self.vertical_string_list[ln] and self.vertical_string_list[ln].offset or 1) + end + end +end + function TextBoxWidget:scrollToTop() self.image_show_alt_text = nil if self.virtual_line_num > 1 then diff --git a/plugins/texteditor.koplugin/main.lua b/plugins/texteditor.koplugin/main.lua index 41a15f4bf..960a48fa8 100644 --- a/plugins/texteditor.koplugin/main.lua +++ b/plugins/texteditor.koplugin/main.lua @@ -378,6 +378,7 @@ function TextEditor:editFile(file_path, readonly) cursor_at_end = false, readonly = readonly, add_nav_bar = true, + scroll_by_pan = true, buttons = is_lua and {{ -- First button on first row, that will be filled with Reset|Save|Close {