1use crate::console::{Console, ConsoleOptions};
7use crate::measure::Measurement;
8use crate::protocol::Renderable;
9use crate::segment::Segment;
10
11pub struct Constrain {
13 child: Box<dyn Renderable>,
14 width: Option<usize>,
15}
16
17impl Constrain {
18 pub fn new(child: Box<dyn Renderable>, width: Option<usize>) -> Self {
20 Constrain { child, width }
21 }
22}
23
24impl Renderable for Constrain {
25 fn rich_render(&self, console: &Console, options: &ConsoleOptions) -> Vec<Segment> {
26 let width = match self.width {
27 Some(width) => width.min(options.max_width),
28 None => options.max_width,
29 };
30 let child_options = options.update_width(width);
31 console.render(self.child.as_ref(), Some(&child_options))
34 }
35
36 fn measure(&self, console: &Console, options: &ConsoleOptions) -> Measurement {
39 let options = match self.width {
40 Some(width) => options.update_width(width),
41 None => options.clone(),
42 };
43 Measurement::get(console, &options, self.child.as_ref())
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50 use crate::color::ColorSystem;
51 use crate::panel::Panel;
52 use crate::r#box::SQUARE;
53 use crate::text::Text;
54
55 #[test]
56 fn constrains_panel_width() {
57 let console = Console::builder()
58 .force_terminal(true)
59 .color_system(Some(ColorSystem::Truecolor))
60 .width(20)
61 .build();
62 let panel = Panel::new(Box::new(Text::new("hi"))).box_set(SQUARE);
63 let constrained = Constrain::new(Box::new(panel), Some(10));
64 let out = console.render_export(&constrained);
65 assert_eq!(out, "┌────────┐\n│ hi │\n└────────┘\n");
66 }
67}