use ratatui::{ buffer::Buffer, layout::Rect, style::{Color, Modifier, Style}, widgets::Widget, }; use crate::model::Model; use crate::view::Axis; use crate::ui::app::AppMode; pub struct TileBar<'a> { pub model: &'a Model, pub mode: &'a AppMode, } impl<'a> TileBar<'a> { pub fn new(model: &'a Model, mode: &'a AppMode) -> Self { Self { model, mode } } } impl<'a> Widget for TileBar<'a> { fn render(self, area: Rect, buf: &mut Buffer) { let view = match self.model.active_view() { Some(v) => v, None => return, }; let selected_cat_idx = if let AppMode::TileSelect { cat_idx } = self.mode { Some(*cat_idx) } else { None }; let mut x = area.x + 1; buf.set_string(area.x, area.y, " Tiles: ", Style::default().fg(Color::Gray)); x += 8; let cat_names: Vec<&str> = self.model.category_names(); for (i, cat_name) in cat_names.iter().enumerate() { let axis = view.axis_of(cat_name); let axis_symbol = match axis { Axis::Row => "↕", Axis::Column => "↔", Axis::Page => "☰", Axis::Unassigned => "─", }; let label = format!(" [{cat_name} {axis_symbol}] "); let is_selected = selected_cat_idx == Some(i); let style = if is_selected { Style::default().fg(Color::Black).bg(Color::Cyan).add_modifier(Modifier::BOLD) } else { match axis { Axis::Row => Style::default().fg(Color::Green), Axis::Column => Style::default().fg(Color::Blue), Axis::Page => Style::default().fg(Color::Magenta), Axis::Unassigned => Style::default().fg(Color::DarkGray), } }; if x + label.len() as u16 > area.x + area.width { break; } buf.set_string(x, area.y, &label, style); x += label.len() as u16; } // Hint if matches!(self.mode, AppMode::TileSelect { .. }) { let hint = " [Enter] cycle axis [r/c/p] set axis [←→] select [Esc] cancel"; if x + hint.len() as u16 <= area.x + area.width { buf.set_string(x, area.y, hint, Style::default().fg(Color::DarkGray)); } } else { let hint = " Ctrl+↑↓←→ to move tiles"; if x + hint.len() as u16 <= area.x + area.width { buf.set_string(x, area.y, hint, Style::default().fg(Color::DarkGray)); } } } }