Skip to main content

rosace_widgets/tree/
aspect_ratio.rs

1use rosace_core::types::Size;
2use rosace_layout::Constraints;
3use super::{Widget, Children, LayoutCtx, PaintCtx, BoxedWidget, avail_w, avail_h};
4
5/// Sizes its child to a fixed width:height `ratio` (e.g. 16.0/9.0), fitting
6/// within the available space. Lays out something new (D095).
7pub struct AspectRatio {
8    ratio: f32,
9    child: BoxedWidget,
10}
11
12impl AspectRatio {
13    pub fn new(ratio: f32, child: impl Widget + 'static) -> Self {
14        Self { ratio: ratio.max(0.01), child: Box::new(child) }
15    }
16
17    fn box_size(&self, c: &Constraints) -> Size {
18        let (aw, ah) = (avail_w(*c), avail_h(*c));
19        // Prefer full width; if that overflows height, clamp by height.
20        let mut w = if aw.is_finite() { aw } else { ah * self.ratio };
21        let mut h = w / self.ratio;
22        if ah.is_finite() && h > ah { h = ah; w = h * self.ratio; }
23        Size { width: w, height: h }
24    }
25}
26
27impl Widget for AspectRatio {
28    fn children(&self) -> Children<'_> { Children::One(&*self.child) }
29
30    fn layout(&self, ctx: &LayoutCtx) -> Size {
31        ctx.constraints.constrain(self.box_size(&ctx.constraints))
32    }
33
34    fn paint(&self, ctx: &mut PaintCtx) {
35        let r = ctx.rect;
36        self.child.paint(&mut ctx.child(r));
37    }
38}