diff --git a/docs/changelog.txt b/docs/changelog.txt index eb90bcf861..7ce53f2c65 100644 --- a/docs/changelog.txt +++ b/docs/changelog.txt @@ -82,8 +82,10 @@ Template for new versions: - ``dfhack.units.setAutomaticProfessions``: sets unit labors according to current work detail settings - ``dfhack.military.removeFromSquad``: Lua API for ``Military::removeFromSquad`` - ``gui.dwarfmode``: adventure mode cursor now supported in ``getCursorPos``, ``setCursorPos``, and ``clearCursorPos`` funcitons +- ``widgets.Slider``: new mouse-controlled single-headed slider widget - ``dfhack.buildings.checkFreeTiles``: now replaces the extents parameter for a building pointer + ## Removed # 51.05-r1 diff --git a/docs/dev/Lua API.rst b/docs/dev/Lua API.rst index f8108e8b2c..22c3b5598b 100644 --- a/docs/dev/Lua API.rst +++ b/docs/dev/Lua API.rst @@ -6454,10 +6454,24 @@ change, the ``RangeSlider`` appearance will adjust automatically. :get_left_idx_fn: The function used by the RangeSlider to get the notch index on which to display the left handle. :get_right_idx_fn: The function used by the RangeSlider to get the notch index on which - to display the right handle. + to display the right handle. :on_left_change: Callback executed when moving the left handle. :on_right_change: Callback executed when moving the right handle. +Slider class +----------------- + +This widget implements a mouse-interactable slider. The player can move the handle to +set the value of the slider. The parent widget owns the slider value, and can control +it independently (e.g., with ``CycleHotkeyLabels``). If the value changes, the ``Slider`` +appearance will adjust automatically. + +:num_stops: Used to specify the number of "notches" in the slider, the places + where the handle can stop. (This should match the parents' number of options.) +:get_idx_fn: The function used by the Slider to get the notch index on which + to display the handle. +:on_change: Callback executed when moving the handle. + DimensionsTooltip class ----------------------- diff --git a/library/lua/gui/widgets.lua b/library/lua/gui/widgets.lua index 8a5daab7b2..e7870f88e8 100644 --- a/library/lua/gui/widgets.lua +++ b/library/lua/gui/widgets.lua @@ -27,6 +27,7 @@ List = require('gui.widgets.list') FilteredList = require('gui.widgets.filtered_list') TabBar = require('gui.widgets.tab_bar') RangeSlider = require('gui.widgets.range_slider') +Slider = require('gui.widgets.slider') DimensionsTooltip = require('gui.widgets.dimensions_tooltip') TextArea = require('gui.widgets.text_area') diff --git a/library/lua/gui/widgets/range_slider.lua b/library/lua/gui/widgets/range_slider.lua index bd1f9cb3de..f55f0e00f0 100644 --- a/library/lua/gui/widgets/range_slider.lua +++ b/library/lua/gui/widgets/range_slider.lua @@ -29,6 +29,7 @@ RangeSlider.ATTRS{ get_right_idx_fn=DEFAULT_NIL, on_left_change=DEFAULT_NIL, on_right_change=DEFAULT_NIL, + is_single=DEFAULT_NIL } function RangeSlider:preinit(init_table) @@ -43,7 +44,8 @@ function RangeSlider:init() end local function rangeslider_get_width_per_idx(self) - return math.max(5, (self.frame_body.width-7) // (self.num_stops-1)) + local min_value = (self.is_single) and 3 or 5 -- Single slider = 3, else 5 + return math.max(min_value, (self.frame_body.width-7) // (self.num_stops-1)) end function RangeSlider:onInput(keys) @@ -142,16 +144,27 @@ function RangeSlider:onRenderBody(dc, rect) end dc:char(nil, SLIDER_TRACK) dc:char(nil, SLIDER_RIGHT_END) - -- draw tabs - dc:seek(width_per_idx*(left_idx-1)) - dc:char(nil, SLIDER_TAB_LEFT) - dc:char(nil, SLIDER_TAB_CENTER) - dc:char(nil, SLIDER_TAB_RIGHT) - dc:seek(width_per_idx*(right_idx-1)+4) - dc:char(nil, SLIDER_TAB_LEFT) - dc:char(nil, SLIDER_TAB_CENTER) - dc:char(nil, SLIDER_TAB_RIGHT) - -- manage dragging + + -- Draw tab(s) + if self.is_single then + -- Single slider: Draw one centered tab + dc:seek(width_per_idx * (left_idx-1) + 2) -- Center the tab + dc:char(nil, SLIDER_TAB_LEFT) + dc:char(nil, SLIDER_TAB_CENTER) + dc:char(nil, SLIDER_TAB_RIGHT) + else + -- Dual slider: Draw left and right tabs separately + dc:seek(width_per_idx * (left_idx-1)) + dc:char(nil, SLIDER_TAB_LEFT) + dc:char(nil, SLIDER_TAB_CENTER) + dc:char(nil, SLIDER_TAB_RIGHT) + dc:seek(width_per_idx*(right_idx-1)+4) + dc:char(nil, SLIDER_TAB_LEFT) + dc:char(nil, SLIDER_TAB_CENTER) + dc:char(nil, SLIDER_TAB_RIGHT) + end + + -- Manage dragging if self.is_dragging_target then rangeslider_do_drag(self, width_per_idx) end diff --git a/library/lua/gui/widgets/slider.lua b/library/lua/gui/widgets/slider.lua new file mode 100644 index 0000000000..23bf6f6202 --- /dev/null +++ b/library/lua/gui/widgets/slider.lua @@ -0,0 +1,22 @@ +-- slider.lua +local RangeSlider = require('gui.widgets.range_slider') + +local Slider = defclass(Slider, RangeSlider) +Slider.ATTRS { + get_idx_fn = DEFAULT_NIL, -- Function to get the current index + on_change = DEFAULT_NIL, -- Function to handle index change + is_single = true +} + +function Slider:init() + self.get_left_idx_fn = self.get_idx_fn + self.get_right_idx_fn = self.get_idx_fn + self.on_left_change = function(index) + if self.on_change then self.on_change(index) end + end + self.on_right_change = function(index) + if self.on_change then self.on_change(index) end + end +end + +return Slider