Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add prototype for a new slider widget with only one slider. #1363

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

realSquidCoder
Copy link
Contributor

@realSquidCoder realSquidCoder commented Jan 1, 2025

Created devel/helloSlider.lua (a prototype for a new single-slider widget)

Created helloSlider.lua (a prototype for a new single-slider widget)
@realSquidCoder realSquidCoder marked this pull request as ready for review January 1, 2025 17:38
Comment on lines +5 to +130
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
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment on lines +158 to +188
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,
},
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this code should be added to https://github.com/DFHack/scripts/blob/master/devel/hello-world.lua, with frame sizes adjusted to accommodate.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants