scrin 0.1.37

A terminal UI toolkit with panes, widgets, overlays, animations, and Aisling-powered effects/loaders.
Documentation
use crate::core::buffer::Buffer;
use crate::core::color::Color;
use crate::core::rect::Rect;
use crate::style::Style;
use crate::widgets::Widget;

#[derive(Debug, Clone)]
pub struct ListItem {
    pub content: String,
    pub style: Style,
}

impl ListItem {
    pub fn new(content: &str) -> Self {
        Self {
            content: content.to_string(),
            style: Style::new(),
        }
    }

    pub fn with_style(mut self, style: Style) -> Self {
        self.style = style;
        self
    }
}

#[derive(Debug, Clone)]
pub struct List<'a> {
    pub items: &'a [ListItem],
    pub selected: Option<usize>,
    pub highlight_style: Style,
    pub highlight_symbol: &'a str,
}

impl<'a> List<'a> {
    pub fn new(items: &'a [ListItem]) -> Self {
        Self {
            items,
            selected: None,
            highlight_style: Style::new().fg(Color::WHITE).bg(Color::rgb(31, 111, 235)),
            highlight_symbol: "",
        }
    }

    pub fn with_selected(mut self, selected: usize) -> Self {
        self.selected = Some(selected);
        self
    }

    pub fn with_highlight_style(mut self, style: Style) -> Self {
        self.highlight_style = style;
        self
    }
}

impl<'a> Widget for List<'a> {
    fn render(&self, buffer: &mut Buffer, area: Rect) {
        for (i, item) in self.items.iter().enumerate() {
            let y = area.y as usize + i;
            if y >= area.bottom() as usize {
                break;
            }
            let is_selected = self.selected == Some(i);
            let fg = if is_selected {
                self.highlight_style.fg_or_default()
            } else {
                item.style.fg_or_default()
            };
            let bg = if is_selected {
                self.highlight_style.bg
            } else {
                item.style.bg
            };

            if is_selected {
                let symbol_len = self.highlight_symbol.len();
                buffer.set_str(area.x as usize, y, self.highlight_symbol, fg, bg);
                buffer.set_str(area.x as usize + symbol_len, y, &item.content, fg, bg);
            } else {
                buffer.set_str(area.x as usize, y, &item.content, fg, bg);
            }
        }
    }
}