1use deref_derive::{Deref, DerefMut};
2use glam::Vec2;
3use ori_graphics::Rect;
4use smallvec::SmallVec;
5
6use crate::{
7 AlignItems, Axis, BoxConstraints, DrawContext, Event, EventContext, JustifyContent,
8 LayoutContext, Node,
9};
10
11pub struct FlexLayout {
13 pub offset: Vec2,
17 pub axis: Axis,
19 pub justify_content: JustifyContent,
21 pub align_items: AlignItems,
23 pub gap: f32,
25}
26
27impl Default for FlexLayout {
28 fn default() -> Self {
29 Self {
30 offset: Vec2::ZERO,
31 axis: Axis::Vertical,
32 justify_content: JustifyContent::Start,
33 align_items: AlignItems::Start,
34 gap: 0.0,
35 }
36 }
37}
38
39impl FlexLayout {
40 pub fn new() -> Self {
41 Self::default()
42 }
43
44 pub fn vertical() -> Self {
45 Self {
46 axis: Axis::Vertical,
47 ..Self::default()
48 }
49 }
50
51 pub fn horizontal() -> Self {
52 Self {
53 axis: Axis::Horizontal,
54 ..Self::default()
55 }
56 }
57
58 pub fn row() -> Self {
59 Self::horizontal()
60 }
61
62 pub fn column() -> Self {
63 Self::vertical()
64 }
65}
66
67#[derive(Default, Deref, DerefMut)]
68pub struct Children {
69 nodes: Vec<Node>,
70}
71
72impl Children {
73 pub const fn new() -> Self {
74 Self { nodes: Vec::new() }
75 }
76
77 pub fn len(&self) -> usize {
78 self.nodes.len()
79 }
80
81 pub fn is_empty(&self) -> bool {
82 self.nodes.is_empty()
83 }
84
85 pub fn add_child(&mut self, child: impl Into<Node>) {
86 self.nodes.push(child.into());
87 }
88
89 pub fn event(&self, cx: &mut EventContext, event: &Event) {
91 for child in self.iter() {
92 child.event(cx, event);
93 }
94 }
95
96 pub fn flex_layout(
98 &self,
99 cx: &mut LayoutContext,
100 bc: BoxConstraints,
101 flex: FlexLayout,
102 ) -> Vec2 {
103 let FlexLayout {
104 offset,
105 axis,
106 justify_content,
107 align_items,
108 gap,
109 } = flex;
110
111 let max_minor = axis.minor(bc.max);
112 let min_minor = axis.minor(bc.min);
113
114 let max_major = axis.major(bc.max);
115 let min_major = axis.major(bc.min);
116
117 let mut minor = min_minor;
118 let mut major = 0.0f32;
119
120 let mut children = SmallVec::<[f32; 8]>::with_capacity(self.len());
125 for (i, child) in self.iter().enumerate() {
126 let child_bc = BoxConstraints {
127 min: axis.pack(0.0, 0.0),
128 max: axis.pack(max_major, max_minor),
129 };
130 let size = child.layout(cx, child_bc);
131 let child_minor = axis.minor(size);
132 let child_major = axis.major(size);
133
134 children.push(child_major);
135
136 minor = minor.max(child_minor);
137 major += child_major;
138
139 if i > 0 {
140 major += gap;
141 }
142 }
143
144 if align_items == AlignItems::Stretch {
145 major = 0.0;
147 children.clear();
148
149 for (i, child) in self.iter().enumerate() {
150 let child_bc = BoxConstraints {
151 min: axis.pack(0.0, minor),
152 max: axis.pack(max_major, minor),
153 };
154 let size = child.layout(cx, child_bc);
158 let child_major = axis.major(size);
159
160 children.push(child_major);
161
162 major += child_major;
163
164 if i > 0 {
165 major += gap;
166 }
167 }
168 }
169
170 major = major.max(min_major);
171
172 let child_offsets = justify_content.justify(&children, major, gap);
173
174 for (child, align_major) in self.iter().zip(child_offsets) {
176 let child_minor = axis.minor(child.size());
177 let align_minor = align_items.align(0.0, minor, child_minor);
178
179 let child_offset = axis.pack(align_major, align_minor);
180 child.set_offset(offset + child_offset);
181 }
182
183 axis.pack(major, minor)
184 }
185
186 pub fn local_rect(&self) -> Rect {
187 let mut rect = None;
188
189 for child in self.iter() {
190 let rect = rect.get_or_insert_with(|| child.local_rect());
191 *rect = rect.union(child.local_rect());
192 }
193
194 rect.unwrap_or_default()
195 }
196
197 pub fn rect(&self) -> Rect {
198 let mut rect = None;
199
200 for child in self.iter() {
201 let rect = rect.get_or_insert_with(|| child.global_rect());
202 *rect = rect.union(child.global_rect());
203 }
204
205 rect.unwrap_or_default()
206 }
207
208 pub fn size(&self) -> Vec2 {
209 self.rect().size()
210 }
211
212 pub fn set_offset(&self, offset: Vec2) {
213 if self.is_empty() {
214 return;
215 }
216
217 let min = self.local_rect().min;
218
219 for child in self.iter() {
220 let child_offset = child.local_rect().min - min;
221 child.set_offset(offset + child_offset);
222 }
223 }
224
225 pub fn draw(&self, cx: &mut DrawContext) {
226 for child in self.iter() {
227 child.draw(cx);
228 }
229 }
230}
231
232impl IntoIterator for Children {
233 type Item = Node;
234 type IntoIter = std::vec::IntoIter<Self::Item>;
235
236 fn into_iter(self) -> Self::IntoIter {
237 self.nodes.into_iter()
238 }
239}
240
241impl<'a> IntoIterator for &'a Children {
242 type Item = &'a Node;
243 type IntoIter = std::slice::Iter<'a, Node>;
244
245 fn into_iter(self) -> Self::IntoIter {
246 self.nodes.iter()
247 }
248}
249
250impl<'a> IntoIterator for &'a mut Children {
251 type Item = &'a mut Node;
252 type IntoIter = std::slice::IterMut<'a, Node>;
253
254 fn into_iter(self) -> Self::IntoIter {
255 self.nodes.iter_mut()
256 }
257}