Skip to content
Merged
Changes from 2 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
1b79147
Create helloSlider.lua
realSquidCoder Jan 1, 2025
9d68aca
Update helloSlider.lua to try and fix precommit EOF errors
realSquidCoder Jan 1, 2025
bbac6c4
Merge branch 'master' into squid-slider-widget
realSquidCoder Jan 16, 2025
81e5179
Move code to new files
realSquidCoder Jan 16, 2025
735f5d5
Clean up code
realSquidCoder Jan 20, 2025
9055dc8
Clean up the code and add a divider
realSquidCoder Jan 20, 2025
ca91203
Merge branch 'DFHack:master' into squid-slider-widget
realSquidCoder Jan 26, 2025
45c1997
Update hello-world.lua
realSquidCoder Jan 26, 2025
1e98d04
Merge branch 'master' into squid-slider-widget
realSquidCoder Feb 11, 2025
8f12b8a
Merge branch 'DFHack:master' into squid-slider-widget
realSquidCoder Feb 11, 2025
1bc3501
Update hello-world.lua
realSquidCoder Feb 11, 2025
2d6d854
Update changelog.txt
realSquidCoder Feb 11, 2025
a4a4ab3
Merge remote-tracking branch 'upstream/master' into squid-slider-widget
realSquidCoder Jul 3, 2025
952e0fb
Merge remote-tracking branch 'upstream/master' into squid-slider-widget
realSquidCoder Aug 17, 2025
ebacabd
Update changelog.txt
realSquidCoder Aug 17, 2025
efaf42e
Merge branch 'master' into squid-slider-widget
realSquidCoder Aug 17, 2025
7e37ac2
Merge remote-tracking branch 'upstream/master' into squid-slider-widget
realSquidCoder Aug 17, 2025
2a78083
Merge branch 'squid-slider-widget' of https://github.com/SquidCoderIn…
realSquidCoder Aug 17, 2025
56bca44
Update changelog.txt
realSquidCoder Aug 17, 2025
44bf3c6
Update changelog.txt
realSquidCoder Aug 17, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
212 changes: 212 additions & 0 deletions devel/helloSlider.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,212 @@
local Widget = require('gui.widgets.widget')

local to_pen = dfhack.pen.parse

--------------------------------
-- Slider
--------------------------------

---@class widgets.Slider.attrs: widgets.Widget.attrs
---@field num_stops integer
---@field get_idx_fn? function
---@field on_change? fun(index: integer)

---@class widgets.Slider.attrs.partial: widgets.Slider.attrs

---@class widgets.Slider.initTable: widgets.Slider.attrs
---@field num_stops integer

---@class widgets.Slider: widgets.Widget, widgets.Slider.attrs
---@field super widgets.Widget
---@field ATTRS widgets.Slider.attrs|fun(attributes: widgets.Slider.attrs.partial)
---@overload fun(init_table: widgets.Slider.initTable): self
Slider = defclass(Slider, Widget)
Slider.ATTRS{
num_stops=DEFAULT_NIL,
get_idx_fn=DEFAULT_NIL,
on_change=DEFAULT_NIL,
}

function Slider:preinit(init_table)
init_table.frame = init_table.frame or {}
init_table.frame.h = init_table.frame.h or 1
end

function Slider:init()
if self.num_stops < 2 then error('too few Slider stops') end
self.is_dragging_target = nil -- 'left', 'right', or 'both'
self.is_dragging_idx = nil -- offset from leftmost dragged tile
end

local function Slider_get_width_per_idx(self)
return math.max(3, (self.frame_body.width-7) // (self.num_stops-1))
end

function Slider:onInput(keys)
if not keys._MOUSE_L then return false end
local x = self:getMousePos()
if not x then return false end
local left_idx = self.get_idx_fn()
local width_per_idx = Slider_get_width_per_idx(self)
local left_pos = width_per_idx*(left_idx-1)
local right_pos = width_per_idx*(left_idx-1) + 4
if x < left_pos then
self.on_change(self.get_idx_fn() - 1)
else
self.is_dragging_target = 'both'
self.is_dragging_idx = x - right_pos
end
return true
end

local function Slider_do_drag(self, width_per_idx)
local x = self.frame_body:localXY(dfhack.screen.getMousePos())
local cur_pos = x - self.is_dragging_idx
cur_pos = math.max(0, cur_pos)
cur_pos = math.min(width_per_idx*(self.num_stops-1)+7, cur_pos)
local offset = 1
local new_idx = math.max(0, cur_pos+offset)//width_per_idx + 1
if self.is_dragging_target == 'both' then
if new_idx > self.num_stops then
return
end
end
if new_idx and new_idx ~= self.get_idx_fn() then
self.on_change(new_idx)
end
end

local SLIDER_LEFT_END = to_pen{ch=198, fg=COLOR_GREY, bg=COLOR_BLACK}
local SLIDER_TRACK = to_pen{ch=205, fg=COLOR_GREY, bg=COLOR_BLACK}
local SLIDER_TRACK_SELECTED = to_pen{ch=205, fg=COLOR_LIGHTGREEN, bg=COLOR_BLACK}
local SLIDER_TRACK_STOP = to_pen{ch=216, fg=COLOR_GREY, bg=COLOR_BLACK}
local SLIDER_TRACK_STOP_SELECTED = to_pen{ch=216, fg=COLOR_LIGHTGREEN, bg=COLOR_BLACK}
local SLIDER_RIGHT_END = to_pen{ch=181, fg=COLOR_GREY, bg=COLOR_BLACK}
local SLIDER_TAB_LEFT = to_pen{ch=60, fg=COLOR_BLACK, bg=COLOR_YELLOW}
local SLIDER_TAB_CENTER = to_pen{ch=9, fg=COLOR_BLACK, bg=COLOR_YELLOW}
local SLIDER_TAB_RIGHT = to_pen{ch=62, fg=COLOR_BLACK, bg=COLOR_YELLOW}

function Slider:onRenderBody(dc, rect)
local left_idx = self.get_idx_fn()
local width_per_idx = Slider_get_width_per_idx(self)
-- draw track
dc:seek(1,0)
dc:char(nil, SLIDER_LEFT_END)
dc:char(nil, SLIDER_TRACK)
for stop_idx=1,self.num_stops-1 do
local track_stop_pen = SLIDER_TRACK_STOP_SELECTED
local track_pen = SLIDER_TRACK_SELECTED
if left_idx ~= stop_idx then
track_stop_pen = SLIDER_TRACK_STOP
track_pen = SLIDER_TRACK
elseif left_idx == stop_idx then
track_pen = SLIDER_TRACK
end
dc:char(nil, track_stop_pen)
for i=2,width_per_idx do
dc:char(nil, track_pen)
end
end
if left_idx >= self.num_stops then
dc:char(nil, SLIDER_TRACK_STOP_SELECTED)
else
dc:char(nil, SLIDER_TRACK_STOP)
end
dc:char(nil, SLIDER_TRACK)
dc:char(nil, SLIDER_RIGHT_END)
-- draw tab
dc:seek(width_per_idx*(left_idx-1)+2)
dc:char(nil, SLIDER_TAB_LEFT)
dc:char(nil, SLIDER_TAB_CENTER)
dc:char(nil, SLIDER_TAB_RIGHT)
-- manage dragging
if self.is_dragging_target then
Slider_do_drag(self, width_per_idx)
end
if df.global.enabler.mouse_lbut_down == 0 then
self.is_dragging_target = nil
self.is_dragging_idx = nil
end
end
Comment thread
realSquidCoder marked this conversation as resolved.
Outdated











local gui = require('gui')
local widgets = require('gui.widgets')

--
-- RangerWindow
--

RangerWindow = defclass(RangerWindow, widgets.Window)
RangerWindow.ATTRS {
frame_title='Hello, Slider!',
frame={w=25, h=8},
resizable=true,
resize_min={w=25, h=8},
}

function RangerWindow:init()
local LEVEL_OPTIONS = {
{label='Low', value=1},
{label='Medium', value=2},
{label='High', value=3},
{label='Pro', value=4},
{label='Insane', value=5},
}

self:addviews{
widgets.CycleHotkeyLabel{
view_id='level',
frame={l=1, t=0, w=16},
label='Level:',
label_below=true,
key_back='CUSTOM_SHIFT_C',
key='CUSTOM_SHIFT_V',
options=LEVEL_OPTIONS,
initial_option=LEVEL_OPTIONS[1].value,
on_change=function(val)
self.subviews.level:setOption(val)
end,
},
Slider{
frame={l=1, t=3},
num_stops=#LEVEL_OPTIONS,
get_idx_fn=function()
return self.subviews.level:getOptionValue()
end,
on_change=function(idx) self.subviews.level:setOption(idx) end,
},
}
Comment thread
realSquidCoder marked this conversation as resolved.
Outdated
end

--
-- RangerScreen
--

RangerScreen = defclass(RangerScreen, gui.ZScreen)
RangerScreen.ATTRS {
focus_path='ranger',
}

function RangerScreen:init()
self:addviews{RangerWindow{}}
end

function RangerScreen:onDismiss()
view = nil
end

--
-- main logic
--

view = view and view:raise() or RangerScreen{}:show()