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}