Skip to main content

promkit_widgets/
checkbox.rs

1use promkit_core::{Pane, PaneFactory, grapheme::StyledGraphemes};
2
3#[path = "checkbox/checkbox.rs"]
4mod inner;
5pub use inner::Checkbox;
6pub mod config;
7pub use config::Config;
8
9/// Represents the state of a `Checkbox` component.
10///
11/// This state includes not only the checkbox itself but also various attributes
12/// that determine how the checkbox and its items are displayed. These attributes
13/// include symbols for indicating active and inactive items, styles for selected
14/// and unselected lines, and the number of lines available for rendering.
15#[derive(Clone)]
16pub struct State {
17    /// The `Checkbox` component to be rendered.
18    pub checkbox: Checkbox,
19
20    /// Configuration for rendering and behavior.
21    pub config: Config,
22}
23
24impl PaneFactory for State {
25    fn create_pane(&self, width: u16, height: u16) -> Pane {
26        let f = |idx: usize| -> StyledGraphemes {
27            if self.checkbox.picked_indexes().contains(&idx) {
28                StyledGraphemes::from(format!("{} ", self.config.active_mark))
29            } else {
30                StyledGraphemes::from(format!("{} ", self.config.inactive_mark))
31            }
32        };
33
34        let height = match self.config.lines {
35            Some(lines) => lines.min(height as usize),
36            None => height as usize,
37        };
38
39        let matrix = self
40            .checkbox
41            .items()
42            .iter()
43            .enumerate()
44            .filter(|(i, _)| {
45                *i >= self.checkbox.position() && *i < self.checkbox.position() + height
46            })
47            .map(|(i, item)| {
48                if i == self.checkbox.position() {
49                    StyledGraphemes::from_iter([
50                        &StyledGraphemes::from(&self.config.cursor),
51                        &f(i),
52                        item,
53                    ])
54                    .apply_style(self.config.active_item_style)
55                } else {
56                    StyledGraphemes::from_iter([
57                        &StyledGraphemes::from(
58                            " ".repeat(StyledGraphemes::from(&self.config.cursor).widths()),
59                        ),
60                        &f(i),
61                        item,
62                    ])
63                    .apply_style(self.config.inactive_item_style)
64                }
65            })
66            .fold((vec![], 0), |(mut acc, pos), item| {
67                let rows = item.matrixify(width as usize, height, 0).0;
68                if pos < self.checkbox.position() + height {
69                    acc.extend(rows);
70                }
71                (acc, pos + 1)
72            });
73
74        Pane::new(matrix.0, 0)
75    }
76}