1use crate::console::RenderContext;
6use crate::renderable::Renderable;
7
8#[derive(Debug, Clone, Copy, PartialEq, Eq)]
10pub struct Measurement {
11 pub minimum: usize,
13 pub maximum: usize,
15 pub lines: usize,
17}
18
19impl Measurement {
20 pub fn new(minimum: usize, maximum: usize, lines: usize) -> Self {
22 Measurement {
23 minimum,
24 maximum,
25 lines,
26 }
27 }
28
29 pub fn measure(renderable: &impl Renderable, width: usize) -> Self {
31 let context = RenderContext { width, height: None };
32 let segments = renderable.render(&context);
33
34 let lines = segments.len();
35 let minimum = renderable.min_width();
36 let maximum = renderable.max_width().min(width);
37
38 Measurement {
39 minimum,
40 maximum,
41 lines,
42 }
43 }
44
45 pub fn aspect_ratio(&self) -> f64 {
47 if self.lines == 0 {
48 0.0
49 } else {
50 self.maximum as f64 / self.lines as f64
51 }
52 }
53
54 pub fn fits(&self, width: usize, height: usize) -> bool {
56 self.minimum <= width && self.lines <= height
57 }
58
59 pub fn area(&self) -> usize {
61 self.maximum * self.lines
62 }
63}
64
65pub trait Measurable {
67 fn measure(&self, width: usize) -> Measurement;
69}
70
71impl<T: Renderable> Measurable for T {
72 fn measure(&self, width: usize) -> Measurement {
73 Measurement::measure(self, width)
74 }
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80 use crate::text::Text;
81
82 #[test]
83 fn test_measurement_creation() {
84 let m = Measurement::new(10, 50, 3);
85 assert_eq!(m.minimum, 10);
86 assert_eq!(m.maximum, 50);
87 assert_eq!(m.lines, 3);
88 }
89
90 #[test]
91 fn test_measure_text() {
92 let text = Text::plain("Hello, World!");
93 let m = Measurement::measure(&text, 80);
94
95 assert!(m.minimum > 0);
96 assert!(m.lines > 0);
97 }
98
99 #[test]
100 fn test_aspect_ratio() {
101 let m = Measurement::new(20, 40, 5);
102 assert_eq!(m.aspect_ratio(), 8.0);
103 }
104
105 #[test]
106 fn test_fits() {
107 let m = Measurement::new(10, 40, 3);
108 assert!(m.fits(50, 5));
109 assert!(!m.fits(5, 5)); assert!(!m.fits(50, 2)); }
112
113 #[test]
114 fn test_area() {
115 let m = Measurement::new(10, 20, 5);
116 assert_eq!(m.area(), 100); }
118}