Skip to content
Merged
1 change: 1 addition & 0 deletions docs/changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ Template for new versions:
## Documentation

## API
- ``widgets.RadioButton``: New button widget resembling those used in ``gui/control-panel``

## Lua

Expand Down
33 changes: 25 additions & 8 deletions docs/dev/Lua API.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6356,12 +6356,27 @@ This is a specialized subclass of CycleHotkeyLabel that has two options:
``On`` (with a value of ``true``) and ``Off`` (with a value of ``false``). The
``On`` option is rendered in green.

ConfigureButton class
---------------------

A 3x1 tile button with a gear symbol on it, intended to represent a configure
icon. Clicking on the icon will run the given callback. The graphics can also
be overridden to create custom buttons.

It has the following attributes:

:on_click: The function to run when the icon is clicked.
:pen_left: Pen or function returning a pen to overwrite the left tile of the button.
:pen_center: As above, but for the center tile (gear symbol).
:pen_right: As above, but for the right tile.

HelpButton class
----------------

A 3x1 tile button with a question mark on it, intended to represent a help
icon. Clicking on the icon will launch `gui/launcher` with a given command
string, showing the help text for that command.
Subclass of ConfigureButton; a 3x1 tile button with a question mark on it,
intended to represent a help icon. Clicking on the icon will launch
`gui/launcher` with a given command string, showing the help text for that
command.

It has the following attributes:

Expand All @@ -6371,15 +6386,17 @@ It also sets the ``frame`` attribute so the button appears in the upper right
corner of the parent, but you can override this to your liking if you want a
different position.

ConfigureButton class
---------------------
RadioButton class
-----------------

A 3x1 tile button with a gear mark on it, intended to represent a configure
icon. Clicking on the icon will run the given callback.
Subclass of ConfigureButton; a 3x1 tile button that resembles a radio button
(or check box in ASCII mode), identical to the ones found in
`gui/control-panel`. Clicking on the button will toggle its enabled state.
This state is represented by the boolean value ``toggle_state``.

It has the following attributes:

:on_click: The function on run when the icon is clicked.
:initial_state: Start in the ``true`` or ``false`` state. Defaults to ``true``.

BannerPanel class
-----------------
Expand Down
3 changes: 2 additions & 1 deletion library/lua/gui/widgets.lua
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ Label = require('gui.widgets.labels.label')
Scrollbar = require('gui.widgets.scrollbar')
WrappedLabel = require('gui.widgets.labels.wrapped_label')
TooltipLabel = require('gui.widgets.labels.tooltip_label')
HelpButton = require('gui.widgets.buttons.help_button')
ConfigureButton = require('gui.widgets.buttons.configure_button')
HelpButton = require('gui.widgets.buttons.help_button')
RadioButton = require('gui.widgets.buttons.radio_button')
BannerPanel = require('gui.widgets.containers.banner_panel')
TextButton = require('gui.widgets.buttons.text_button')
CycleHotkeyLabel = require('gui.widgets.labels.cycle_hotkey_label')
Expand Down
40 changes: 29 additions & 11 deletions library/lua/gui/widgets/buttons/configure_button.lua
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
-- A 3x1 tile button with a gear symbol on it. Clicking on it will run a callback

local textures = require('gui.textures')
local Panel = require('gui.widgets.containers.panel')
local Label = require('gui.widgets.labels.label')
Expand All @@ -6,17 +8,20 @@ local to_pen = dfhack.pen.parse

local button_pen_left = to_pen{fg=COLOR_CYAN,
tile=curry(textures.tp_control_panel, 7) or nil, ch=string.byte('[')}
local button_pen_center = to_pen{
tile=curry(textures.tp_control_panel, 10) or nil, ch=15} -- gear/masterwork symbol
local button_pen_right = to_pen{fg=COLOR_CYAN,
tile=curry(textures.tp_control_panel, 8) or nil, ch=string.byte(']')}
local configure_pen_center = to_pen{
tile=curry(textures.tp_control_panel, 10) or nil, ch=15} -- gear/masterwork symbol

---------------------
Comment thread
Bumber64 marked this conversation as resolved.
-- ConfigureButton --
---------------------

---@class widgets.ConfigureButton.attrs: widgets.Panel.attrs
---@field on_click? function
---@field pen_left dfhack.pen|fun(): dfhack.pen
---@field pen_center dfhack.pen|fun(): dfhack.pen
---@field pen_right dfhack.pen|fun(): dfhack.pen

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

Expand All @@ -27,27 +32,40 @@ local configure_pen_center = to_pen{
ConfigureButton = defclass(ConfigureButton, Panel)

ConfigureButton.ATTRS{
frame={t=0, l=0, w=3, h=1},
on_click=DEFAULT_NIL,
pen_left=button_pen_left,
pen_center=button_pen_center,
pen_right=button_pen_right,
Comment thread
Bumber64 marked this conversation as resolved.
}

function ConfigureButton:preinit(init_table)
init_table.frame = init_table.frame or {}
init_table.frame.h = init_table.frame.h or 1
init_table.frame.w = init_table.frame.w or 3
end

function ConfigureButton:init()
self.frame.h = self.frame.h or 1
self.frame.w = self.frame.w or 3

self:addviews{
Label{
view_id='label',
frame={t=0, l=0, w=3, h=1},
text={
{tile=button_pen_left},
{tile=configure_pen_center},
{tile=button_pen_right},
{tile=self.pen_left},
{tile=self.pen_center},
{tile=self.pen_right},
},
on_click=self.on_click,
},
}
end

function ConfigureButton:postinit()
local l = self.subviews.label

l.on_click = self.on_click
l.pen_left = self.pen_left
l.pen_center = self.pen_center
l.pen_right = self.pen_right

l:setText({{tile=self.pen_left}, {tile=self.pen_center}, {tile=self.pen_right}})
end

return ConfigureButton
40 changes: 11 additions & 29 deletions library/lua/gui/widgets/buttons/help_button.lua
Original file line number Diff line number Diff line change
@@ -1,53 +1,35 @@
-- A 3x1 tile button with a question mark on it. Clicking on it will show help text for a command

local textures = require('gui.textures')
local Panel = require('gui.widgets.containers.panel')
local Label = require('gui.widgets.labels.label')
local ConfigureButton = require('gui.widgets.buttons.configure_button')

local to_pen = dfhack.pen.parse
local help_pen_center = dfhack.pen.parse{
tile=curry(textures.tp_control_panel, 9) or nil, ch=string.byte('?')}

----------------
-- HelpButton --
----------------

---@class widgets.HelpButton.attrs: widgets.Panel.attrs
---@class widgets.HelpButton.attrs: widgets.ConfigureButton.attrs
---@field command? string

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

---@class widgets.HelpButton: widgets.Panel, widgets.HelpButton.attrs
---@field super widgets.Panel
---@class widgets.HelpButton: widgets.ConfigureButton, widgets.HelpButton.attrs
---@field super widgets.ConfigureButton
---@field ATTRS widgets.HelpButton.attrs|fun(attributes: widgets.HelpButton.attrs.partial)
---@overload fun(init_table: widgets.HelpButton.attrs.partial): self
HelpButton = defclass(HelpButton, Panel)
HelpButton = defclass(HelpButton, ConfigureButton)
Comment thread
Bumber64 marked this conversation as resolved.

HelpButton.ATTRS{
frame={t=0, r=1, w=3, h=1},
command=DEFAULT_NIL,
pen_center=help_pen_center,
Comment thread
Bumber64 marked this conversation as resolved.
}

local button_pen_left = to_pen{fg=COLOR_CYAN,
tile=curry(textures.tp_control_panel, 7) or nil, ch=string.byte('[')}
local button_pen_right = to_pen{fg=COLOR_CYAN,
tile=curry(textures.tp_control_panel, 8) or nil, ch=string.byte(']')}
local help_pen_center = to_pen{
tile=curry(textures.tp_control_panel, 9) or nil, ch=string.byte('?')}

function HelpButton:init()
self.frame.w = self.frame.w or 3
self.frame.h = self.frame.h or 1

local command = self.command .. ' '

self:addviews{
Label{
frame={t=0, l=0, w=3, h=1},
text={
{tile=button_pen_left},
{tile=help_pen_center},
{tile=button_pen_right},
},
on_click=function() dfhack.run_command('gui/launcher', command) end,
},
}
self.on_click = function() dfhack.run_command('gui/launcher', command) end
Comment thread
Bumber64 marked this conversation as resolved.
end

return HelpButton
49 changes: 49 additions & 0 deletions library/lua/gui/widgets/buttons/radio_button.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
-- A 3x1 tile button that toggles state when clicked

local textures = require('gui.textures')
local ConfigureButton = require('gui.widgets.buttons.configure_button')

local to_pen = dfhack.pen.parse

local enabled_pen_left = to_pen{fg=COLOR_CYAN,
tile=curry(textures.tp_control_panel, 1), ch=string.byte('[')}
Comment thread
Bumber64 marked this conversation as resolved.
local enabled_pen_center = to_pen{fg=COLOR_LIGHTGREEN,
tile=curry(textures.tp_control_panel, 2) or nil, ch=251} -- check
local enabled_pen_right = to_pen{fg=COLOR_CYAN,
tile=curry(textures.tp_control_panel, 3) or nil, ch=string.byte(']')}
local disabled_pen_left = to_pen{fg=COLOR_CYAN,
tile=curry(textures.tp_control_panel, 4) or nil, ch=string.byte('[')}
local disabled_pen_center = to_pen{fg=COLOR_RED,
tile=curry(textures.tp_control_panel, 5) or nil, ch=string.byte('x')}
local disabled_pen_right = to_pen{fg=COLOR_CYAN,
tile=curry(textures.tp_control_panel, 6) or nil, ch=string.byte(']')}

-----------------
-- RadioButton --
-----------------

---@class widgets.RadioButton.attrs: widgets.ConfigureButton.attrs
---@field initial_state boolean

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

---@class widgets.RadioButton: widgets.ConfigureButton, widgets.RadioButton.attrs
---@field super widgets.ConfigureButton
---@field ATTRS widgets.RadioButton.attrs|fun(attributes: widgets.RadioButton.attrs.partial)
---@overload fun(init_table: widgets.RadioButton.attrs.partial): self
RadioButton = defclass(RadioButton, ConfigureButton)

RadioButton.ATTRS{
initial_state=true,
}

function RadioButton:init()
self.toggle_state = self.initial_state

self.on_click = function() self.toggle_state = not self.toggle_state end
self.pen_left = function() return self.toggle_state and enabled_pen_left or disabled_pen_left end
self.pen_center = function() return self.toggle_state and enabled_pen_center or disabled_pen_center end
self.pen_right = function() return self.toggle_state and enabled_pen_right or disabled_pen_right end
end

Comment thread
SilasD marked this conversation as resolved.
return RadioButton
Loading