use crate::console::RenderContext;
use crate::renderable::{BoxedRenderable, Renderable, Segment};
use crate::text::Span;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct PaddingSpec {
pub top: usize,
pub right: usize,
pub bottom: usize,
pub left: usize,
}
impl PaddingSpec {
pub fn all(size: usize) -> Self {
PaddingSpec {
top: size,
right: size,
bottom: size,
left: size,
}
}
pub fn symmetric(vertical: usize, horizontal: usize) -> Self {
PaddingSpec {
top: vertical,
right: horizontal,
bottom: vertical,
left: horizontal,
}
}
pub fn new(top: usize, right: usize, bottom: usize, left: usize) -> Self {
PaddingSpec {
top,
right,
bottom,
left,
}
}
pub fn none() -> Self {
PaddingSpec::all(0)
}
}
pub struct Padding {
child: BoxedRenderable,
spec: PaddingSpec,
}
impl Padding {
pub fn new(child: impl Renderable + Send + Sync + 'static, spec: PaddingSpec) -> Self {
Padding {
child: Box::new(child),
spec,
}
}
pub fn all(child: impl Renderable + Send + Sync + 'static, size: usize) -> Self {
Padding::new(child, PaddingSpec::all(size))
}
pub fn symmetric(
child: impl Renderable + Send + Sync + 'static,
vertical: usize,
horizontal: usize,
) -> Self {
Padding::new(child, PaddingSpec::symmetric(vertical, horizontal))
}
}
impl Renderable for Padding {
fn render(&self, context: &RenderContext) -> Vec<Segment> {
let child_width = context
.width
.saturating_sub(self.spec.left + self.spec.right);
let child_context = RenderContext {
width: child_width,
height: None,
};
let child_segments = self.child.render(&child_context);
let mut result = Vec::new();
for _ in 0..self.spec.top {
result.push(Segment::line(vec![Span::raw(" ".repeat(context.width))]));
}
for segment in child_segments {
let mut padded_spans = Vec::new();
if self.spec.left > 0 {
padded_spans.push(Span::raw(" ".repeat(self.spec.left)));
}
padded_spans.extend(segment.spans);
if self.spec.right > 0 {
padded_spans.push(Span::raw(" ".repeat(self.spec.right)));
}
if segment.newline {
result.push(Segment::line(padded_spans));
} else {
result.push(Segment::new(padded_spans));
}
}
for _ in 0..self.spec.bottom {
result.push(Segment::line(vec![Span::raw(" ".repeat(context.width))]));
}
result
}
}