use ratatui::{prelude::*, style::palette::tailwind};
use tui_framework_experiment::{
button,
events::{self, *},
Button,
};
#[derive(Debug, Clone)]
pub struct ButtonsTab {
selected_index: usize,
buttons: Vec<Button<'static>>,
button_areas: Vec<Rect>,
}
impl Default for ButtonsTab {
fn default() -> Self {
Self {
selected_index: 0,
buttons: vec![
Button::new("Button 1").with_theme(button::themes::RED),
Button::new("Button 2").with_theme(button::themes::GREEN),
Button::new("Button 3").with_theme(button::themes::BLUE),
],
button_areas: vec![],
}
}
}
impl EventHandler for ButtonsTab {
fn handle_key(&mut self, event: KeyPressedEvent) {
use events::Key::*;
match event.key {
Char('j') | Left => self.select_previous(),
Char('k') | Right => self.select_next(),
_ => self.selected_button_mut().handle_key(event),
}
}
fn handle_mouse(&mut self, event: MouseEvent) {
match event.kind {
MouseEventKind::Down(MouseButton::Left) => self.click(event.column, event.row),
MouseEventKind::Up(_) => self.release(),
_ => {}
}
}
}
impl ButtonsTab {
pub fn selected_button_mut(&mut self) -> &mut Button<'static> {
&mut self.buttons[self.selected_index]
}
fn click(&mut self, column: u16, row: u16) {
for (i, area) in self.button_areas.iter().enumerate() {
let area_contains_click = area.left() <= column
&& column < area.right()
&& area.top() <= row
&& row < area.bottom();
if area_contains_click {
self.release();
self.buttons[i].toggle_press();
self.selected_index = i;
break;
}
}
}
fn release(&mut self) {
self.selected_button_mut().select();
}
pub fn select_next(&mut self) {
self.select_index((self.selected_index + 1) % self.buttons.len())
}
pub fn select_previous(&mut self) {
self.select_index((self.selected_index + self.buttons.len() - 1) % self.buttons.len());
}
pub fn select_index(&mut self, index: usize) {
self.selected_button_mut().normal();
self.selected_index = index % self.buttons.len();
self.selected_button_mut().select();
}
pub fn press(&mut self) {
self.buttons[self.selected_index].toggle_press();
}
}
impl Widget for &mut ButtonsTab {
fn render(self, area: Rect, buf: &mut Buffer) {
let layout = Layout::vertical([3, 0]);
let [buttons, instructions] = layout.areas(area);
let layout = Layout::horizontal([20, 1, 20, 1, 20, 0]);
let [left, _, middle, _, right, _] = layout.areas(buttons);
self.button_areas = vec![left, middle, right];
self.buttons[0].render(left, buf);
self.buttons[1].render(middle, buf);
self.buttons[2].render(right, buf);
Line::raw("←/→: select, space/mouse: press")
.style(tailwind::SLATE.c300)
.render(instructions, buf);
}
}