promkit_widgets/
listbox.rs1use promkit_core::{Pane, PaneFactory, grapheme::StyledGraphemes};
2
3#[path = "listbox/listbox.rs"]
4mod inner;
5pub use inner::Listbox;
6pub mod config;
7pub use config::Config;
8
9#[derive(Clone)]
13pub struct State {
14 pub listbox: Listbox,
16 pub config: Config,
18}
19
20impl PaneFactory for State {
21 fn create_pane(&self, width: u16, height: u16) -> Pane {
22 let height = match self.config.lines {
23 Some(lines) => lines.min(height as usize),
24 None => height as usize,
25 };
26
27 let matrix = self
28 .listbox
29 .items()
30 .iter()
31 .enumerate()
32 .filter(|(i, _)| *i >= self.listbox.position() && *i < self.listbox.position() + height)
33 .map(|(i, item)| {
34 if i == self.listbox.position() {
35 let init = StyledGraphemes::from_iter([
36 &StyledGraphemes::from(&self.config.cursor),
37 item,
38 ]);
39 if let Some(style) = &self.config.active_item_style {
40 init.apply_style(*style)
41 } else {
42 init
43 }
44 } else {
45 let init = StyledGraphemes::from_iter([
46 &StyledGraphemes::from(
47 " ".repeat(StyledGraphemes::from(&self.config.cursor).widths()),
48 ),
49 item,
50 ]);
51 if let Some(style) = &self.config.inactive_item_style {
52 init.apply_style(*style)
53 } else {
54 init
55 }
56 }
57 })
58 .fold((vec![], 0), |(mut acc, pos), item| {
59 let rows = item.matrixify(width as usize, height, 0).0;
60 if pos < self.listbox.position() + height {
61 acc.extend(rows);
62 }
63 (acc, pos + 1)
64 });
65
66 Pane::new(matrix.0, 0)
67 }
68}