From 35eb4e08dd53133abc14fdb189bfc9dd8fa848b7 Mon Sep 17 00:00:00 2001 From: myk002 Date: Fri, 7 Oct 2022 15:40:05 -0700 Subject: [PATCH] hold down the mouse button to continue scrolling --- docs/Lua API.rst | 12 +++++++++++ docs/changelog.txt | 1 + library/lua/gui/widgets.lua | 41 ++++++++++++++++++++++++++++++------- 3 files changed, 47 insertions(+), 7 deletions(-) diff --git a/docs/Lua API.rst b/docs/Lua API.rst index ddb00c61a..8960cb15c 100644 --- a/docs/Lua API.rst +++ b/docs/Lua API.rst @@ -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 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 ----------- diff --git a/docs/changelog.txt b/docs/changelog.txt index b1d5300a9..1669ea9dd 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -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. - `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: You can now hold down the mouse button on a scrollbar to make it scroll multiple times. ## Documentation diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 2eaf80577..e5b7e9bfd 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -363,6 +363,11 @@ end -- 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.ATTRS{ @@ -377,6 +382,9 @@ function Scrollbar:preinit(init_table) end function Scrollbar:init() + self.last_scroll_ms = 0 + self.is_first_click = false + self.scroll_spec = nil self:update(1, 1, 1) end @@ -434,19 +442,38 @@ function Scrollbar:onRenderBody(dc) dc:seek(0, dc.height-1):char( last_visible_el >= self.num_elems and NO_ARROW_CHAR or DOWN_ARROW_CHAR, 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 function Scrollbar:onInput(keys) if not keys._MOUSE_L_DOWN or not self.on_scroll then return false end local _,y = self:getMousePos() if not y then return false end - local scroll = nil - if y == 0 then scroll = 'up_small' - elseif y == self.frame_body.height - 1 then scroll = 'down_small' - elseif y <= self.bar_offset then scroll = 'up_large' - elseif y > self.bar_offset + self.bar_height then scroll = 'down_large' - end - if scroll then self.on_scroll(scroll) end + local scroll_spec = nil + if y == 0 then scroll_spec = 'up_small' + elseif y == self.frame_body.height - 1 then scroll_spec = 'down_small' + elseif y <= self.bar_offset then scroll_spec = 'up_large' + elseif y > self.bar_offset + self.bar_height then scroll_spec = 'down_large' + 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 end