gm-tui 0.0.1

TUI-based Ethereum wallet
Documentation
use std::fmt::Display;

use ratatui::{
    layout::{Constraint, Layout},
    style::Style,
    text::Line,
    widgets::{List, ListItem, Widget},
};

use crate::utils::cursor::Cursor;

use super::scroll_bar::CustomScrollBar;

pub struct Select<'a, T: Display> {
    pub focus: bool,
    pub list: &'a Vec<T>,
    pub cursor: &'a Cursor,
    pub focus_style: Style,
}

impl<T: Display> Widget for Select<'_, T> {
    fn render(self, area: ratatui::prelude::Rect, buf: &mut ratatui::prelude::Buffer)
    where
        Self: Sized,
    {
        let capacity = area.height as usize;
        let page_number = self.cursor.current / capacity;
        let idx = self.cursor.current % capacity;

        let render_item = |(i, member)| {
            let content = Line::from(format!("{member}"));
            let style = if idx == i && self.focus {
                self.focus_style
            } else {
                Style::default()
            };
            ListItem::new(content).style(style)
        };

        if capacity < self.list.len() {
            let display_items = self
                .list
                .chunks(capacity)
                .nth(page_number)
                .unwrap()
                .iter()
                .enumerate()
                .map(render_item)
                .collect::<Vec<ListItem>>();

            let horizontal_layout = Layout::horizontal([Constraint::Min(3), Constraint::Length(1)]);
            let [list_area, scroll_area] = horizontal_layout.areas(area);
            List::new(display_items).render(list_area, buf);
            CustomScrollBar {
                cursor: self.cursor.current,
                total: self.list.len(),
            }
            .render(scroll_area, buf);
        } else {
            let display_items = self
                .list
                .iter()
                .enumerate()
                .map(render_item)
                .collect::<Vec<ListItem>>();
            List::new(display_items).render(area, buf);
        }
    }
}