ascii_forge/widgets/
border.rs

1use crate::prelude::*;
2
3/// A basic border type.
4/// Rendering this will put the next content inside of the function
5/// Borders will skip rendering if their size is under a 3x3
6pub struct Border {
7    pub size: Vec2,
8    pub horizontal: &'static str,
9    pub vertical: &'static str,
10    pub top_left: &'static str,
11    pub top_right: &'static str,
12    pub bottom_left: &'static str,
13    pub bottom_right: &'static str,
14}
15
16impl Border {
17    pub const fn square(width: u16, height: u16) -> Border {
18        Border {
19            size: vec2(width, height),
20            horizontal: "─",
21            vertical: "│",
22            top_right: "┐",
23            top_left: "┌",
24            bottom_left: "└",
25            bottom_right: "┘",
26        }
27    }
28}
29
30impl Render for Border {
31    fn render(&self, loc: Vec2, buffer: &mut Buffer) -> Vec2 {
32        if self.size.x < 3 || self.size.y < 3 {
33            return loc;
34        }
35        for y in (loc.y + 1)..(loc.y + self.size.y.saturating_sub(1)) {
36            buffer.set(vec2(loc.x, y), self.vertical);
37            buffer.set(
38                vec2(loc.x + self.size.x.saturating_sub(1), y),
39                self.vertical,
40            );
41        }
42
43        let _ = render!(buffer,
44            loc => [self.top_left, self.horizontal.repeat(self.size.x.saturating_sub(2) as usize), self.top_right],
45            vec2(loc.x, loc.y + self.size.y.saturating_sub(1)) => [self.bottom_left, self.horizontal.repeat(self.size.x.saturating_sub(2) as usize), self.bottom_right]
46        );
47
48        vec2(loc.x + 1, loc.y + 1)
49    }
50    fn size(&self) -> Vec2 {
51        self.size
52    }
53}
54
55#[cfg(test)]
56mod test {
57    use crate::{
58        math::Vec2,
59        render,
60        widgets::border::Border,
61        window::{Buffer, Render},
62    };
63
64    #[test]
65    fn render_small() {
66        let border = Border::square(0, 0);
67        // Ensure no panics
68        let _ = Buffer::sized_element(border);
69    }
70
71    #[test]
72    fn check_size() {
73        let border = Border::square(16, 16);
74        let mut buf = Buffer::new((80, 80));
75        render!(buf, (0, 0) => [ border ]);
76        buf.shrink();
77        assert_eq!(buf.size(), border.size())
78    }
79}