Skip to main content

teksilo_data/
check_state.rs

1// SPDX-License-Identifier: MPL-2.0
2// SPDX-FileCopyrightText: 2026 FernTech
3
4//! `CheckState` — tri-state checkbox value shared by the data layer and widgets.
5//!
6//! Represents the three visual states of a checkbox: unchecked, checked, and
7//! indeterminate (partial — some but not all descendants are checked). Lives in
8//! `teksilo-data` rather than `teksilo-widgets` so that [`crate::TreeCheckedModel`]
9//! can produce `Signal<CheckState>` values without inverting the dependency graph.
10//!
11//! `From<bool>` converts a plain two-state boolean (e.g. from a filter predicate)
12//! into `Unchecked` or `Checked`, making it easy to bridge non-tristate sources.
13//!
14//! ```rust
15//! # use teksilo_data::CheckState;
16//! let state = CheckState::Indeterminate;
17//! assert!(state.is_filled());
18//! assert_eq!(state.next_tristate(), CheckState::Unchecked);
19//! assert_eq!(CheckState::from(true), CheckState::Checked);
20//! ```
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
23pub enum CheckState {
24    /// The checkbox is unchecked (no fill, no mark).
25    Unchecked,
26    /// The checkbox is fully checked (filled with a check mark).
27    Checked,
28    /// Some but not all descendants are checked; shown as a dash or partial fill.
29    Indeterminate,
30}
31
32impl CheckState {
33    /// Whether the box shows a filled background (checked or indeterminate).
34    pub fn is_filled(self) -> bool {
35        self != CheckState::Unchecked
36    }
37
38    /// Cycle to the next state: Unchecked → Checked → Indeterminate → Unchecked.
39    pub fn next_tristate(self) -> Self {
40        match self {
41            CheckState::Unchecked => CheckState::Checked,
42            CheckState::Checked => CheckState::Indeterminate,
43            CheckState::Indeterminate => CheckState::Unchecked,
44        }
45    }
46}
47
48impl From<bool> for CheckState {
49    fn from(checked: bool) -> Self {
50        if checked {
51            CheckState::Checked
52        } else {
53            CheckState::Unchecked
54        }
55    }
56}