Merge pull request #2320 from myk002/myk_scrollbar_multiscroll

[widgets.Scrollbar] hold down the mouse button to continue scrolling
develop
Myk 2022-10-07 16:26:45 -07:00 committed by GitHub
commit a088287317
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 7 deletions

@ -4064,6 +4064,18 @@ direction. The amount of scrolling done in each case in determined by the
associated widget, and after scrolling is complete, the associated widget must associated widget, and after scrolling is complete, the associated widget must
call ``scrollbar:update()`` with updated new display info. call ``scrollbar:update()`` with updated new display info.
You can hold down the mouse button to scroll multiple times, just like in a
normal browser scrollbar. The speed of scroll events when the mouse button is
held down is controlled by two global variables:
:``SCROLL_INITIAL_DELAY_MS``: The delay before the second scroll event.
:``SCROLL_DELAY_MS``: The delay between further scroll events.
The defaults are 300 and 20, respectively, but they can be overridden by the
user in their :file:`dfhack-config/init/dfhack.init` file, for example::
:lua require('gui.widgets').SCROLL_DELAY_MS = 100
Label class Label class
----------- -----------

@ -42,6 +42,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
- `ls`: new ``--exclude`` option for hiding matched scripts from the output. this can be especially useful for modders who don't want their mod scripts to be included in ``ls`` output. - `ls`: new ``--exclude`` option for hiding matched scripts from the output. this can be especially useful for modders who don't want their mod scripts to be included in ``ls`` output.
- `digtype`: new ``-z`` option for digtype to restrict designations to the current z-level and down - `digtype`: new ``-z`` option for digtype to restrict designations to the current z-level and down
- UX: List widgets now have mouse-interactive scrollbars - UX: List widgets now have mouse-interactive scrollbars
- UX: You can now hold down the mouse button on a scrollbar to make it scroll multiple times.
## Documentation ## Documentation

@ -363,6 +363,11 @@ end
-- Scrollbar -- -- Scrollbar --
--------------- ---------------
-- these can be overridden by the user, e.g.:
-- require('gui.widgets').SCROLL_DELAY_MS = 100
SCROLL_INITIAL_DELAY_MS = 300
SCROLL_DELAY_MS = 20
Scrollbar = defclass(Scrollbar, Widget) Scrollbar = defclass(Scrollbar, Widget)
Scrollbar.ATTRS{ Scrollbar.ATTRS{
@ -377,6 +382,9 @@ function Scrollbar:preinit(init_table)
end end
function Scrollbar:init() function Scrollbar:init()
self.last_scroll_ms = 0
self.is_first_click = false
self.scroll_spec = nil
self:update(1, 1, 1) self:update(1, 1, 1)
end end
@ -434,19 +442,38 @@ function Scrollbar:onRenderBody(dc)
dc:seek(0, dc.height-1):char( dc:seek(0, dc.height-1):char(
last_visible_el >= self.num_elems and NO_ARROW_CHAR or DOWN_ARROW_CHAR, last_visible_el >= self.num_elems and NO_ARROW_CHAR or DOWN_ARROW_CHAR,
self.fg, self.bg) self.fg, self.bg)
-- manage state for continuous scrolling
if self.last_scroll_ms == 0 or not self.on_scroll then return end
if df.global.enabler.mouse_lbut_down == 0 then
self.last_scroll_ms = 0
self.scroll_spec = nil
return
end
local now = dfhack.getTickCount()
local delay = self.is_first_click and
SCROLL_INITIAL_DELAY_MS or SCROLL_DELAY_MS
if now - self.last_scroll_ms >= delay then
self.is_first_click = false
self.on_scroll(self.scroll_spec)
self.last_scroll_ms = now
end
end end
function Scrollbar:onInput(keys) function Scrollbar:onInput(keys)
if not keys._MOUSE_L_DOWN or not self.on_scroll then return false end if not keys._MOUSE_L_DOWN or not self.on_scroll then return false end
local _,y = self:getMousePos() local _,y = self:getMousePos()
if not y then return false end if not y then return false end
local scroll = nil local scroll_spec = nil
if y == 0 then scroll = 'up_small' if y == 0 then scroll_spec = 'up_small'
elseif y == self.frame_body.height - 1 then scroll = 'down_small' elseif y == self.frame_body.height - 1 then scroll_spec = 'down_small'
elseif y <= self.bar_offset then scroll = 'up_large' elseif y <= self.bar_offset then scroll_spec = 'up_large'
elseif y > self.bar_offset + self.bar_height then scroll = 'down_large' elseif y > self.bar_offset + self.bar_height then scroll_spec = 'down_large'
end end
if scroll then self.on_scroll(scroll) end self.scroll_spec = scroll_spec
if scroll_spec then self.on_scroll(scroll_spec) end
-- reset continuous scroll state
self.is_first_click = true
self.last_scroll_ms = dfhack.getTickCount()
return true return true
end end