toggleable.rs

 1/// A trait for elements that can be toggled.
 2///
 3/// Implement this for elements that are visually distinct
 4/// when in two opposing states, like checkboxes or switches.
 5pub trait Toggleable {
 6    /// Sets whether the element is selected.
 7    fn toggle_state(self, selected: bool) -> Self;
 8}
 9
10/// Represents the selection status of an element.
11#[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Copy)]
12pub enum ToggleState {
13    /// The element is not selected.
14    #[default]
15    Unselected,
16    /// The selection state of the element is indeterminate.
17    Indeterminate,
18    /// The element is selected.
19    Selected,
20}
21
22impl ToggleState {
23    /// Returns the inverse of the current selection status.
24    ///
25    /// Indeterminate states become selected if inverted.
26    pub const fn inverse(&self) -> Self {
27        match self {
28            Self::Unselected | Self::Indeterminate => Self::Selected,
29            Self::Selected => Self::Unselected,
30        }
31    }
32
33    /// Creates a `ToggleState` from the given `any_checked` and `all_checked` flags.
34    pub const fn from_any_and_all(any_checked: bool, all_checked: bool) -> Self {
35        match (any_checked, all_checked) {
36            (true, true) => Self::Selected,
37            (false, false) => Self::Unselected,
38            _ => Self::Indeterminate,
39        }
40    }
41
42    /// Returns whether this toggle state is selected
43    pub const fn selected(&self) -> bool {
44        match self {
45            ToggleState::Indeterminate | ToggleState::Unselected => false,
46            ToggleState::Selected => true,
47        }
48    }
49}
50
51impl From<bool> for ToggleState {
52    fn from(selected: bool) -> Self {
53        if selected {
54            Self::Selected
55        } else {
56            Self::Unselected
57        }
58    }
59}
60
61impl From<Option<bool>> for ToggleState {
62    fn from(selected: Option<bool>) -> Self {
63        match selected {
64            Some(true) => Self::Selected,
65            Some(false) => Self::Unselected,
66            None => Self::Indeterminate,
67        }
68    }
69}