From 1b79147cce59e0288424ed2f5e438823e332185d Mon Sep 17 00:00:00 2001 From: Squid Coder <92821989+realSquidCoder@users.noreply.github.com> Date: Wed, 1 Jan 2025 11:34:58 -0600 Subject: [PATCH 1/8] Create helloSlider.lua Created helloSlider.lua (a prototype for a new single-slider widget) --- devel/helloSlider.lua | 212 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 devel/helloSlider.lua diff --git a/devel/helloSlider.lua b/devel/helloSlider.lua new file mode 100644 index 0000000000..ff850d0982 --- /dev/null +++ b/devel/helloSlider.lua @@ -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 + + + + + + + + + + + +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, + }, + } +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() \ No newline at end of file From 9d68acaef29eac40be4cbd85a7541d41a2e423e0 Mon Sep 17 00:00:00 2001 From: Squid Coder <92821989+realSquidCoder@users.noreply.github.com> Date: Wed, 1 Jan 2025 11:37:53 -0600 Subject: [PATCH 2/8] Update helloSlider.lua to try and fix precommit EOF errors --- devel/helloSlider.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/devel/helloSlider.lua b/devel/helloSlider.lua index ff850d0982..f22b7c7a6b 100644 --- a/devel/helloSlider.lua +++ b/devel/helloSlider.lua @@ -209,4 +209,4 @@ end -- main logic -- -view = view and view:raise() or RangerScreen{}:show() \ No newline at end of file +view = view and view:raise() or RangerScreen{}:show() From 81e5179d29ef12f8ea44d8efee35bd34157b9014 Mon Sep 17 00:00:00 2001 From: Squid Coder <92821989+realSquidCoder@users.noreply.github.com> Date: Thu, 16 Jan 2025 12:25:44 -0600 Subject: [PATCH 3/8] Move code to new files --- devel/helloSlider.lua | 143 +----------------------------------------- devel/slider.lua | 132 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 133 insertions(+), 142 deletions(-) create mode 100644 devel/slider.lua diff --git a/devel/helloSlider.lua b/devel/helloSlider.lua index f22b7c7a6b..e2e250df6b 100644 --- a/devel/helloSlider.lua +++ b/devel/helloSlider.lua @@ -1,144 +1,3 @@ -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 - - - - - - - - - - - local gui = require('gui') local widgets = require('gui.widgets') @@ -177,7 +36,7 @@ function RangerWindow:init() self.subviews.level:setOption(val) end, }, - Slider{ + widgets.Slider{ frame={l=1, t=3}, num_stops=#LEVEL_OPTIONS, get_idx_fn=function() diff --git a/devel/slider.lua b/devel/slider.lua new file mode 100644 index 0000000000..92263d2924 --- /dev/null +++ b/devel/slider.lua @@ -0,0 +1,132 @@ +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 + +return Slider From 735f5d5a25d5cce7e6575d69aa6ed745bcad1ecd Mon Sep 17 00:00:00 2001 From: Squid Coder <92821989+realSquidCoder@users.noreply.github.com> Date: Mon, 20 Jan 2025 12:15:32 -0600 Subject: [PATCH 4/8] Clean up code Move Slider example into the hello world move the Slider widget away to its proper place (DFHack Repo). --- devel/hello-world.lua | 33 ++++++++++- devel/helloSlider.lua | 71 ----------------------- devel/slider.lua | 132 ------------------------------------------ 3 files changed, 32 insertions(+), 204 deletions(-) delete mode 100644 devel/helloSlider.lua delete mode 100644 devel/slider.lua diff --git a/devel/hello-world.lua b/devel/hello-world.lua index 679bf1d52e..bf872f4baa 100644 --- a/devel/hello-world.lua +++ b/devel/hello-world.lua @@ -12,13 +12,23 @@ local HIGHLIGHT_PEN = dfhack.pen.parse{ HelloWorldWindow = defclass(HelloWorldWindow, widgets.Window) HelloWorldWindow.ATTRS{ - frame={w=20, h=14}, + frame={w=25, h=20}, frame_title='Hello World', autoarrange_subviews=true, autoarrange_gap=1, + resizable=true, + resize_min={w=25, h=20}, } function HelloWorldWindow: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.Label{text={{text='Hello, world!', pen=COLOR_LIGHTGREEN}}}, widgets.HotkeyLabel{ @@ -32,6 +42,27 @@ function HelloWorldWindow:init() frame={w=10, h=5}, frame_style=gui.INTERIOR_FRAME, }, + 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, + }, + widgets.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, + }, } end diff --git a/devel/helloSlider.lua b/devel/helloSlider.lua deleted file mode 100644 index e2e250df6b..0000000000 --- a/devel/helloSlider.lua +++ /dev/null @@ -1,71 +0,0 @@ -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, - }, - widgets.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, - }, - } -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() diff --git a/devel/slider.lua b/devel/slider.lua deleted file mode 100644 index 92263d2924..0000000000 --- a/devel/slider.lua +++ /dev/null @@ -1,132 +0,0 @@ -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 - -return Slider From 9055dc8fe5a46e56786c7928493d7616593ee5ab Mon Sep 17 00:00:00 2001 From: Squid Coder <92821989+realSquidCoder@users.noreply.github.com> Date: Mon, 20 Jan 2025 12:34:33 -0600 Subject: [PATCH 5/8] Clean up the code and add a divider --- devel/hello-world.lua | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/devel/hello-world.lua b/devel/hello-world.lua index bf872f4baa..5e8b22ebb6 100644 --- a/devel/hello-world.lua +++ b/devel/hello-world.lua @@ -12,10 +12,10 @@ local HIGHLIGHT_PEN = dfhack.pen.parse{ HelloWorldWindow = defclass(HelloWorldWindow, widgets.Window) HelloWorldWindow.ATTRS{ - frame={w=25, h=20}, + frame={w=25, h=25}, frame_title='Hello World', autoarrange_subviews=true, - autoarrange_gap=1, + autoarrange_gap=2, resizable=true, resize_min={w=25, h=20}, } @@ -28,7 +28,7 @@ function HelloWorldWindow:init() {label='Pro', value=4}, {label='Insane', value=5}, } - + self:addviews{ widgets.Label{text={{text='Hello, world!', pen=COLOR_LIGHTGREEN}}}, widgets.HotkeyLabel{ @@ -42,9 +42,12 @@ function HelloWorldWindow:init() frame={w=10, h=5}, frame_style=gui.INTERIOR_FRAME, }, + widgets.Divider{ + frame={l=0,t=3} + }, widgets.CycleHotkeyLabel{ view_id='level', - frame={l=1, t=0, w=16}, + frame={l=0, t=3, w=16}, label='Level:', label_below=true, key_back='CUSTOM_SHIFT_C', From 45c1997ec1077abd50ddefed6003e22df22777c0 Mon Sep 17 00:00:00 2001 From: Squid Coder <92821989+realSquidCoder@users.noreply.github.com> Date: Sun, 26 Jan 2025 14:42:16 -0600 Subject: [PATCH 6/8] Update hello-world.lua --- devel/hello-world.lua | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/devel/hello-world.lua b/devel/hello-world.lua index 5e8b22ebb6..12b9eab7c3 100644 --- a/devel/hello-world.lua +++ b/devel/hello-world.lua @@ -17,7 +17,7 @@ HelloWorldWindow.ATTRS{ autoarrange_subviews=true, autoarrange_gap=2, resizable=true, - resize_min={w=25, h=20}, + resize_min={w=25, h=25}, } function HelloWorldWindow:init() @@ -32,7 +32,7 @@ function HelloWorldWindow:init() self:addviews{ widgets.Label{text={{text='Hello, world!', pen=COLOR_LIGHTGREEN}}}, widgets.HotkeyLabel{ - frame={l=0, t=0}, + frame={l=0}, label='Click me', key='CUSTOM_CTRL_A', on_activate=self:callback('toggleHighlight'), @@ -43,23 +43,25 @@ function HelloWorldWindow:init() frame_style=gui.INTERIOR_FRAME, }, widgets.Divider{ - frame={l=0,t=3} + frame={h=1}, + frame_style_l=false, + frame_style_r=false, }, widgets.CycleHotkeyLabel{ view_id='level', - frame={l=0, t=3, w=16}, + frame={l=0, w=20}, label='Level:', - label_below=true, + label_below=false, 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) + self.callback{Slider.on_change(val)} end, }, widgets.Slider{ - frame={l=1, t=3}, + frame={l=1}, num_stops=#LEVEL_OPTIONS, get_idx_fn=function() return self.subviews.level:getOptionValue() From 1bc3501b5ee48ab70b24f96947314c4c3f4a89e7 Mon Sep 17 00:00:00 2001 From: Squid Coder Date: Tue, 11 Feb 2025 15:38:17 -0600 Subject: [PATCH 7/8] Update hello-world.lua --- devel/hello-world.lua | 4 ---- 1 file changed, 4 deletions(-) diff --git a/devel/hello-world.lua b/devel/hello-world.lua index 12b9eab7c3..2af576f815 100644 --- a/devel/hello-world.lua +++ b/devel/hello-world.lua @@ -51,14 +51,10 @@ function HelloWorldWindow:init() view_id='level', frame={l=0, w=20}, label='Level:', - label_below=false, key_back='CUSTOM_SHIFT_C', key='CUSTOM_SHIFT_V', options=LEVEL_OPTIONS, initial_option=LEVEL_OPTIONS[1].value, - on_change=function(val) - self.callback{Slider.on_change(val)} - end, }, widgets.Slider{ frame={l=1}, From 2d6d854cb295f1eb16533a1528a31d28c42b7dae Mon Sep 17 00:00:00 2001 From: Squid Coder Date: Tue, 11 Feb 2025 15:40:04 -0600 Subject: [PATCH 8/8] Update changelog.txt --- changelog.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.txt b/changelog.txt index 4965da0d76..31788f2d80 100644 --- a/changelog.txt +++ b/changelog.txt @@ -43,6 +43,7 @@ Template for new versions: - `gui/notify`: moody dwarf notification turns red when they can't reach workshop or items - `gui/confirm`: in the delete manager order confirmation dialog, show a description of which order you have selected to delete - `position`: display both adventurer and site pos simultaneously. Display map block pos+offset of selected tile. +- `devel/hello-world`: updated to show off the new Slider widget ## Removed