support scrolling by half pages in Label

develop
myk002 2022-08-06 23:48:25 -07:00
parent 153fef934b
commit a8d0cc7980
No known key found for this signature in database
GPG Key ID: 8A39CA0FA0C16E78
3 changed files with 69 additions and 12 deletions

@ -3928,11 +3928,14 @@ It has the following attributes:
:auto_width: Sets self.frame.w from the text width. :auto_width: Sets self.frame.w from the text width.
:on_click: A callback called when the label is clicked (optional) :on_click: A callback called when the label is clicked (optional)
:on_rclick: A callback called when the label is right-clicked (optional) :on_rclick: A callback called when the label is right-clicked (optional)
:scroll_keys: Specifies which keys the label should react to as a table. Default is ``STANDARDSCROLL`` (up or down arrows, page up or down). :scroll_keys: Specifies which keys the label should react to as a table. The table should map
keys to the number of lines to scroll as positive or negative integers or one of the keywords
supported by the ``scroll`` method. The default is up/down arrows scrolling by one line and page
up/down scrolling by one page.
:show_scroll_icons: Controls scroll icons' behaviour: ``false`` for no icons, ``'right'`` or ``'left'`` for :show_scroll_icons: Controls scroll icons' behaviour: ``false`` for no icons, ``'right'`` or ``'left'`` for
icons next to the text in an additional column (``frame_inset`` is adjusted to have ``.r`` or ``.l`` greater than ``0``), icons next to the text in an additional column (``frame_inset`` is adjusted to have ``.r`` or ``.l`` greater than ``0``),
``nil`` same as ``'right'`` but changes ``frame_inset`` only if a scroll icon is actually necessary ``nil`` same as ``'right'`` but changes ``frame_inset`` only if a scroll icon is actually necessary
(if ``getTextHeight()`` is greater than ``frame_body.height``). Default is ``nil``. (if ``getTextHeight()`` is greater than ``frame_body.height``). Default is ``nil``.
:up_arrow_icon: The symbol for scroll up arrow. Default is ``string.char(24)`` (``↑``). :up_arrow_icon: The symbol for scroll up arrow. Default is ``string.char(24)`` (``↑``).
:down_arrow_icon: The symbol for scroll down arrow. Default is ``string.char(25)`` (``↓``). :down_arrow_icon: The symbol for scroll down arrow. Default is ``string.char(25)`` (``↓``).
:scroll_icon_pen: Specifies the pen for scroll icons. Default is ``COLOR_LIGHTCYAN``. :scroll_icon_pen: Specifies the pen for scroll icons. Default is ``COLOR_LIGHTCYAN``.
@ -4024,6 +4027,12 @@ The Label widget implements the following methods:
Computes the width of the text. Computes the width of the text.
* ``label:scroll(nlines)``
This method takes the number of lines to scroll as positive or negative
integers or one of the following keywords: ``+page``, ``-page``,
``+halfpage``, or ``-halfpage``.
WrappedLabel class WrappedLabel class
------------------ ------------------

@ -652,6 +652,19 @@ function Label:onRenderFrame(dc, rect)
end end
function Label:scroll(nlines) function Label:scroll(nlines)
if type(nlines) == 'string' then
if nlines == '+page' then
nlines = self.frame_body.height
elseif nlines == '-page' then
nlines = -self.frame_body.height
elseif nlines == '+halfpage' then
nlines = math.ceil(self.frame_body.height/2)
elseif nlines == '-halfpage' then
nlines = -math.ceil(self.frame_body.height/2)
else
error(('unhandled scroll keyword: "%s"'):format(nlines))
end
end
local n = self.start_line_num + nlines local n = self.start_line_num + nlines
n = math.min(n, self:getTextHeight() - self.frame_body.height + 1) n = math.min(n, self:getTextHeight() - self.frame_body.height + 1)
n = math.max(n, 1) n = math.max(n, 1)
@ -668,11 +681,6 @@ function Label:onInput(keys)
end end
for k,v in pairs(self.scroll_keys) do for k,v in pairs(self.scroll_keys) do
if keys[k] then if keys[k] then
if v == '+page' then
v = self.frame_body.height
elseif v == '-page' then
v = -self.frame_body.height
end
self:scroll(v) self:scroll(v)
end end
end end

@ -18,7 +18,7 @@ function test.correct_frame_body_with_scroll_icons()
t[#t+1] = NEWLINE t[#t+1] = NEWLINE
end end
function fs:init(args) function fs:init()
self:addviews{ self:addviews{
widgets.Label{ widgets.Label{
view_id = 'text', view_id = 'text',
@ -39,7 +39,7 @@ function test.correct_frame_body_with_few_text_lines()
t[#t+1] = NEWLINE t[#t+1] = NEWLINE
end end
function fs:init(args) function fs:init()
self:addviews{ self:addviews{
widgets.Label{ widgets.Label{
view_id = 'text', view_id = 'text',
@ -60,7 +60,7 @@ function test.correct_frame_body_without_show_scroll_icons()
t[#t+1] = NEWLINE t[#t+1] = NEWLINE
end end
function fs:init(args) function fs:init()
self:addviews{ self:addviews{
widgets.Label{ widgets.Label{
view_id = 'text', view_id = 'text',
@ -74,3 +74,43 @@ function test.correct_frame_body_without_show_scroll_icons()
local o = fs{} local o = fs{}
expect.eq(o.subviews.text.frame_body.width, 10, "Label's frame_body.x2 and .width should not change with show_scroll_icons = false.") expect.eq(o.subviews.text.frame_body.width, 10, "Label's frame_body.x2 and .width should not change with show_scroll_icons = false.")
end end
function test.scroll()
local t = {}
for i = 1, 12 do
t[#t+1] = tostring(i)
t[#t+1] = NEWLINE
end
function fs:init()
self:addviews{
widgets.Label{
view_id = 'text',
frame_inset = 0,
text = t,
},
}
end
local o = fs{frame_height=3}
local txt = o.subviews.text
expect.eq(1, txt.start_line_num)
txt:scroll(1)
expect.eq(2, txt.start_line_num)
txt:scroll('+page')
expect.eq(5, txt.start_line_num)
txt:scroll('+halfpage')
expect.eq(7, txt.start_line_num)
txt:scroll('-halfpage')
expect.eq(5, txt.start_line_num)
txt:scroll('-page')
expect.eq(2, txt.start_line_num)
txt:scroll(-1)
expect.eq(1, txt.start_line_num)
txt:scroll(-1)
expect.eq(1, txt.start_line_num)
txt:scroll(100)
expect.eq(10, txt.start_line_num)
end