rtcom_tui/layout.rs
1//! Top-level chrome layout for the TUI main screen.
2//!
3//! The main screen has three horizontal bands:
4//!
5//! ```text
6//! ┌────────────────────────────────────┐
7//! │ top bar (1 row, status / device) │
8//! ├────────────────────────────────────┤
9//! │ body (serial pane) │
10//! │ │
11//! │ │
12//! ├────────────────────────────────────┤
13//! │ bottom bar (1 row, hint text) │
14//! └────────────────────────────────────┘
15//! ```
16//!
17//! [`main_chrome`] splits a [`Rect`] into exactly those three bands so
18//! the top-level renderer can hand each sub-rect to the right widget.
19
20use ratatui::layout::{Constraint, Layout, Rect};
21
22/// Splits the terminal area into top bar (1 row), body (min 1 row),
23/// and bottom bar (1 row).
24///
25/// Returned tuple is `(top, body, bottom)`. When `area.height < 3`
26/// the ratatui [`Layout`] engine still yields three rects but some
27/// may be zero-sized; the caller is responsible for skipping them.
28///
29/// # Examples
30///
31/// ```
32/// use ratatui::layout::Rect;
33/// use rtcom_tui::layout::main_chrome;
34///
35/// let (top, body, bottom) = main_chrome(Rect::new(0, 0, 80, 24));
36/// assert_eq!(top.height, 1);
37/// assert_eq!(body.height, 22);
38/// assert_eq!(bottom.height, 1);
39/// ```
40#[must_use]
41pub fn main_chrome(area: Rect) -> (Rect, Rect, Rect) {
42 let rows = Layout::vertical([
43 Constraint::Length(1),
44 Constraint::Min(1),
45 Constraint::Length(1),
46 ])
47 .split(area);
48 (rows[0], rows[1], rows[2])
49}
50
51#[cfg(test)]
52mod tests {
53 use super::*;
54
55 #[test]
56 fn main_chrome_splits_80x24() {
57 let (top, body, bottom) = main_chrome(Rect::new(0, 0, 80, 24));
58 assert_eq!(top.height, 1);
59 assert_eq!(bottom.height, 1);
60 assert_eq!(body.height, 22);
61 assert_eq!(top.width, 80);
62 assert_eq!(body.width, 80);
63 assert_eq!(bottom.width, 80);
64 }
65
66 #[test]
67 fn main_chrome_preserves_origin() {
68 let (top, body, bottom) = main_chrome(Rect::new(5, 2, 40, 10));
69 assert_eq!(top.y, 2);
70 assert_eq!(body.y, 3);
71 // bottom.y = origin.y + height - 1 = 2 + 10 - 1 = 11
72 assert_eq!(bottom.y, 11);
73 assert_eq!(top.x, 5);
74 assert_eq!(body.x, 5);
75 assert_eq!(bottom.x, 5);
76 }
77}