Skip to content
Open
Changes from all commits
Commits
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
69 changes: 49 additions & 20 deletions src/tui.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,11 +259,32 @@ pub enum Overflow {
TruncateTail,
}

/// If specified, a checkmark 🗹 / ☐ to be prepended to the button text
#[derive(Default, Clone, Copy, PartialEq, Eq)]
enum Checkmark {
/// No checkmark (or space for it)
#[default]
Absent,
/// Add whitespace where a checkmark would be
/// (to keep aligned with checkmark'd buttons)
AlignOnly,
/// Add a 🗹 prefix
Checked,
/// Add a ☐ prefix
Unchecked,
}

impl From<bool> for Checkmark {
fn from(checked: bool) -> Self {
if checked { Checkmark::Checked } else { Checkmark::Unchecked }
}
}

/// Controls the style with which a button label renders
#[derive(Clone, Copy)]
pub struct ButtonStyle {
accelerator: Option<char>,
checked: Option<bool>,
checkmark: Checkmark,
bracketed: bool,
}

Expand All @@ -274,21 +295,23 @@ impl ButtonStyle {
pub fn accelerator(self, char: char) -> Self {
Self { accelerator: Some(char), ..self }
}
/// Draw a checkbox prefix: `[🗹 Example Button]`
pub fn checked(self, checked: bool) -> Self {
Self { checked: Some(checked), ..self }
}
/// Draw with or without brackets: `[Example Button]` or `Example Button`
pub fn bracketed(self, bracketed: bool) -> Self {
Self { bracketed, ..self }
}
/// Draw a checkbox prefix: `[🗹 Example Button]`
///
/// Note: use `checkbox` or `menubar_menu_checkbox`
fn checkmark(self, checkmark: Checkmark) -> Self {
Self { checkmark, ..self }
}
}

impl Default for ButtonStyle {
fn default() -> Self {
Self {
accelerator: None,
checked: None,
checkmark: Checkmark::Absent,
bracketed: true, // Default style for most buttons. Brackets may be disabled e.g. for buttons in menus
}
}
Expand Down Expand Up @@ -2004,17 +2027,9 @@ impl<'a> Context<'a, '_> {
/// Creates a checkbox with the given text.
/// Returns true if the checkbox was activated.
pub fn checkbox(&mut self, classname: &'static str, text: &str, checked: &mut bool) -> bool {
self.styled_label_begin(classname);
self.attr_focusable();
if self.is_focused() {
self.attr_reverse();
}
self.styled_label_add_text(if *checked { "[🗹 " } else { "[☐ " });
self.styled_label_add_text(text);
self.styled_label_add_text("]");
self.styled_label_end();
let activated =
self.button(classname, text, ButtonStyle::default().checkmark((*checked).into()));

let activated = self.button_activated();
if activated {
*checked = !*checked;
}
Expand Down Expand Up @@ -3142,7 +3157,7 @@ impl<'a> Context<'a, '_> {
accelerator: char,
shortcut: InputKey,
) -> bool {
self.menubar_menu_checkbox(text, accelerator, shortcut, false)
self.menubar_menu_item(text, accelerator, shortcut, Checkmark::AlignOnly)
}

/// Appends a checkbox to the current menu.
Expand All @@ -3153,6 +3168,17 @@ impl<'a> Context<'a, '_> {
accelerator: char,
shortcut: InputKey,
checked: bool,
) -> bool {
self.menubar_menu_item(text, accelerator, shortcut, checked.into())
}

/// Appends a button or checkbox to the current menu,
fn menubar_menu_item(
&mut self,
text: &str,
accelerator: char,
shortcut: InputKey,
checkmark: Checkmark,
) -> bool {
self.table_next_row();
self.attr_focusable();
Expand All @@ -3173,7 +3199,7 @@ impl<'a> Context<'a, '_> {
self.button_label(
"menu_checkbox",
text,
ButtonStyle::default().bracketed(false).checked(checked).accelerator(accelerator),
ButtonStyle::default().bracketed(false).checkmark(checkmark).accelerator(accelerator),
);
self.menubar_shortcut(shortcut);

Expand Down Expand Up @@ -3227,8 +3253,11 @@ impl<'a> Context<'a, '_> {
if style.bracketed {
self.styled_label_add_text("[");
}
if let Some(checked) = style.checked {
self.styled_label_add_text(if checked { "🗹 " } else { " " });
match style.checkmark {
Checkmark::Absent => {}
Checkmark::AlignOnly => self.styled_label_add_text(" "),
Checkmark::Checked => self.styled_label_add_text("🗹 "),
Checkmark::Unchecked => self.styled_label_add_text("☐ "),
}
// Label text
match style.accelerator {
Expand Down