use std::sync::{atomic::{AtomicUsize, Ordering}, Arc}; use color_eyre::Result; use ratatui::{prelude::*, widgets::*}; use tokio::sync::mpsc::UnboundedSender; use super::Component; use crate::{action::Action, config::Config}; #[derive(Default)] pub struct Tabs { command_tx: Option>, config: Config, tabs: Vec<&'static str>, selected_tab: Arc, } impl Tabs { pub fn new(tabs: Vec<&'static str>, selected_tab: Arc) -> Self { Self { tabs, selected_tab, ..Default::default() } } pub fn next(&mut self) { if self.selected_tab.load(Ordering::Relaxed) < self.tabs.len() - 1 { self.selected_tab.fetch_add(1, Ordering::Relaxed); } } pub fn previous(&mut self) { if self.selected_tab.load(Ordering::Relaxed) > 0 { self.selected_tab.fetch_sub(1, Ordering::Relaxed); } } pub fn current_tab(&self) -> usize { self.selected_tab.load(Ordering::Relaxed) } } impl Component for Tabs { fn register_action_handler(&mut self, tx: UnboundedSender) -> Result<()> { self.command_tx = Some(tx); Ok(()) } fn register_config_handler(&mut self, config: Config) -> Result<()> { self.config = config; Ok(()) } fn update(&mut self, action: Action) -> Result> { match action { Action::Tick => {} Action::Render => {} Action::NextTab => self.next(), Action::PrevTab => self.previous(), _ => {} }; Ok(None) } fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> { let mut tab_lines = vec![Line::default(), Line::default()]; for (i, &tab) in self.tabs.iter().enumerate() { let style = if self.selected_tab.load(Ordering::Relaxed) == i { Style::default() .fg(Color::Magenta) .add_modifier(Modifier::BOLD) } else { Style::default().fg(Color::White) }; tab_lines[0].spans.push(Span::styled( format!("╭{}╮", "─".repeat(tab.len() + 2)), Style::default().fg(Color::DarkGray), )); tab_lines[1] .spans .push(Span::styled("│", Style::default().fg(Color::DarkGray))); tab_lines[1] .spans .push(Span::styled(format!(" {} ", tab), style)); tab_lines[1] .spans .push(Span::styled("│", Style::default().fg(Color::DarkGray))); } let tabs_widget = Paragraph::new(tab_lines).block(Block::default().borders(Borders::NONE)); frame.render_widget( tabs_widget, Rect { x: area.x, y: area.y, width: area.width, height: 2, }, ); Ok(()) }}