use ratatui::layout::{Constraint, Direction, Layout, Rect};
pub(crate) struct MainLayout {
header: Rect,
subheader: Rect,
body: Rect,
footer: Rect,
}
impl MainLayout {
pub(crate) fn header_area(&self) -> Rect {
self.header
}
pub(crate) fn subheader_area(&self) -> Rect {
self.subheader
}
pub(crate) fn body_area(&self) -> Rect {
self.body
}
pub(crate) fn footer_area(&self) -> Rect {
self.footer
}
pub(crate) fn input_area(&self) -> Rect {
let body_chunks = Layout::default()
.direction(Direction::Horizontal)
.constraints([Constraint::Percentage(68), Constraint::Percentage(32)])
.split(self.body);
let left_chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Min(5),
Constraint::Length(self.body.height.saturating_sub(6)),
])
.split(body_chunks[0]);
left_chunks[1]
}
}
pub(crate) fn main_layout(area: Rect) -> MainLayout {
MainLayout::new(area)
}
impl MainLayout {
pub(crate) fn new(area: Rect) -> Self {
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(4), Constraint::Length(0), Constraint::Min(5), Constraint::Length(1), ])
.split(area);
Self { header: chunks[0], subheader: chunks[1], body: chunks[2], footer: chunks[3] }
}
}
pub(crate) fn home_layout(
area: Rect,
logo_height: u16,
input_height: u16,
) -> (Vec<Rect>, Vec<Rect>) {
let logo_gap: u16 = if logo_height > 0 { 1 } else { 0 };
let center_height =
logo_height.saturating_add(input_height).saturating_add(logo_gap).saturating_add(2);
let remaining_height = area.height.saturating_sub(center_height.saturating_add(1));
let top_space = remaining_height / 2;
let bottom_space = remaining_height.saturating_sub(top_space);
let chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(top_space),
Constraint::Length(center_height),
Constraint::Length(bottom_space),
Constraint::Length(1),
])
.split(area);
let center_chunks = Layout::default()
.direction(Direction::Vertical)
.constraints([
Constraint::Length(logo_height),
Constraint::Length(logo_gap),
Constraint::Length(input_height),
Constraint::Length(1),
Constraint::Length(1),
Constraint::Min(1),
])
.split(chunks[1]);
(chunks.to_vec(), center_chunks.to_vec())
}
pub(crate) fn centered_overlay_rect(
area: Rect,
width_div: u16,
height_div: u16,
max_height: u16,
) -> Rect {
let w = area.width.saturating_mul(width_div) / (width_div + 3);
let h = max_height.min(area.height.saturating_mul(height_div) / (height_div + 3));
let x = area.x.saturating_add(area.width.saturating_sub(w) / 2);
let y = area.y.saturating_add(area.height.saturating_sub(h) / 2);
Rect { x, y, width: w, height: h }
}
#[cfg(test)]
#[path = "layout_tests.rs"]
mod layout_tests;