Skip to content

Commit 7c417a4

Browse files
authored
Merge pull request #4955 from wiktor-obrebski/refactor/widgets
Refactor/widgets
2 parents d60b196 + 0badb26 commit 7c417a4

25 files changed

Lines changed: 3524 additions & 3333 deletions

library/lua/gui/widgets.lua

Lines changed: 32 additions & 3333 deletions
Large diffs are not rendered by default.
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
local CycleHotkeyLabel = require('gui.widgets.labels.cycle_hotkey_label')
2+
local Label = require('gui.widgets.labels.label')
3+
4+
-----------------
5+
-- ButtonGroup --
6+
-----------------
7+
8+
---@class widgets.ButtonGroup.attrs: widgets.CycleHotkeyLabel.attrs
9+
10+
---@class widgets.ButtonGroup.initTable: widgets.ButtonGroup.attrs
11+
---@field button_specs widgets.ButtonLabelSpec[]
12+
---@field button_specs_selected widgets.ButtonLabelSpec[]
13+
14+
---@class widgets.ButtonGroup: widgets.ButtonGroup.attrs, widgets.CycleHotkeyLabel
15+
---@field super widgets.CycleHotkeyLabel
16+
---@overload fun(init_table: widgets.ButtonGroup.initTable): self
17+
ButtonGroup = defclass(ButtonGroup, CycleHotkeyLabel)
18+
19+
ButtonGroup.ATTRS{
20+
auto_height=false,
21+
}
22+
23+
function ButtonGroup:init(info)
24+
ensure_key(self, 'frame').h = #info.button_specs[1].chars + 2
25+
26+
local start = 0
27+
for idx in ipairs(self.options) do
28+
local opt_val = self:getOptionValue(idx)
29+
local width = #info.button_specs[idx].chars[1]
30+
self:addviews{
31+
Label{
32+
frame={t=2, l=start, w=width},
33+
text=Label.makeButtonLabelText(info.button_specs[idx]),
34+
on_click=function() self:setOption(opt_val, true) end,
35+
visible=function() return self:getOptionValue() ~= opt_val end,
36+
},
37+
Label{
38+
frame={t=2, l=start, w=width},
39+
text=Label.makeButtonLabelText(info.button_specs_selected[idx]),
40+
on_click=function() self:setOption(opt_val, false) end,
41+
visible=function() return self:getOptionValue() == opt_val end,
42+
},
43+
}
44+
start = start + width
45+
end
46+
end
47+
48+
return ButtonGroup
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
local textures = require('gui.textures')
2+
local Panel = require('gui.widgets.containers.panel')
3+
local Label = require('gui.widgets.labels.label')
4+
5+
local to_pen = dfhack.pen.parse
6+
7+
local button_pen_left = to_pen{fg=COLOR_CYAN,
8+
tile=curry(textures.tp_control_panel, 7) or nil, ch=string.byte('[')}
9+
local button_pen_right = to_pen{fg=COLOR_CYAN,
10+
tile=curry(textures.tp_control_panel, 8) or nil, ch=string.byte(']')}
11+
local configure_pen_center = to_pen{
12+
tile=curry(textures.tp_control_panel, 10) or nil, ch=15} -- gear/masterwork symbol
13+
14+
---------------------
15+
-- ConfigureButton --
16+
---------------------
17+
18+
---@class widgets.ConfigureButton.attrs: widgets.Panel.attrs
19+
---@field on_click? function
20+
21+
---@class widgets.ConfigureButton.attrs.partial: widgets.ConfigureButton.attrs
22+
23+
---@class widgets.ConfigureButton: widgets.Panel, widgets.ConfigureButton.attrs
24+
---@field super widgets.Panel
25+
---@field ATTRS widgets.ConfigureButton.attrs|fun(attributes: widgets.ConfigureButton.attrs.partial)
26+
---@overload fun(init_table: widgets.ConfigureButton.attrs.partial): self
27+
ConfigureButton = defclass(ConfigureButton, Panel)
28+
29+
ConfigureButton.ATTRS{
30+
on_click=DEFAULT_NIL,
31+
}
32+
33+
function ConfigureButton:preinit(init_table)
34+
init_table.frame = init_table.frame or {}
35+
init_table.frame.h = init_table.frame.h or 1
36+
init_table.frame.w = init_table.frame.w or 3
37+
end
38+
39+
function ConfigureButton:init()
40+
self:addviews{
41+
Label{
42+
frame={t=0, l=0, w=3, h=1},
43+
text={
44+
{tile=button_pen_left},
45+
{tile=configure_pen_center},
46+
{tile=button_pen_right},
47+
},
48+
on_click=self.on_click,
49+
},
50+
}
51+
end
52+
53+
return ConfigureButton
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
local textures = require('gui.textures')
2+
local Panel = require('gui.widgets.containers.panel')
3+
local Label = require('gui.widgets.labels.label')
4+
5+
local to_pen = dfhack.pen.parse
6+
7+
----------------
8+
-- HelpButton --
9+
----------------
10+
11+
---@class widgets.HelpButton.attrs: widgets.Panel.attrs
12+
---@field command? string
13+
14+
---@class widgets.HelpButton.attrs.partial: widgets.HelpButton.attrs
15+
16+
---@class widgets.HelpButton: widgets.Panel, widgets.HelpButton.attrs
17+
---@field super widgets.Panel
18+
---@field ATTRS widgets.HelpButton.attrs|fun(attributes: widgets.HelpButton.attrs.partial)
19+
---@overload fun(init_table: widgets.HelpButton.attrs.partial): self
20+
HelpButton = defclass(HelpButton, Panel)
21+
22+
HelpButton.ATTRS{
23+
frame={t=0, r=1, w=3, h=1},
24+
command=DEFAULT_NIL,
25+
}
26+
27+
local button_pen_left = to_pen{fg=COLOR_CYAN,
28+
tile=curry(textures.tp_control_panel, 7) or nil, ch=string.byte('[')}
29+
local button_pen_right = to_pen{fg=COLOR_CYAN,
30+
tile=curry(textures.tp_control_panel, 8) or nil, ch=string.byte(']')}
31+
local help_pen_center = to_pen{
32+
tile=curry(textures.tp_control_panel, 9) or nil, ch=string.byte('?')}
33+
34+
function HelpButton:init()
35+
self.frame.w = self.frame.w or 3
36+
self.frame.h = self.frame.h or 1
37+
38+
local command = self.command .. ' '
39+
40+
self:addviews{
41+
Label{
42+
frame={t=0, l=0, w=3, h=1},
43+
text={
44+
{tile=button_pen_left},
45+
{tile=help_pen_center},
46+
{tile=button_pen_right},
47+
},
48+
on_click=function() dfhack.run_command('gui/launcher', command) end,
49+
},
50+
}
51+
end
52+
53+
return HelpButton
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
local BannerPanel = require('gui.widgets.containers.banner_panel')
2+
local HotkeyLabel = require('gui.widgets.labels.hotkey_label')
3+
4+
----------------
5+
-- TextButton --
6+
----------------
7+
8+
---@class widgets.TextButton.initTable: widgets.Panel.attrs.partial, widgets.HotkeyLabel.attrs.partial
9+
10+
---@class widgets.TextButton: widgets.BannerPanel
11+
---@field super widgets.BannerPanel
12+
---@overload fun(init_table: widgets.TextButton.initTable): self
13+
TextButton = defclass(TextButton, BannerPanel)
14+
15+
---@param info widgets.TextButton.initTable
16+
function TextButton:init(info)
17+
self.label = HotkeyLabel{
18+
frame={t=0, l=1, r=1},
19+
key=info.key,
20+
key_sep=info.key_sep,
21+
label=info.label,
22+
on_activate=info.on_activate,
23+
text_pen=info.text_pen,
24+
text_dpen=info.text_dpen,
25+
text_hpen=info.text_hpen,
26+
disabled=info.disabled,
27+
enabled=info.enabled,
28+
auto_height=info.auto_height,
29+
auto_width=info.auto_width,
30+
on_click=info.on_click,
31+
on_rclick=info.on_rclick,
32+
scroll_keys=info.scroll_keys,
33+
}
34+
35+
self:addviews{self.label}
36+
end
37+
38+
function TextButton:setLabel(label)
39+
self.label:setLabel(label)
40+
end
41+
42+
return TextButton
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
local Panel = require('gui.widgets.containers.panel')
2+
3+
-----------------
4+
-- BannerPanel --
5+
-----------------
6+
7+
---@class widgets.BannerPanel: widgets.Panel
8+
---@field super widgets.Panel
9+
BannerPanel = defclass(BannerPanel, Panel)
10+
11+
---@param dc gui.Painter
12+
function BannerPanel:onRenderBody(dc)
13+
dc:pen(COLOR_RED)
14+
for y=0,self.frame_rect.height-1 do
15+
dc:seek(0, y):char('[')
16+
dc:seek(self.frame_rect.width-1):char(']')
17+
end
18+
end
19+
20+
return BannerPanel
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
local gui = require('gui')
2+
local utils = require('utils')
3+
local Panel = require('gui.widgets.containers.panel')
4+
5+
---@param view gui.View
6+
---@param vis boolean
7+
local function show_view(view,vis)
8+
if view then
9+
view.visible = vis
10+
end
11+
end
12+
13+
-----------
14+
-- Pages --
15+
-----------
16+
17+
---@class widgets.Pages.initTable: widgets.Panel.attrs
18+
---@field selected? integer|string
19+
20+
---@class widgets.Pages: widgets.Panel
21+
---@field super widgets.Panel
22+
---@overload fun(attributes: widgets.Pages.initTable): self
23+
Pages = defclass(Pages, Panel)
24+
25+
---@param self widgets.Pages
26+
---@param args widgets.Pages.initTable
27+
function Pages:init(args)
28+
for _,v in ipairs(self.subviews) do
29+
v.visible = false
30+
end
31+
self:setSelected(args.selected or 1)
32+
end
33+
34+
---@param idx integer|string
35+
function Pages:setSelected(idx)
36+
if type(idx) ~= 'number' then
37+
local key = idx
38+
if type(idx) == 'string' then
39+
key = self.subviews[key]
40+
end
41+
idx = utils.linear_index(self.subviews, key)
42+
if not idx then
43+
error('Unknown page: '..tostring(key))
44+
end
45+
end
46+
47+
show_view(self.subviews[self.selected], false)
48+
self.selected = math.min(math.max(1, idx), #self.subviews)
49+
show_view(self.subviews[self.selected], true)
50+
end
51+
52+
---@return integer index
53+
---@return gui.View child
54+
function Pages:getSelected()
55+
return self.selected, self.subviews[self.selected]
56+
end
57+
58+
---@return gui.View child
59+
function Pages:getSelectedPage()
60+
return self.subviews[self.selected]
61+
end
62+
63+
return Pages

0 commit comments

Comments
 (0)