gm_lib/tui/app/widgets/
select.rs1use std::fmt::Display;
2
3use ratatui::{
4 layout::{Constraint, Layout},
5 style::Style,
6 text::Line,
7 widgets::{List, ListItem, Widget},
8};
9
10use crate::utils::cursor::Cursor;
11
12use super::scroll_bar::CustomScrollBar;
13
14pub struct Select<'a, T: Display> {
15 pub focus: bool,
16 pub list: &'a Vec<T>,
17 pub cursor: &'a Cursor,
18 pub focus_style: Style,
19}
20
21impl<T: Display> Widget for Select<'_, T> {
22 fn render(self, area: ratatui::prelude::Rect, buf: &mut ratatui::prelude::Buffer)
23 where
24 Self: Sized,
25 {
26 let capacity = area.height as usize;
27 let page_number = self.cursor.current / capacity;
28 let idx = self.cursor.current % capacity;
29
30 let render_item = |(i, member)| {
31 let content = Line::from(format!("{member}"));
32 let style = if idx == i && self.focus {
33 self.focus_style
34 } else {
35 Style::default()
36 };
37 ListItem::new(content).style(style)
38 };
39
40 if capacity < self.list.len() {
41 let display_items = self
42 .list
43 .chunks(capacity)
44 .nth(page_number)
45 .unwrap()
46 .iter()
47 .enumerate()
48 .map(render_item)
49 .collect::<Vec<ListItem>>();
50
51 let horizontal_layout = Layout::horizontal([Constraint::Min(3), Constraint::Length(1)]);
52 let [list_area, scroll_area] = horizontal_layout.areas(area);
53 List::new(display_items).render(list_area, buf);
54 CustomScrollBar {
55 cursor: self.cursor.current,
56 total: self.list.len(),
57 }
58 .render(scroll_area, buf);
59 } else {
60 let display_items = self
61 .list
62 .iter()
63 .enumerate()
64 .map(render_item)
65 .collect::<Vec<ListItem>>();
66 List::new(display_items).render(area, buf);
67 }
68 }
69}