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);
}
}
}
}