show full scrollbars instead of just scroll icons

develop
myk002 2022-09-11 17:58:10 -07:00
parent 09372680a2
commit f71f034d1d
No known key found for this signature in database
GPG Key ID: 8A39CA0FA0C16E78
3 changed files with 62 additions and 24 deletions

@ -4039,13 +4039,12 @@ It has the following attributes:
keys to the number of lines to scroll as positive or negative integers or one of the keywords 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 supported by the ``scroll`` method. The default is up/down arrows scrolling by one line and page
up/down scrolling by one page. up/down scrolling by one page.
:show_scroll_icons: Controls scroll icons' behaviour: ``false`` for no icons, ``'right'`` or ``'left'`` for :show_scrollbar: Controls scrollbar display: ``false`` for no scrollbar, ``'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)`` (``↑``). :scrollbar_fg: Specifies the pen for the scroll icons and the active part of the bar. Default is ``COLOR_LIGHTGREEN`` (the same as the native DF help screens).
:down_arrow_icon: The symbol for scroll down arrow. Default is ``string.char(25)`` (``↓``). :scrollbar_bg: Specifies the pen for the background part of the scrollbar. Default is ``COLOR_CYAN`` (the same as the native DF help screens).
:scroll_icon_pen: Specifies the pen for scroll icons. Default is ``COLOR_LIGHTCYAN``.
The text itself is represented as a complex structure, and passed The text itself is represented as a complex structure, and passed
to the object via the ``text`` argument of the constructor, or via to the object via the ``text`` argument of the constructor, or via

@ -64,6 +64,7 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
- `seedwatch`: ``seedwatch all`` now adds all plants with seeds to the watchlist, not just the "basic" crops. - `seedwatch`: ``seedwatch all`` now adds all plants with seeds to the watchlist, not just the "basic" crops.
- UX: You can now move the cursor around in DFHack text fields in ``gui/`` scripts (e.g. `gui/blueprint`, `gui/quickfort`, or `gui/gm-editor`). You can move the cursor by clicking where you want it to go with the mouse or using the Left/Right arrow keys. Ctrl+Left/Right will move one word at a time, and Alt+Left/Right will move to the beginning/end of the text. - UX: You can now move the cursor around in DFHack text fields in ``gui/`` scripts (e.g. `gui/blueprint`, `gui/quickfort`, or `gui/gm-editor`). You can move the cursor by clicking where you want it to go with the mouse or using the Left/Right arrow keys. Ctrl+Left/Right will move one word at a time, and Alt+Left/Right will move to the beginning/end of the text.
- UX: You can now click on the hotkey hint text in many ``gui/`` script windows to activate the hotkey, like a button. Not all scripts have been updated to use the clickable widget yet, but you can try it in `gui/blueprint` or `gui/quickfort`. - UX: You can now click on the hotkey hint text in many ``gui/`` script windows to activate the hotkey, like a button. Not all scripts have been updated to use the clickable widget yet, but you can try it in `gui/blueprint` or `gui/quickfort`.
- UX: Label widget scroll icons are replaced with scrollbars that represent the percentage of text on the screen and move with the position of the visible text, just like web browser scrollbars.
- `quickfort`: `Dreamfort <quickfort-blueprint-guide>` blueprint set improvements: set traffic designations to encourage dwarves to eat cooked food instead of raw ingredients - `quickfort`: `Dreamfort <quickfort-blueprint-guide>` blueprint set improvements: set traffic designations to encourage dwarves to eat cooked food instead of raw ingredients
## Documentation ## Documentation

@ -544,12 +544,10 @@ Label.ATTRS{
auto_width = false, auto_width = false,
on_click = DEFAULT_NIL, on_click = DEFAULT_NIL,
on_rclick = DEFAULT_NIL, on_rclick = DEFAULT_NIL,
--
scroll_keys = STANDARDSCROLL, scroll_keys = STANDARDSCROLL,
show_scroll_icons = DEFAULT_NIL, -- DEFAULT_NIL, 'right', 'left', false show_scrollbar = DEFAULT_NIL, -- DEFAULT_NIL, 'right', 'left', false
up_arrow_icon = string.char(24), scrollbar_fg = COLOR_LIGHTGREEN,
down_arrow_icon = string.char(25), scrollbar_bg = COLOR_CYAN
scroll_icon_pen = COLOR_LIGHTCYAN,
} }
function Label:init(args) function Label:init(args)
@ -573,16 +571,16 @@ function Label:setText(text)
end end
function Label:update_scroll_inset() function Label:update_scroll_inset()
if self.show_scroll_icons == nil then if self.show_scrollbar == nil then
self._show_scroll_icons = self:getTextHeight() > self.frame_body.height and 'right' or false self._show_scrollbar = self:getTextHeight() > self.frame_body.height and 'right' or false
else else
self._show_scroll_icons = self.show_scroll_icons self._show_scrollbar = self.show_scrollbar
end end
if self._show_scroll_icons then if self._show_scrollbar then
-- here self._show_scroll_icons can only be either -- here self._show_scrollbar can only be either
-- 'left' or any true value which we interpret as right -- 'left' or any true value which we interpret as right
local l,t,r,b = gui.parse_inset(self.frame_inset) local l,t,r,b = gui.parse_inset(self.frame_inset)
if self._show_scroll_icons == 'left' and l <= 0 then if self._show_scrollbar == 'left' and l <= 0 then
l = 1 l = 1
elseif r <= 0 then elseif r <= 0 then
r = 1 r = 1
@ -591,14 +589,54 @@ function Label:update_scroll_inset()
end end
end end
function Label:render_scroll_icons(dc, x, y1, y2) -- the position is the number of tiles of empty space above the top of the
if self.start_line_num ~= 1 then -- scrollbar, and the height is the number of tiles the scrollbar should occupy
dc:seek(x, y1):char(self.up_arrow_icon, self.scroll_icon_pen) -- to represent the percentage of text that is on the screen.
local function get_scrollbar_pos_and_height(label)
local first_visible_line = label.start_line_num
local text_height = label:getTextHeight()
local last_visible_line = first_visible_line + label.frame_body.height - 1
local scrollbar_body_height = label.frame_body.height - 2
local displayed_lines = last_visible_line - first_visible_line
local height = math.min(scrollbar_body_height - 1,
math.ceil((displayed_lines-1) * scrollbar_body_height / text_height))
local max_pos = scrollbar_body_height - height
local pos = math.ceil(((first_visible_line-1) * max_pos) /
(text_height - label.frame_body.height))
return pos, height
end
local UP_ARROW_CHAR = string.char(24)
local DOWN_ARROW_CHAR = string.char(25)
local NO_ARROW_CHAR = string.char(32)
local BAR_CHAR = string.char(7)
local BAR_BG_CHAR = string.char(179)
function Label:render_scrollbar(dc, x, y1, y2)
-- render up arrow if we're not at the top
dc:seek(x, y1):char(
self.start_line_num == 1 and NO_ARROW_CHAR or UP_ARROW_CHAR,
self.scrollbar_fg, self.scrollbar_bg)
-- render scrollbar body
local pos, height = get_scrollbar_pos_and_height(self)
local starty = y1 + pos + 1
local endy = y1 + pos + height
for y=y1+1,y2-1 do
if y >= starty and y <= endy then
dc:seek(x, y):char(BAR_CHAR, self.scrollbar_fg)
else
dc:seek(x, y):char(BAR_BG_CHAR, self.scrollbar_bg)
end
end end
-- render down arrow if we're not at the bottom
local last_visible_line = self.start_line_num + self.frame_body.height - 1 local last_visible_line = self.start_line_num + self.frame_body.height - 1
if last_visible_line < self:getTextHeight() then dc:seek(x, y2):char(
dc:seek(x, y2):char(self.down_arrow_icon, self.scroll_icon_pen) last_visible_line >= self:getTextHeight() and
end NO_ARROW_CHAR or DOWN_ARROW_CHAR,
self.scrollbar_fg, self.scrollbar_bg)
end end
function Label:computeFrame(parent_rect) function Label:computeFrame(parent_rect)
@ -644,13 +682,13 @@ function Label:onRenderBody(dc)
end end
function Label:onRenderFrame(dc, rect) function Label:onRenderFrame(dc, rect)
if self._show_scroll_icons if self._show_scrollbar
and self:getTextHeight() > self.frame_body.height and self:getTextHeight() > self.frame_body.height
then then
local x = self._show_scroll_icons == 'left' local x = self._show_scrollbar == 'left'
and self.frame_body.x1-dc.x1-1 and self.frame_body.x1-dc.x1-1
or self.frame_body.x2-dc.x1+1 or self.frame_body.x2-dc.x1+1
self:render_scroll_icons(dc, self:render_scrollbar(dc,
x, x,
self.frame_body.y1-dc.y1, self.frame_body.y1-dc.y1,
self.frame_body.y2-dc.y1 self.frame_body.y2-dc.y1