use ratatui_core::layout::Rect;
use crate::{Element, RenderCtx, Size, Surface, View};
pub struct Constrained<V: View = Element> {
child: V,
min: Size,
max: Size,
}
impl<V: View> Constrained<V> {
pub fn new(child: V) -> Self {
Self {
child,
min: Size::ZERO,
max: Size::new(u16::MAX, u16::MAX),
}
}
pub fn min_size(mut self, width: u16, height: u16) -> Self {
self.min = Size::new(width, height);
self
}
pub fn max_size(mut self, width: u16, height: u16) -> Self {
self.max = Size::new(width, height);
self
}
}
impl<V: View> View for Constrained<V> {
fn measure(&self, available: Size, ctx: &RenderCtx) -> Size {
let measured = self.child.measure(available, ctx);
Size::new(
measured
.width
.max(self.min.width)
.min(self.max.width)
.min(available.width),
measured
.height
.max(self.min.height)
.min(self.max.height)
.min(available.height),
)
}
fn render(&self, area: Rect, surface: &mut Surface, ctx: &RenderCtx) {
self.child.render(area, surface, ctx);
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Size;
use crate::components::Text;
use crate::view::{View, element};
#[test]
fn constrained_clamps_intrinsic_measurement() {
let theme = crate::Theme::default();
let ctx = RenderCtx::new(&theme);
let constrained = Constrained::new(element(Text::raw("long content")))
.min_size(4, 1)
.max_size(6, 2);
assert_eq!(
constrained.measure(Size::new(20, 10), &ctx),
Size::new(6, 1)
);
assert_eq!(constrained.measure(Size::new(3, 1), &ctx), Size::new(3, 1));
}
}