agpu/layout/
constraint.rs1use crate::core::Rect;
4use crate::layout::{DesiredSize, Layout, SizeConstraints};
5
6#[derive(Debug, Clone, Copy)]
8pub struct MinMax {
9 pub min: f32,
10 pub max: f32,
11}
12
13impl MinMax {
14 pub fn new(min: f32, max: f32) -> Self {
15 Self { min, max }
16 }
17
18 pub fn clamp(&self, value: f32) -> f32 {
19 value.clamp(self.min, self.max)
20 }
21}
22
23#[derive(Debug, Clone)]
25pub struct ConstraintRule {
26 pub index: usize,
27 pub width: Option<MinMax>,
28 pub height: Option<MinMax>,
29}
30
31impl ConstraintRule {
32 pub fn new(index: usize) -> Self {
33 Self {
34 index,
35 width: None,
36 height: None,
37 }
38 }
39
40 pub fn width(mut self, constraint: MinMax) -> Self {
41 self.width = Some(constraint);
42 self
43 }
44
45 pub fn height(mut self, constraint: MinMax) -> Self {
46 self.height = Some(constraint);
47 self
48 }
49}
50
51pub struct ConstraintLayout {
53 rules: Vec<ConstraintRule>,
54}
55
56impl ConstraintLayout {
57 pub fn new() -> Self {
58 Self { rules: Vec::new() }
59 }
60
61 pub fn rule(mut self, rule: ConstraintRule) -> Self {
62 self.rules.push(rule);
63 self
64 }
65
66 fn constrain(&self, index: usize, width: f32, height: f32) -> (f32, f32) {
67 if let Some(rule) = self.rules.iter().find(|r| r.index == index) {
68 let w = rule.width.as_ref().map_or(width, |c| c.clamp(width));
69 let h = rule.height.as_ref().map_or(height, |c| c.clamp(height));
70 (w, h)
71 } else {
72 (width, height)
73 }
74 }
75}
76
77impl Default for ConstraintLayout {
78 fn default() -> Self {
79 Self::new()
80 }
81}
82
83impl Layout for ConstraintLayout {
84 fn measure(&self, children: &[DesiredSize], constraints: SizeConstraints) -> DesiredSize {
85 if children.is_empty() {
86 return DesiredSize::zero();
87 }
88 let mut total_h = 0.0f32;
90 let mut max_w = 0.0f32;
91 for (i, child) in children.iter().enumerate() {
92 let (w, h) = self.constrain(i, child.width, child.height);
93 max_w = max_w.max(w);
94 total_h += h;
95 }
96 let (w, h) = constraints.clamp(max_w, total_h);
97 DesiredSize::new(w, h)
98 }
99
100 fn arrange(&self, children: &[DesiredSize], area: Rect) -> Vec<Rect> {
101 let mut rects = Vec::with_capacity(children.len());
102 let mut y = area.y;
103 for (i, child) in children.iter().enumerate() {
104 let (w, h) = self.constrain(i, child.width, child.height);
105 rects.push(Rect::new(area.x, y, w, h));
106 y += h;
107 }
108 rects
109 }
110}