use ratatui::prelude::*;
use ratatui::widgets::{Block, BorderType, Borders, Clear, Paragraph};
use super::theme;
const CHROME_ROWS: u16 = 4;
const CHROME_COLS: u16 = 6;
const MAX_COLS: u16 = 60;
pub fn centred(area: Rect, w: u16, h: u16) -> Rect {
let w = w.min(area.width);
let h = h.min(area.height);
Rect { x: area.x + (area.width - w) / 2, y: area.y + (area.height - h) / 2, width: w, height: h }
}
pub fn render(f: &mut Frame, area: Rect, title: &str, lines: Vec<Line>, accent: Color) {
let widest = lines.iter().map(|l| l.width()).max().unwrap_or(0);
let content = (widest.max(title.chars().count() + 2) as u16).min(MAX_COLS);
let rect = centred(area, content + CHROME_COLS, lines.len() as u16 + CHROME_ROWS);
f.render_widget(Clear, rect);
let block = Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.border_style(Style::default().fg(accent))
.style(Style::default().bg(theme::BG_MODAL))
.title(format!(" {title} "))
.title_style(Style::default().fg(accent).bold());
let inner = block.inner(rect);
f.render_widget(block, rect);
let body = Rect { y: inner.y + 1, height: inner.height.saturating_sub(1), ..inner };
f.render_widget(Paragraph::new(lines).alignment(Alignment::Center), body);
}
#[cfg(test)]
mod tests {
use super::centred;
use ratatui::layout::Rect;
#[test]
fn a_dialog_is_centred_in_its_area() {
let r = centred(Rect::new(0, 0, 100, 40), 20, 6);
assert_eq!((r.x, r.y, r.width, r.height), (40, 17, 20, 6));
}
#[test]
fn a_dialog_too_big_for_the_terminal_is_squeezed_not_clipped() {
let area = Rect::new(0, 0, 20, 5);
let r = centred(area, 60, 12);
assert_eq!((r.width, r.height), (20, 5));
assert!(r.x + r.width <= area.width && r.y + r.height <= area.height);
}
}