Skip to main content

photon_ui/components/
box_component.rs

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