use std::fmt;
use ctl_text::{Context, Line, Measurement, Renderable};
#[derive(Default)]
pub struct Stack<'a> {
children: Vec<Box<dyn Renderable + 'a>>,
spacing: u16,
}
impl<'a> Stack<'a> {
#[must_use]
pub fn new() -> Self {
Self::default()
}
#[must_use]
pub fn spacing(mut self, lines: u16) -> Self {
self.spacing = lines;
self
}
#[must_use]
pub fn push(mut self, child: impl Renderable + 'a) -> Self {
self.children.push(Box::new(child));
self
}
}
impl fmt::Debug for Stack<'_> {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter
.debug_struct("Stack")
.field("children", &self.children.len())
.field("spacing", &self.spacing)
.finish()
}
}
impl Renderable for Stack<'_> {
fn measure(&self, context: &Context) -> Measurement {
self.children
.iter()
.map(|child| child.measure(context))
.fold(Measurement::exact(0), |widest, child| {
Measurement::new(
widest.minimum().max(child.minimum()),
widest.maximum().max(child.maximum()),
)
})
}
fn render(&self, context: &Context) -> Vec<Line> {
let mut lines: Vec<Line> = Vec::new();
for child in &self.children {
let rendered = child.render(context);
if rendered.iter().all(Line::is_empty) {
continue;
}
if !lines.is_empty() {
lines.extend((0..self.spacing).map(|_| Line::new()));
}
lines.extend(rendered);
}
lines
}
}