use std::io::{self, Write};
use crate::layout_panel::LayoutPanel;
use crate::renderer::{Component, Renderer};
pub enum Align {
Box,
Content(u16),
Full,
}
pub struct LayoutStack {
row: u16,
terminal_width: u16,
box_column: u16,
box_width: u16,
}
impl LayoutStack {
pub fn new(start_row: u16, terminal_width: u16, box_column: u16, box_width: u16) -> Self {
Self {
row: start_row,
terminal_width,
box_column,
box_width,
}
}
pub fn row(&self) -> u16 {
self.row
}
pub fn terminal_width(&self) -> u16 {
self.terminal_width
}
#[cfg(not(tarpaulin_include))]
pub fn draw<W: Write>(
&mut self,
renderer: &mut Renderer<W>,
component: &impl Component,
align: Align,
) -> io::Result<u16> {
let panel = self.panel(align);
let rows = renderer.draw(component, panel)?;
self.row = self.row.saturating_add(rows);
Ok(rows)
}
pub fn skip(&mut self, rows: u16) {
self.row = self.row.saturating_add(rows);
}
fn panel(&self, align: Align) -> LayoutPanel {
match align {
Align::Box => LayoutPanel {
row: self.row,
column: self.box_column,
width: self.box_width,
},
Align::Content(width) => LayoutPanel::centered(self.terminal_width, width, self.row),
Align::Full => LayoutPanel {
row: self.row,
column: 0,
width: self.terminal_width,
},
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_starts_at_given_row() {
let stack = LayoutStack::new(5, 80, 10, 30);
assert_eq!(stack.row(), 5);
assert_eq!(stack.terminal_width(), 80);
}
#[test]
fn skip_advances_row() {
let mut stack = LayoutStack::new(0, 80, 10, 30);
stack.skip(3);
assert_eq!(stack.row(), 3);
stack.skip(2);
assert_eq!(stack.row(), 5);
}
#[test]
fn panel_box_uses_precomputed_geometry() {
let stack = LayoutStack::new(10, 80, 15, 40);
let panel = stack.panel(Align::Box);
assert_eq!(panel.row, 10);
assert_eq!(panel.column, 15);
assert_eq!(panel.width, 40);
}
#[test]
fn panel_content_centers_width() {
let stack = LayoutStack::new(5, 80, 0, 0);
let panel = stack.panel(Align::Content(20));
assert_eq!(panel.row, 5);
assert_eq!(panel.column, 30); assert_eq!(panel.width, 20);
}
#[test]
fn panel_full_spans_terminal() {
let stack = LayoutStack::new(7, 120, 10, 30);
let panel = stack.panel(Align::Full);
assert_eq!(panel.row, 7);
assert_eq!(panel.column, 0);
assert_eq!(panel.width, 120);
}
}