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 self.child.rich_render(console, &child_options)
32 }
33
34 fn measure(&self, console: &Console, options: &ConsoleOptions) -> Measurement {
37 let options = match self.width {
38 Some(width) => options.update_width(width),
39 None => options.clone(),
40 };
41 Measurement::get(console, &options, self.child.as_ref())
42 }
43}
44
45#[cfg(test)]
46mod tests {
47 use super::*;
48 use crate::color::ColorSystem;
49 use crate::panel::Panel;
50 use crate::r#box::SQUARE;
51 use crate::text::Text;
52
53 #[test]
54 fn constrains_panel_width() {
55 let console = Console::builder()
56 .force_terminal(true)
57 .color_system(Some(ColorSystem::Truecolor))
58 .width(20)
59 .build();
60 let panel = Panel::new(Box::new(Text::new("hi"))).box_set(SQUARE);
61 let constrained = Constrain::new(Box::new(panel), Some(10));
62 let out = console.render_export(&constrained);
63 assert_eq!(out, "┌────────┐\n│ hi │\n└────────┘\n");
64 }
65}