clide/src/tui/title_bar.rs

112 lines
3.2 KiB
Rust
Raw Normal View History

use crate::tui::component::{Action, Component, ComponentState};
use ratatui::buffer::Buffer;
use ratatui::crossterm::event::{KeyCode, KeyEvent};
use ratatui::layout::Rect;
use ratatui::style::{Color, Style};
use ratatui::text::Line;
use ratatui::widgets::{Block, Borders, Tabs, Widget};
use strum::{EnumIter, FromRepr, IntoEnumIterator};
#[derive(Debug, Clone, Copy, PartialEq, Eq, FromRepr, EnumIter)]
enum TitleBarItem {
File,
Edit,
View,
Help,
}
impl TitleBarItem {
pub fn next(mut self) -> Self {
let cur = self as usize;
let next = cur.saturating_add(1);
Self::from_repr(next).unwrap_or(self)
}
pub fn prev(self) -> Self {
let cur = self as usize;
let prev = cur.saturating_sub(1);
Self::from_repr(prev).unwrap_or(self)
}
pub fn id(&self) -> &str {
match self {
TitleBarItem::File => "File",
TitleBarItem::Edit => "Edit",
TitleBarItem::View => "View",
TitleBarItem::Help => "Help",
}
}
}
pub struct TitleBar {
selected: TitleBarItem,
opened: Option<TitleBarItem>,
pub(crate) component_state: ComponentState,
}
impl TitleBar {
pub fn new() -> Self {
Self {
selected: TitleBarItem::File,
opened: None,
component_state: ComponentState::default()
.with_help_text(concat!("TODO: Title bar help text.").as_ref()),
}
}
fn render_title_bar(&self, area: Rect, buf: &mut Buffer) {
let titles: Vec<Line> = TitleBarItem::iter()
.map(|item| Line::from(item.id().to_owned()))
.collect();
let tabs_style = Style::default();
let highlight_style = if self.opened.is_some() {
Style::default().bg(Color::Blue).fg(Color::White)
} else {
Style::default().bg(Color::Cyan).fg(Color::Black)
};
Tabs::new(titles)
.style(tabs_style)
.block(Block::default().borders(Borders::ALL))
.highlight_style(highlight_style)
.select(self.selected as usize)
.render(area, buf);
}
}
impl Widget for &TitleBar {
fn render(self, area: Rect, buf: &mut Buffer)
where
Self: Sized,
{
let title_bar_area = Rect {
x: area.x,
y: area.y,
width: area.width,
height: 3,
};
self.render_title_bar(title_bar_area, buf);
}
}
impl Component for TitleBar {
fn handle_key_events(&mut self, key: KeyEvent) -> anyhow::Result<Action> {
match key.code {
// KeyCode::Up | KeyCode::Char('k') => self.selected.key_up(),
// KeyCode::Down | KeyCode::Char('j') => self.selected.key_down(),
KeyCode::Left | KeyCode::Char('h') => {
self.selected = self.selected.prev();
Ok(Action::Handled)
}
KeyCode::Right | KeyCode::Char('l') => {
self.selected = self.selected.next();
Ok(Action::Handled)
}
KeyCode::Enter => {
self.opened = Some(self.selected);
Ok(Action::Handled)
}
_ => Ok(Action::Noop),
}
}
}