use crate::{event::Event, layout::Rect, render::Frame, style::Style};
use crossterm::event::KeyCode;
pub struct ListItem {
text: String,
style: Style,
selected_style: Style,
}
impl ListItem {
pub fn new(text: &str) -> Self {
Self { text: text.to_string(), style: Style::new(), selected_style: Style::new().reversed() }
}
pub fn style(mut self, style: Style) -> Self {
self.style = style;
self
}
pub fn selected_style(mut self, style: Style) -> Self {
self.selected_style = style;
self
}
pub fn text(&self) -> &str {
&self.text
}
pub fn get_style(&self) -> &Style {
&self.style
}
pub fn get_selected_style(&self) -> &Style {
&self.selected_style
}
}
pub struct List {
items: Vec<ListItem>,
selected: usize,
style: Style,
on_select: Option<Box<dyn Fn(usize)>>,
}
impl List {
pub fn new(items: Vec<ListItem>) -> Self {
Self { items, selected: 0, style: Style::new(), on_select: None }
}
pub fn style(mut self, style: Style) -> Self {
self.style = style;
self
}
pub fn on_select<F: Fn(usize) + 'static>(mut self, f: F) -> Self {
self.on_select = Some(Box::new(f));
self
}
pub fn get_selected(&self) -> usize {
self.selected
}
pub fn set_selected(&mut self, index: usize) {
if index < self.items.len() {
self.selected = index;
if let Some(callback) = &self.on_select {
callback(self.selected);
}
}
}
fn handle_key(&mut self, key: KeyCode) {
match key {
KeyCode::Up => {
if self.selected > 0 {
self.selected -= 1;
if let Some(callback) = &self.on_select {
callback(self.selected);
}
}
}
KeyCode::Down => {
if self.selected < self.items.len() - 1 {
self.selected += 1;
if let Some(callback) = &self.on_select {
callback(self.selected);
}
}
}
KeyCode::Home => {
self.selected = 0;
if let Some(callback) = &self.on_select {
callback(self.selected);
}
}
KeyCode::End => {
self.selected = self.items.len().saturating_sub(1);
if let Some(callback) = &self.on_select {
callback(self.selected);
}
}
_ => {}
}
}
}
impl super::Component for List {
fn render(&self, frame: &mut Frame, area: Rect) {
frame.render_list(&self.items, self.selected, area, self.style.clone());
}
fn handle_event(&mut self, event: &Event) -> bool {
match event {
Event::Key(key_event) => {
self.handle_key(key_event.code);
true
}
_ => false,
}
}
}