rosace_widgets/tree/
wrap.rs1use rosace_core::types::{Point, Rect, Size};
2use rosace_layout::Constraints;
3use super::{Widget, Children, LayoutCtx, PaintCtx, BoxedWidget, avail_w};
4
5pub struct Wrap {
8 spacing: f32,
9 run_spacing: f32,
10 children: Vec<BoxedWidget>,
11}
12
13impl Wrap {
14 pub fn new() -> Self { Self { spacing: 8.0, run_spacing: 8.0, children: Vec::new() } }
15 pub fn spacing(mut self, s: f32) -> Self { self.spacing = s; self }
16 pub fn run_spacing(mut self, s: f32) -> Self { self.run_spacing = s; self }
17 pub fn child(mut self, w: impl Widget + 'static) -> Self { self.children.push(Box::new(w)); self }
18 pub fn children(mut self, ws: Vec<BoxedWidget>) -> Self { self.children.extend(ws); self }
19
20 fn arrange(&self, ctx: &LayoutCtx, max_w: f32) -> (Vec<Rect>, Size) {
22 let mut rects = Vec::with_capacity(self.children.len());
23 let (mut x, mut y, mut row_h, mut widest) = (0.0f32, 0.0f32, 0.0f32, 0.0f32);
24 for c in &self.children {
25 let s = c.layout(&ctx.with_constraints(Constraints::loose(max_w, f32::INFINITY)));
26 if x > 0.0 && x + s.width > max_w {
27 x = 0.0; y += row_h + self.run_spacing; row_h = 0.0;
28 }
29 rects.push(Rect { origin: Point { x, y }, size: s });
30 x += s.width + self.spacing;
31 row_h = row_h.max(s.height);
32 widest = widest.max(x - self.spacing);
33 }
34 (rects, Size { width: widest.min(max_w), height: y + row_h })
35 }
36}
37
38impl Default for Wrap { fn default() -> Self { Self::new() } }
39
40impl Widget for Wrap {
41 fn children(&self) -> Children<'_> { Children::Many(&self.children) }
42
43 fn layout(&self, ctx: &LayoutCtx) -> Size {
44 let w = avail_w(ctx.constraints);
50 let (_, size) = self.arrange(ctx, w);
51 ctx.constraints.constrain(Size { width: w, height: size.height })
52 }
53
54 fn paint(&self, ctx: &mut PaintCtx) {
55 let r = ctx.rect;
56 let (rects, _) = self.arrange(&ctx.layout_ctx(Constraints::loose(r.size.width, r.size.height)), r.size.width);
57 for (child, rel) in self.children.iter().zip(rects) {
58 let rect = Rect {
59 origin: Point { x: r.origin.x + rel.origin.x, y: r.origin.y + rel.origin.y },
60 size: rel.size,
61 };
62 child.paint(&mut ctx.child(rect));
63 }
64 }
65}