use crossterm::event::KeyCode;
use ratatui::{
layout::{Constraint, Direction, Layout, Rect},
style::{Color, Modifier, Style},
widgets::{Block, Borders, Cell, Paragraph, Row, Table, TableState},
Frame,
};
use crate::desktop::manager::InstalledStatus;
pub struct DesktopPanel {
pub desktops: Vec<InstalledStatus>,
pub state: TableState,
}
impl DesktopPanel {
pub fn new(desktops: Vec<InstalledStatus>) -> Self {
let mut state = TableState::default();
if !desktops.is_empty() {
state.select(Some(0));
}
Self { desktops, state }
}
pub fn handle_key(&mut self, code: KeyCode) {
match code {
KeyCode::Char('j') | KeyCode::Down => self.next(1),
KeyCode::Char('k') | KeyCode::Up => self.prev(1),
KeyCode::PageDown => self.next(10),
KeyCode::PageUp => self.prev(10),
_ => {}
}
}
fn next(&mut self, step: usize) {
let len = self.desktops.len();
if len == 0 { return; }
let i = self.state.selected().map_or(0, |i| (i + step).min(len - 1));
self.state.select(Some(i));
}
fn prev(&mut self, step: usize) {
let i = self.state.selected().map_or(0, |i| i.saturating_sub(step));
self.state.select(Some(i));
}
pub fn render(&self, f: &mut Frame, area: Rect) {
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([Constraint::Min(0), Constraint::Length(3)])
.split(area);
let rows: Vec<Row> = self
.desktops
.iter()
.map(|d| {
let check = if d.installed { "✓" } else { " " };
let pkgs = d.profile.packages.join(", ");
let status = if d.installed { "installed" } else { "available" };
let style = if d.installed {
Style::default().fg(Color::Green)
} else {
Style::default().fg(Color::White)
};
Row::new(vec![
Cell::from(check),
Cell::from(d.profile.display_name),
Cell::from(pkgs),
Cell::from(d.profile.display_manager),
Cell::from(status),
])
.style(style)
})
.collect();
let widths = [
Constraint::Length(3),
Constraint::Length(18),
Constraint::Min(30),
Constraint::Length(12),
Constraint::Length(12),
];
let table = Table::new(rows, widths)
.header(
Row::new(vec!["", "Desktop", "Packages", "Display Mgr", "Status"])
.style(Style::default().fg(Color::Cyan).add_modifier(Modifier::BOLD)),
)
.block(Block::default().borders(Borders::ALL).title(" Desktop Environments "))
.row_highlight_style(Style::default().bg(Color::DarkGray).add_modifier(Modifier::BOLD))
.highlight_symbol("▶ ");
let mut state = self.state.clone();
f.render_stateful_widget(table, chunks[0], &mut state);
let actions = Paragraph::new(" Enter: install/remove s: switch default DM q: back [?] Help")
.block(Block::default().borders(Borders::ALL).title(" Actions "));
f.render_widget(actions, chunks[1]);
}
}