use crossterm::event::{KeyCode, KeyEvent, MouseEvent};
use crate::widget::Widget;
use ratatui::{
layout::Rect,
style::{Color, Modifier, Style},
text::Line,
widgets::{Block, BorderType, Borders, Tabs as T},
Frame,
};
#[derive(Debug, Clone)]
pub enum ViewMode {
Overview,
Logs,
Metrics,
Alerts,
Performance,
Network,
}
impl ViewMode {
fn as_str(&self) -> &str {
match self {
ViewMode::Overview => "Overview",
ViewMode::Logs => "Logs",
ViewMode::Metrics => "Metrics",
ViewMode::Alerts => "Alerts",
ViewMode::Performance => "Performance",
ViewMode::Network => "Network",
}
}
}
pub struct ListWidget {
pub id: u8,
pub title: &'static str,
pub items: [ViewMode; 2],
pub selected: usize,
pub area: Option<Rect>,
pub focused: bool,
}
impl ListWidget {
pub fn new() -> Self {
Self {
id: 0,
title: "~ Menu ~",
items: [ViewMode::Overview, ViewMode::Logs],
selected: 0,
area: None,
focused: false,
}
}
}
impl Widget for ListWidget {
fn render(&mut self, f: &mut Frame<'_>, area: Rect) {
let tab_titles: Vec<Line> = self
.items
.iter()
.map(|t| Line::from(format!(" {} ", t.as_str())))
.collect();
let base_style = Style::default().fg(Color::DarkGray);
let highlight_style = if self.focused {
Style::default()
.fg(Color::Black)
.bg(Color::Blue) .add_modifier(Modifier::BOLD)
} else {
Style::default()
.fg(Color::White)
.bg(Color::DarkGray) .add_modifier(Modifier::BOLD)
};
let block = Block::default()
.borders(Borders::ALL)
.title(self.title)
.border_type(BorderType::Rounded)
.border_style(if self.focused {
Style::default().fg(Color::Cyan)
} else {
Style::default().fg(Color::White)
});
let tabs = T::new(tab_titles)
.block(block)
.select(self.selected)
.style(base_style)
.highlight_style(highlight_style);
f.render_widget(tabs, area);
}
fn on_key(&mut self, key: KeyEvent) {
if !self.focused {
return;
}
match key.code {
KeyCode::Char('l') => {
self.selected = (self.selected + 1) % self.items.len();
},
KeyCode::Char('h') => {
self.selected = (self.selected + self.items.len() - 1) % self.items.len();
},
_ => {},
}
}
fn on_mouse(&mut self, me: MouseEvent) {
use crossterm::event::MouseEventKind;
if let Some(area) = self.area {
if let MouseEventKind::Down(_) = me.kind {
if me.row == area.top() {
let mut x = area.left() + 1; for (i, item) in self.items.iter().enumerate() {
let tab_width = item.as_str().len() as u16 + 2;
if me.column >= x && me.column < x + tab_width {
self.selected = i;
break;
}
x += tab_width;
}
}
}
}
}
}