1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
use crate::{
Component,
RenderError,
Rendered,
};
/// A rectangular box filled with spaces, optionally with a background color.
///
/// The box renders `pad_y` rows of spaces at the requested width. A background
/// function can be applied to each line via
/// [`with_background`](Box::with_background).
pub struct Box {
pad_y: u16,
bg_fn: Option<fn(&str, u16) -> String>,
}
impl Box {
/// Create a new box with the given vertical padding.
pub fn new(pad_y: u16) -> Self {
Self { pad_y, bg_fn: None }
}
/// Apply a background color function to every line.
///
/// The function receives `(line_text, width)` and should return the
/// styled line.
pub fn with_background(mut self, bg: fn(&str, u16) -> String) -> Self {
self.bg_fn = Some(bg);
self
}
}
impl Component for Box {
fn render(&self, width: u16) -> Result<Rendered, RenderError> {
let mut lines = Vec::new();
let empty = " ".repeat(width as usize);
for _ in 0..self.pad_y {
lines.push(empty.clone());
}
if let Some(bg) = self.bg_fn {
lines = lines.into_iter().map(|l| bg(&l, width)).collect();
}
Ok(Rendered {
lines,
cursor: None,
images: Vec::new(),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn box_with_background() {
let b = Box::new(2).with_background(|line, _w| format!(">{}<", line));
let r = b.render(5).unwrap();
assert_eq!(r.lines.len(), 2);
}
}