Files
improvise/src/ui/category_panel.rs
Edward Langley 6370f8b19f chore: format
2026-04-13 21:30:37 -07:00

108 lines
3.1 KiB
Rust

use ratatui::{
buffer::Buffer,
layout::Rect,
style::{Color, Modifier, Style},
};
use crate::model::Model;
use crate::ui::app::AppMode;
use crate::ui::cat_tree::{CatTreeEntry, build_cat_tree};
use crate::ui::panel::PanelContent;
use crate::view::Axis;
fn axis_display(axis: Axis) -> (&'static str, Color) {
match axis {
Axis::Row => ("Row ↕", Color::Green),
Axis::Column => ("Col ↔", Color::Blue),
Axis::Page => ("Page ☰", Color::Magenta),
Axis::None => ("None ∅", Color::DarkGray),
}
}
pub struct CategoryContent<'a> {
model: &'a Model,
tree: Vec<CatTreeEntry>,
}
impl<'a> CategoryContent<'a> {
pub fn new(model: &'a Model, expanded: &'a std::collections::HashSet<String>) -> Self {
let tree = build_cat_tree(model, expanded);
Self { model, tree }
}
}
impl PanelContent for CategoryContent<'_> {
fn is_active(&self, mode: &AppMode) -> bool {
matches!(
mode,
AppMode::CategoryPanel | AppMode::ItemAdd { .. } | AppMode::CategoryAdd { .. }
)
}
fn active_color(&self) -> Color {
Color::Cyan
}
fn title(&self) -> &str {
" Categories "
}
fn item_count(&self) -> usize {
self.tree.len()
}
fn empty_message(&self) -> &str {
"(no categories — use :add-cat <name>)"
}
fn render_item(&self, index: usize, is_selected: bool, inner: Rect, buf: &mut Buffer) {
let y = inner.y + index as u16;
let view = self.model.active_view();
let base_style = if is_selected {
Style::default()
.fg(Color::Black)
.bg(Color::Cyan)
.add_modifier(Modifier::BOLD)
} else {
Style::default()
};
if is_selected {
let fill = " ".repeat(inner.width as usize);
buf.set_string(inner.x, y, &fill, base_style);
}
match &self.tree[index] {
CatTreeEntry::Category {
name,
item_count,
expanded,
} => {
let indicator = if *expanded { "" } else { "" };
let (axis_str, axis_color) = axis_display(view.axis_of(name));
let name_part = format!("{indicator} {name} ({item_count})");
let axis_part = format!(" [{axis_str}]");
buf.set_string(inner.x, y, &name_part, base_style);
if name_part.len() + axis_part.len() < inner.width as usize {
buf.set_string(
inner.x + name_part.len() as u16,
y,
&axis_part,
if is_selected {
base_style
} else {
Style::default().fg(axis_color)
},
);
}
}
CatTreeEntry::Item { item_name, .. } => {
let label = format!(" · {item_name}");
buf.set_string(inner.x, y, &label, base_style);
}
}
}
}