use crate::console::{Console, ConsoleOptions};
use crate::protocol::Renderable;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Measurement {
pub minimum: usize,
pub maximum: usize,
}
impl Measurement {
pub fn new(minimum: usize, maximum: usize) -> Self {
Measurement { minimum, maximum }
}
pub fn span(&self) -> isize {
self.maximum as isize - self.minimum as isize
}
pub fn normalize(&self) -> Measurement {
let minimum = self.minimum.min(self.maximum);
Measurement::new(minimum, self.maximum.max(minimum))
}
pub fn with_maximum(&self, width: usize) -> Measurement {
Measurement::new(self.minimum.min(width), self.maximum.min(width))
}
pub fn with_minimum(&self, width: usize) -> Measurement {
Measurement::new(self.minimum.max(width), self.maximum.max(width))
}
pub fn get(console: &Console, options: &ConsoleOptions, renderable: &dyn Renderable) -> Self {
let max_width = options.max_width;
if max_width < 1 {
return Measurement::new(0, 0);
}
let width = renderable
.measure(console, options)
.normalize()
.with_maximum(max_width);
if width.maximum < 1 {
return Measurement::new(0, 0);
}
width.normalize()
}
pub fn clamp(&self, min_width: Option<usize>, max_width: Option<usize>) -> Measurement {
let mut measurement = *self;
if let Some(lo) = min_width {
measurement = measurement.with_minimum(lo);
}
if let Some(hi) = max_width {
measurement = measurement.with_maximum(hi);
}
measurement
}
}
pub fn measure_renderables(
console: &Console,
options: &ConsoleOptions,
renderables: &[&dyn Renderable],
) -> Measurement {
if renderables.is_empty() {
return Measurement::new(0, 0);
}
let measurements: Vec<Measurement> = renderables
.iter()
.map(|renderable| Measurement::get(console, options, *renderable))
.collect();
Measurement::new(
measurements.iter().map(|m| m.minimum).max().unwrap_or(0),
measurements.iter().map(|m| m.maximum).max().unwrap_or(0),
)
}