Skip to main content

promkit_widgets/listbox/
listbox.rs

1use std::fmt;
2
3use promkit_core::grapheme::StyledGraphemes;
4
5use crate::cursor::Cursor;
6
7/// A `Listbox` struct that encapsulates a list of strings,
8/// allowing for navigation and manipulation through a cursor.
9/// It supports basic operations
10/// such as moving the cursor forward and backward,
11/// retrieving the current item,
12/// and initializing from an iterator of displayable items.
13#[derive(Clone)]
14pub struct Listbox(Cursor<Vec<StyledGraphemes>>);
15
16impl Default for Listbox {
17    fn default() -> Self {
18        Self(Cursor::new(vec![StyledGraphemes::default()], 0, false))
19    }
20}
21
22impl<E: fmt::Display, I: IntoIterator<Item = E>> From<I> for Listbox {
23    fn from(items: I) -> Self {
24        Self(Cursor::new(
25            items
26                .into_iter()
27                .map(|e| StyledGraphemes::from(format!("{}", e)))
28                .collect(),
29            0,
30            false,
31        ))
32    }
33}
34
35impl Listbox {
36    pub fn len(&self) -> usize {
37        self.0.contents().len()
38    }
39
40    pub fn is_empty(&self) -> bool {
41        self.0.contents().is_empty()
42    }
43
44    pub fn push_string(&mut self, item: String) {
45        self.0.contents_mut().push(StyledGraphemes::from(item));
46    }
47
48    /// Creates a new `Listbox` from a vector of `StyledGraphemes`.
49    pub fn from_styled_graphemes(items: Vec<StyledGraphemes>) -> Self {
50        Self(Cursor::new(items, 0, false))
51    }
52
53    /// Returns a reference to the vector of items in the listbox.
54    pub fn items(&self) -> &Vec<StyledGraphemes> {
55        self.0.contents()
56    }
57
58    /// Returns the current position of the cursor within the listbox.
59    pub fn position(&self) -> usize {
60        self.0.position()
61    }
62
63    /// Retrieves the item at the current cursor position as a `String`.
64    /// If the cursor is at a position without an item,
65    /// returns an empty `String`.
66    pub fn get(&self) -> StyledGraphemes {
67        self.items()
68            .get(self.position())
69            .unwrap_or(&StyledGraphemes::default())
70            .clone()
71    }
72
73    /// Moves the cursor backward in the listbox, if possible.
74    /// Returns `true` if the cursor was successfully moved backward, `false` otherwise.
75    pub fn backward(&mut self) -> bool {
76        self.0.backward()
77    }
78
79    /// Moves the cursor forward in the listbox, if possible.
80    /// Returns `true` if the cursor was successfully moved forward, `false` otherwise.
81    pub fn forward(&mut self) -> bool {
82        self.0.forward()
83    }
84
85    /// Moves the cursor to the head (beginning) of the listbox.
86    pub fn move_to_head(&mut self) {
87        self.0.move_to_head()
88    }
89
90    /// Moves the cursor to the tail of the listbox.
91    pub fn move_to_tail(&mut self) {
92        self.0.move_to_tail()
93    }
94
95    pub fn is_tail(&self) -> bool {
96        self.0.is_tail()
97    }
98}