1use crate::console::{Console, ConsoleOptions};
9use crate::protocol::Renderable;
10use crate::segment::Segment;
11use crate::style::Style;
12
13pub struct Screen {
16 renderable: Option<Box<dyn Renderable>>,
17 style: Option<Style>,
18}
19
20impl Screen {
21 pub fn new(renderable: Box<dyn Renderable>) -> Self {
23 Screen {
24 renderable: Some(renderable),
25 style: None,
26 }
27 }
28
29 pub fn empty() -> Self {
31 Screen {
32 renderable: None,
33 style: None,
34 }
35 }
36
37 pub fn style(mut self, style: Style) -> Self {
39 self.style = Some(style);
40 self
41 }
42}
43
44impl Renderable for Screen {
45 fn rich_render(&self, console: &Console, options: &ConsoleOptions) -> Vec<Segment> {
46 let width = options.max_width;
47 let height = options.height.unwrap_or_else(|| console.height());
48
49 let lines = match &self.renderable {
50 Some(renderable) => {
51 let child_options = options.update_dimensions(width, height);
52 console.render_lines(renderable.as_ref(), &child_options, true)
53 }
54 None => Vec::new(),
55 };
56 let mut lines = Segment::set_shape(lines, width, height);
57
58 if let Some(style) = &self.style {
60 for line in &mut lines {
61 *line = Segment::apply_style(line, style);
62 }
63 }
64
65 let mut segments = Vec::new();
66 let last = lines.len().saturating_sub(1);
67 for (index, line) in lines.into_iter().enumerate() {
68 segments.extend(line);
69 if index != last {
70 segments.push(Segment::line());
71 }
72 }
73 segments
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80 use crate::color::ColorSystem;
81 use crate::text::Text;
82
83 fn console(width: usize, height: usize) -> Console {
84 Console::builder()
85 .force_terminal(true)
86 .color_system(Some(ColorSystem::Truecolor))
87 .width(width)
88 .height(height)
89 .build()
90 }
91
92 #[test]
93 fn fills_to_width_and_height() {
94 let screen = Screen::new(Box::new(Text::new("hi")));
95 let out = console(6, 3).capture(|c| c.print(&screen));
96 assert_eq!(out, "hi \n \n \n");
99 }
100
101 #[test]
102 fn empty_screen_is_blank_rectangle() {
103 let out = console(4, 2).capture(|c| c.print(&Screen::empty()));
104 assert_eq!(out, " \n \n");
105 }
106}