use crate::components::Blank;
use crate::components::Dimensions;
use crate::components::DrawMode;
use crate::Component;
use crate::Lines;
#[derive(Debug)]
pub struct Padded<C: Component = Box<dyn Component>> {
pub child: C,
pub left: usize,
pub right: usize,
pub top: usize,
pub bottom: usize,
}
impl Default for Padded {
fn default() -> Self {
Self {
child: Box::new(Blank),
left: 0,
right: 0,
top: 0,
bottom: 0,
}
}
}
impl<C: Component> Padded<C> {
pub fn new(child: C, left: usize, right: usize, top: usize, bottom: usize) -> Self {
Self {
child,
left,
right,
top,
bottom,
}
}
}
impl<C: Component> Component for Padded<C> {
fn draw_unchecked(&self, dimensions: Dimensions, mode: DrawMode) -> anyhow::Result<Lines> {
let mut output = self.child.draw(dimensions, mode)?;
output.pad_lines_top(self.top);
output.truncate_lines_bottom(dimensions.height.saturating_sub(self.bottom));
output.pad_lines_bottom(self.bottom);
output.pad_lines_left(self.left);
output.truncate_lines(dimensions.width.saturating_sub(self.right));
output.pad_lines_right(self.right);
Ok(output)
}
}
#[cfg(test)]
mod tests {
use derive_more::AsRef;
use crate::components::echo::Echo;
use crate::components::Padded;
use crate::Component;
use crate::Dimensions;
use crate::DrawMode;
use crate::Line;
use crate::Lines;
#[derive(Debug, AsRef)]
struct Msg(Lines);
#[test]
fn test_pad_left() {
let msg = Lines(vec![
vec!["hello world"].try_into().unwrap(),
vec!["ok"].try_into().unwrap(),
Line::default(),
]);
let padder = Padded {
child: Echo(msg),
left: 5,
right: 0,
top: 0,
bottom: 0,
};
let drawing = padder
.draw(Dimensions::new(20, 20), DrawMode::Normal)
.unwrap();
let expected = Lines(vec![
vec![" ".repeat(5).as_ref(), "hello world"]
.try_into()
.unwrap(),
vec![" ".repeat(5).as_ref(), "ok"].try_into().unwrap(),
vec![" ".repeat(5)].try_into().unwrap(),
]);
assert_eq!(drawing, expected);
}
#[test]
fn test_pad_right() {
let msg = Lines(vec![
vec!["hello world"].try_into().unwrap(),
vec!["ok"].try_into().unwrap(),
Line::default(),
]);
let padder = Padded {
child: Echo(msg),
right: 4,
left: 0,
top: 0,
bottom: 0,
};
let drawing = padder
.draw(Dimensions::new(20, 20), DrawMode::Normal)
.unwrap();
let expected = Lines(vec![
vec!["hello world", &" ".repeat(4)].try_into().unwrap(),
vec!["ok", &" ".repeat(4 + 9)].try_into().unwrap(),
vec![" ".repeat(4 + 11)].try_into().unwrap(),
]);
assert_eq!(drawing, expected);
}
#[test]
fn test_pad_top() {
let msg = Lines(vec![
vec!["hello world"].try_into().unwrap(),
vec!["ok"].try_into().unwrap(),
Line::default(),
]);
let padder = Padded {
child: Echo(msg),
top: 5,
bottom: 0,
left: 0,
right: 0,
};
let drawing = padder
.draw(Dimensions::new(15, 15), DrawMode::Normal)
.unwrap();
let expected = Lines(vec![
Line::default(),
Line::default(),
Line::default(),
Line::default(),
Line::default(),
vec!["hello world"].try_into().unwrap(),
vec!["ok"].try_into().unwrap(),
Line::default(),
]);
assert_eq!(drawing, expected);
}
#[test]
fn test_pad_bottom() {
let msg = Lines(vec![
vec!["hello world"].try_into().unwrap(),
vec!["ok"].try_into().unwrap(),
Line::default(),
]);
let padder = Padded {
child: Echo(msg),
bottom: 5,
top: 0,
left: 0,
right: 0,
};
let drawing = padder
.draw(Dimensions::new(15, 15), DrawMode::Normal)
.unwrap();
let expected = Lines(vec![
vec!["hello world"].try_into().unwrap(),
vec!["ok"].try_into().unwrap(),
Line::default(),
Line::default(),
Line::default(),
Line::default(),
Line::default(),
Line::default(),
]);
assert_eq!(drawing, expected);
}
#[test]
fn test_no_pad() {
let msg = Lines(vec![
vec!["hello world"].try_into().unwrap(),
vec!["ok"].try_into().unwrap(),
Line::default(),
]);
let padder = Padded {
child: Echo(msg),
top: 0,
bottom: 0,
left: 0,
right: 0,
};
let drawing = padder
.draw(Dimensions::new(15, 15), DrawMode::Normal)
.unwrap();
let expected = Lines(vec![
vec!["hello world"].try_into().unwrap(),
vec!["ok"].try_into().unwrap(),
Line::default(),
]);
assert_eq!(drawing, expected);
}
#[test]
fn test_truncated() {
let msg = Lines(vec![
vec!["hello world"].try_into().unwrap(),
vec!["ok"].try_into().unwrap(),
Line::default(),
]);
let padder = Padded {
child: Echo(msg),
left: 5,
right: 3,
top: 3,
bottom: 3,
};
let drawing = padder
.draw(Dimensions::new(10, 8), DrawMode::Normal)
.unwrap();
let expected = Lines(vec![
vec![" ".repeat(5), " ".repeat(5)].try_into().unwrap(),
vec![" ".repeat(5), " ".repeat(5)].try_into().unwrap(),
vec![" ".repeat(5), " ".repeat(5)].try_into().unwrap(),
vec![" ".repeat(5).as_ref(), "he", &" ".repeat(3)]
.try_into()
.unwrap(),
vec![" ".repeat(5).as_ref(), "ok", &" ".repeat(3)]
.try_into()
.unwrap(),
vec![" ".repeat(5), " ".repeat(5)].try_into().unwrap(),
vec![" ".repeat(5), " ".repeat(5)].try_into().unwrap(),
vec![" ".repeat(5), " ".repeat(5)].try_into().unwrap(),
]);
assert_eq!(drawing, expected);
}
}