Return iterator for children for `LayoutTree` (#260)
1//! UI [`Node`] types and related data structures.
2//!
3//! Layouts are composed of multiple nodes, which live in a tree-like data structure.
4use slotmap::{DefaultKey, SlotMap, SparseSecondaryMap};
5
6/// A node in a layout.
7pub type Node = slotmap::DefaultKey;
8
9use crate::error::{TaffyError, TaffyResult};
10use crate::geometry::Size;
11use crate::layout::{AvailableSpace, Cache, Layout};
12use crate::prelude::LayoutTree;
13use crate::style::Style;
14#[cfg(any(feature = "std", feature = "alloc"))]
15use crate::sys::Box;
16use crate::sys::{new_vec_with_capacity, ChildrenVec, Vec};
17use crate::{data::NodeData, error};
18
19/// A function type that can be used in a [`MeasureFunc`]
20///
21/// This trait is automatically implemented for all types (including closures) that define a function with the appropriate type signature.
22pub trait Measurable: Send + Sync + Fn(Size<Option<f32>>, Size<AvailableSpace>) -> Size<f32> {}
23impl<F: Send + Sync + Fn(Size<Option<f32>>, Size<AvailableSpace>) -> Size<f32>> Measurable for F {}
24
25/// A function that can be used to compute the intrinsic size of a node
26pub enum MeasureFunc {
27 /// Stores an unboxed function
28 Raw(fn(Size<Option<f32>>, Size<AvailableSpace>) -> Size<f32>),
29
30 /// Stores a boxed function
31 #[cfg(any(feature = "std", feature = "alloc"))]
32 Boxed(Box<dyn Measurable>),
33}
34
35/// A tree of UI [`Nodes`](`Node`), suitable for UI layout
36pub struct Taffy {
37 /// The [`NodeData`] for each node stored in this tree
38 pub(crate) nodes: SlotMap<Node, NodeData>,
39
40 /// The mapping from the Size<AvailableSpace> (in real units) to Size<f32> (in points) for this node
41 pub(crate) measure_funcs: SparseSecondaryMap<Node, MeasureFunc>,
42
43 /// The children of each node
44 ///
45 /// The indexes in the outer vector correspond to the position of the parent [`NodeData`]
46 pub(crate) children: SlotMap<Node, ChildrenVec<Node>>,
47
48 /// The parents of each node
49 ///
50 /// The indexes in the outer vector correspond to the position of the child [`NodeData`]
51 pub(crate) parents: SlotMap<Node, Option<Node>>,
52}
53
54impl Default for Taffy {
55 fn default() -> Self {
56 Taffy::new()
57 }
58}
59
60impl LayoutTree for Taffy {
61 type ChildIter<'a> = std::slice::Iter<'a, DefaultKey>;
62
63 fn children(&self, node: Node) -> Self::ChildIter<'_> {
64 self.children[node].iter()
65 }
66
67 fn child_count(&self, node: Node) -> usize {
68 self.children[node].len()
69 }
70
71 fn is_childless(&self, node: Node) -> bool {
72 self.children[node].is_empty()
73 }
74
75 fn parent(&self, node: Node) -> Option<Node> {
76 self.parents.get(node).copied().flatten()
77 }
78
79 fn style(&self, node: Node) -> &Style {
80 &self.nodes[node].style
81 }
82
83 fn layout(&self, node: Node) -> &Layout {
84 &self.nodes[node].layout
85 }
86
87 fn layout_mut(&mut self, node: Node) -> &mut Layout {
88 &mut self.nodes[node].layout
89 }
90
91 #[inline(always)]
92 fn mark_dirty(&mut self, node: Node) -> TaffyResult<()> {
93 self.mark_dirty_internal(node)
94 }
95
96 fn measure_node(
97 &self,
98 node: Node,
99 known_dimensions: Size<Option<f32>>,
100 available_space: Size<AvailableSpace>,
101 ) -> Size<f32> {
102 match &self.measure_funcs[node] {
103 MeasureFunc::Raw(measure) => measure(known_dimensions, available_space),
104
105 #[cfg(any(feature = "std", feature = "alloc"))]
106 MeasureFunc::Boxed(measure) => (measure as &dyn Fn(_, _) -> _)(known_dimensions, available_space),
107 }
108 }
109
110 fn needs_measure(&self, node: Node) -> bool {
111 self.nodes[node].needs_measure && self.measure_funcs.get(node).is_some()
112 }
113
114 fn cache_mut(&mut self, node: Node, index: usize) -> &mut Option<Cache> {
115 &mut self.nodes[node].size_cache[index]
116 }
117
118 fn child(&self, node: Node, id: usize) -> Node {
119 self.children[node][id]
120 }
121}
122
123#[allow(clippy::iter_cloned_collect)] // due to no-std support, we need to use `iter_cloned` instead of `collect`
124impl Taffy {
125 /// Creates a new [`Taffy`]
126 ///
127 /// The default capacity of a [`Taffy`] is 16 nodes.
128 #[must_use]
129 pub fn new() -> Self {
130 Self::with_capacity(16)
131 }
132
133 /// Creates a new [`Taffy`] that can store `capacity` nodes before reallocation
134 #[must_use]
135 pub fn with_capacity(capacity: usize) -> Self {
136 Self {
137 // TODO: make this method const upstream,
138 // so constructors here can be const
139 nodes: SlotMap::with_capacity(capacity),
140 children: SlotMap::with_capacity(capacity),
141 parents: SlotMap::with_capacity(capacity),
142 measure_funcs: SparseSecondaryMap::with_capacity(capacity),
143 }
144 }
145
146 /// Creates and adds a new unattached leaf node to the tree, and returns the [`NodeId`] of the new node
147 pub fn new_leaf(&mut self, layout: Style) -> TaffyResult<Node> {
148 let id = self.nodes.insert(NodeData::new(layout));
149 let _ = self.children.insert(new_vec_with_capacity(0));
150 let _ = self.parents.insert(None);
151
152 Ok(id)
153 }
154
155 /// Creates and adds a new unattached leaf node to the tree, and returns the [`NodeId`] of the new node
156 ///
157 /// Creates and adds a new leaf node with a supplied [`MeasureFunc`]
158 pub fn new_leaf_with_measure(&mut self, layout: Style, measure: MeasureFunc) -> TaffyResult<Node> {
159 let mut data = NodeData::new(layout);
160 data.needs_measure = true;
161
162 let id = self.nodes.insert(data);
163 self.measure_funcs.insert(id, measure);
164
165 let _ = self.children.insert(new_vec_with_capacity(0));
166 let _ = self.parents.insert(None);
167
168 Ok(id)
169 }
170
171 /// Creates and adds a new node, which may have any number of `children`
172 pub fn new_with_children(&mut self, layout: Style, children: &[Node]) -> TaffyResult<Node> {
173 let id = self.nodes.insert(NodeData::new(layout));
174
175 for child in children {
176 self.parents[*child] = Some(id);
177 }
178
179 let _ = self.children.insert(children.iter().copied().collect::<_>());
180 let _ = self.parents.insert(None);
181
182 Ok(id)
183 }
184
185 /// Removes all nodes
186 ///
187 /// All associated [`Id`] will be rendered invalid.
188 pub fn clear(&mut self) {
189 self.nodes.clear();
190 self.children.clear();
191 self.parents.clear();
192 }
193
194 /// Remove a specific [`Node`] from the tree
195 ///
196 /// Its [`Id`] is marked as invalid. Returns the id of the node removed.
197 pub fn remove(&mut self, node: Node) -> TaffyResult<Node> {
198 if let Some(parent) = self.parents[node] {
199 if let Some(children) = self.children.get_mut(parent) {
200 children.retain(|f| *f != node);
201 }
202 }
203
204 let _ = self.children.remove(node);
205 let _ = self.parents.remove(node);
206 let _ = self.nodes.remove(node);
207
208 Ok(node)
209 }
210
211 /// Sets the [`MeasureFunc`] of the associated node
212 pub fn set_measure(&mut self, node: Node, measure: Option<MeasureFunc>) -> TaffyResult<()> {
213 if let Some(measure) = measure {
214 self.nodes[node].needs_measure = true;
215 self.measure_funcs.insert(node, measure);
216 } else {
217 self.nodes[node].needs_measure = false;
218 self.measure_funcs.remove(node);
219 }
220
221 self.mark_dirty_internal(node)?;
222
223 Ok(())
224 }
225
226 /// Adds a `child` [`Node`] under the supplied `parent`
227 pub fn add_child(&mut self, parent: Node, child: Node) -> TaffyResult<()> {
228 self.parents[child] = Some(parent);
229 self.children[parent].push(child);
230 self.mark_dirty_internal(parent)?;
231
232 Ok(())
233 }
234
235 /// Directly sets the `children` of the supplied `parent`
236 pub fn set_children(&mut self, parent: Node, children: &[Node]) -> TaffyResult<()> {
237 // Remove node as parent from all its current children.
238 for child in &self.children[parent] {
239 self.parents[*child] = None;
240 }
241
242 // Build up relation node <-> child
243 for child in children {
244 self.parents[*child] = Some(parent);
245 }
246
247 self.children[parent] = children.iter().copied().collect::<_>();
248
249 self.mark_dirty_internal(parent)?;
250
251 Ok(())
252 }
253
254 /// Removes the `child` of the parent `node`
255 ///
256 /// The child is not removed from the tree entirely, it is simply no longer attached to its previous parent.
257 pub fn remove_child(&mut self, parent: Node, child: Node) -> TaffyResult<Node> {
258 let index = self.children[parent].iter().position(|n| *n == child).unwrap();
259 self.remove_child_at_index(parent, index)
260 }
261
262 /// Removes the child at the given `index` from the `parent`
263 ///
264 /// The child is not removed from the tree entirely, it is simply no longer attached to its previous parent.
265 pub fn remove_child_at_index(&mut self, parent: Node, child_index: usize) -> TaffyResult<Node> {
266 let child_count = self.children[parent].len();
267 if child_index >= child_count {
268 return Err(error::TaffyError::ChildIndexOutOfBounds { parent, child_index, child_count });
269 }
270
271 let child = self.children[parent].remove(child_index);
272 self.parents[child] = None;
273
274 self.mark_dirty_internal(parent)?;
275
276 Ok(child)
277 }
278
279 /// Replaces the child at the given `child_index` from the `parent` node with the new `child` node
280 ///
281 /// The child is not removed from the tree entirely, it is simply no longer attached to its previous parent.
282 pub fn replace_child_at_index(&mut self, parent: Node, child_index: usize, new_child: Node) -> TaffyResult<Node> {
283 let child_count = self.children[parent].len();
284 if child_index >= child_count {
285 return Err(error::TaffyError::ChildIndexOutOfBounds { parent, child_index, child_count });
286 }
287
288 self.parents[new_child] = Some(parent);
289 let old_child = core::mem::replace(&mut self.children[parent][child_index], new_child);
290 self.parents[old_child] = None;
291
292 self.mark_dirty_internal(parent)?;
293
294 Ok(old_child)
295 }
296
297 /// Returns the child [`Node`] of the parent `node` at the provided `child_index`
298 pub fn child_at_index(&self, parent: Node, child_index: usize) -> TaffyResult<Node> {
299 let child_count = self.children[parent].len();
300 if child_index >= child_count {
301 return Err(error::TaffyError::ChildIndexOutOfBounds { parent, child_index, child_count });
302 }
303
304 Ok(self.children[parent][child_index])
305 }
306
307 /// Returns the number of children of the `parent` [`Node`]
308 pub fn child_count(&self, parent: Node) -> TaffyResult<usize> {
309 Ok(self.children[parent].len())
310 }
311
312 /// Returns a list of children that belong to the [`Parent`]
313 pub fn children(&self, parent: Node) -> TaffyResult<Vec<Node>> {
314 Ok(self.children[parent].iter().copied().collect::<_>())
315 }
316
317 /// Sets the [`Style`] of the provided `node`
318 pub fn set_style(&mut self, node: Node, style: Style) -> TaffyResult<()> {
319 self.nodes[node].style = style;
320 self.mark_dirty_internal(node)?;
321 Ok(())
322 }
323
324 /// Gets the [`Style`] of the provided `node`
325 pub fn style(&self, node: Node) -> TaffyResult<&Style> {
326 Ok(&self.nodes[node].style)
327 }
328
329 /// Return this node layout relative to its parent
330 pub fn layout(&self, node: Node) -> TaffyResult<&Layout> {
331 Ok(&self.nodes[node].layout)
332 }
333
334 /// Marks the layout computation of this node and its children as outdated
335 ///
336 /// Performs a recursive depth-first search up the tree until the root node is reached
337 ///
338 /// WARNING: this will stack-overflow if the tree contains a cycle
339 fn mark_dirty_internal(&mut self, node: Node) -> TaffyResult<()> {
340 /// WARNING: this will stack-overflow if the tree contains a cycle
341 fn mark_dirty_recursive(
342 nodes: &mut SlotMap<Node, NodeData>,
343 parents: &SlotMap<Node, Option<Node>>,
344 node_id: Node,
345 ) {
346 nodes[node_id].mark_dirty();
347
348 if let Some(Some(node)) = parents.get(node_id) {
349 mark_dirty_recursive(nodes, parents, *node);
350 }
351 }
352
353 mark_dirty_recursive(&mut self.nodes, &self.parents, node);
354
355 Ok(())
356 }
357
358 /// Indicates whether the layout of this node (and its children) need to be recomputed
359 pub fn dirty(&self, node: Node) -> TaffyResult<bool> {
360 Ok(self.nodes[node].size_cache.iter().all(|entry| entry.is_none()))
361 }
362
363 /// Updates the stored layout of the provided `node` and its children
364 pub fn compute_layout(&mut self, node: Node, available_space: Size<AvailableSpace>) -> Result<(), TaffyError> {
365 crate::compute::compute_layout(self, node, available_space)
366 }
367}
368
369#[cfg(test)]
370mod tests {
371 #![allow(clippy::bool_assert_comparison)]
372
373 use super::*;
374 use crate::{
375 style::{Dimension, Display, FlexDirection},
376 sys,
377 };
378
379 #[test]
380 fn new_should_allocate_default_capacity() {
381 const DEFAULT_CAPACITY: usize = 16; // This is the capacity defined in the `impl Default`
382 let taffy = Taffy::new();
383
384 assert!(taffy.children.capacity() >= DEFAULT_CAPACITY);
385 assert!(taffy.parents.capacity() >= DEFAULT_CAPACITY);
386 assert!(taffy.nodes.capacity() >= DEFAULT_CAPACITY);
387 }
388
389 #[test]
390 fn test_with_capacity() {
391 const CAPACITY: usize = 8;
392 let taffy = Taffy::with_capacity(CAPACITY);
393
394 assert!(taffy.children.capacity() >= CAPACITY);
395 assert!(taffy.parents.capacity() >= CAPACITY);
396 assert!(taffy.nodes.capacity() >= CAPACITY);
397 }
398
399 #[test]
400 fn test_new_leaf() {
401 let mut taffy = Taffy::new();
402
403 let res = taffy.new_leaf(Style::default());
404 assert!(res.is_ok());
405 let node = res.unwrap();
406
407 // node should be in the taffy tree and have no children
408 assert!(taffy.child_count(node).unwrap() == 0);
409 }
410
411 #[test]
412 fn new_leaf_with_measure() {
413 let mut taffy = Taffy::new();
414
415 let res = taffy.new_leaf_with_measure(Style::default(), MeasureFunc::Raw(|_, _| Size::ZERO));
416 assert!(res.is_ok());
417 let node = res.unwrap();
418
419 // node should be in the taffy tree and have no children
420 assert!(taffy.child_count(node).unwrap() == 0);
421 }
422
423 /// Test that new_with_children works as expected
424 #[test]
425 fn test_new_with_children() {
426 let mut taffy = Taffy::new();
427 let child0 = taffy.new_leaf(Style::default()).unwrap();
428 let child1 = taffy.new_leaf(Style::default()).unwrap();
429 let node = taffy.new_with_children(Style::default(), &[child0, child1]).unwrap();
430
431 // node should have two children
432 assert_eq!(taffy.child_count(node).unwrap(), 2);
433 assert_eq!(taffy.children(node).unwrap()[0], child0);
434 assert_eq!(taffy.children(node).unwrap()[1], child1);
435 }
436
437 #[test]
438 fn remove_node_should_remove() {
439 let mut taffy = Taffy::new();
440
441 let node = taffy.new_leaf(Style::default()).unwrap();
442
443 let _ = taffy.remove(node).unwrap();
444 }
445
446 #[test]
447 fn remove_node_should_detach_herarchy() {
448 let mut taffy = Taffy::new();
449
450 // Build a linear tree layout: <0> <- <1> <- <2>
451 let node2 = taffy.new_leaf(Style::default()).unwrap();
452 let node1 = taffy.new_with_children(Style::default(), &[node2]).unwrap();
453 let node0 = taffy.new_with_children(Style::default(), &[node1]).unwrap();
454
455 // Both node0 and node1 should have 1 child nodes
456 assert_eq!(taffy.children(node0).unwrap().as_slice(), &[node1]);
457 assert_eq!(taffy.children(node1).unwrap().as_slice(), &[node2]);
458
459 // Disconnect the tree: <0> <2>
460 let _ = taffy.remove(node1).unwrap();
461
462 // Both remaining nodes should have no child nodes
463 assert!(taffy.children(node0).unwrap().is_empty());
464 assert!(taffy.children(node2).unwrap().is_empty());
465 }
466
467 #[test]
468 fn remove_last_node() {
469 let mut taffy = Taffy::new();
470
471 let parent = taffy.new_leaf(Style::default()).unwrap();
472 let child = taffy.new_leaf(Style::default()).unwrap();
473 taffy.add_child(parent, child).unwrap();
474
475 taffy.remove(child).unwrap();
476 taffy.remove(parent).unwrap();
477 }
478
479 #[test]
480 fn set_measure() {
481 let mut taffy = Taffy::new();
482 let node = taffy
483 .new_leaf_with_measure(Style::default(), MeasureFunc::Raw(|_, _| Size { width: 200.0, height: 200.0 }))
484 .unwrap();
485 taffy.compute_layout(node, Size::MAX_CONTENT).unwrap();
486 assert_eq!(taffy.layout(node).unwrap().size.width, 200.0);
487
488 taffy.set_measure(node, Some(MeasureFunc::Raw(|_, _| Size { width: 100.0, height: 100.0 }))).unwrap();
489 taffy.compute_layout(node, Size::MAX_CONTENT).unwrap();
490 assert_eq!(taffy.layout(node).unwrap().size.width, 100.0);
491 }
492
493 #[test]
494 fn set_measure_of_previously_unmeasured_node() {
495 let mut taffy = Taffy::new();
496 let node = taffy.new_leaf(Style::default()).unwrap();
497 taffy.compute_layout(node, Size::MAX_CONTENT).unwrap();
498 assert_eq!(taffy.layout(node).unwrap().size.width, 0.0);
499
500 taffy.set_measure(node, Some(MeasureFunc::Raw(|_, _| Size { width: 100.0, height: 100.0 }))).unwrap();
501 taffy.compute_layout(node, Size::MAX_CONTENT).unwrap();
502 assert_eq!(taffy.layout(node).unwrap().size.width, 100.0);
503 }
504
505 /// Test that adding `add_child()` works
506 #[test]
507 fn add_child() {
508 let mut taffy = Taffy::new();
509 let node = taffy.new_leaf(Style::default()).unwrap();
510 assert_eq!(taffy.child_count(node).unwrap(), 0);
511
512 let child0 = taffy.new_leaf(Style::default()).unwrap();
513 taffy.add_child(node, child0).unwrap();
514 assert_eq!(taffy.child_count(node).unwrap(), 1);
515
516 let child1 = taffy.new_leaf(Style::default()).unwrap();
517 taffy.add_child(node, child1).unwrap();
518 assert_eq!(taffy.child_count(node).unwrap(), 2);
519 }
520
521 #[test]
522 fn set_children() {
523 let mut taffy = Taffy::new();
524
525 let child0 = taffy.new_leaf(Style::default()).unwrap();
526 let child1 = taffy.new_leaf(Style::default()).unwrap();
527 let node = taffy.new_with_children(Style::default(), &[child0, child1]).unwrap();
528
529 assert_eq!(taffy.child_count(node).unwrap(), 2);
530 assert_eq!(taffy.children(node).unwrap()[0], child0);
531 assert_eq!(taffy.children(node).unwrap()[1], child1);
532
533 let child2 = taffy.new_leaf(Style::default()).unwrap();
534 let child3 = taffy.new_leaf(Style::default()).unwrap();
535 taffy.set_children(node, &[child2, child3]).unwrap();
536
537 assert_eq!(taffy.child_count(node).unwrap(), 2);
538 assert_eq!(taffy.children(node).unwrap()[0], child2);
539 assert_eq!(taffy.children(node).unwrap()[1], child3);
540 }
541
542 /// Test that removing a child works
543 #[test]
544 fn remove_child() {
545 let mut taffy = Taffy::new();
546 let child0 = taffy.new_leaf(Style::default()).unwrap();
547 let child1 = taffy.new_leaf(Style::default()).unwrap();
548 let node = taffy.new_with_children(Style::default(), &[child0, child1]).unwrap();
549
550 assert_eq!(taffy.child_count(node).unwrap(), 2);
551
552 taffy.remove_child(node, child0).unwrap();
553 assert_eq!(taffy.child_count(node).unwrap(), 1);
554 assert_eq!(taffy.children(node).unwrap()[0], child1);
555
556 taffy.remove_child(node, child1).unwrap();
557 assert_eq!(taffy.child_count(node).unwrap(), 0);
558 }
559
560 #[test]
561 fn remove_child_at_index() {
562 let mut taffy = Taffy::new();
563 let child0 = taffy.new_leaf(Style::default()).unwrap();
564 let child1 = taffy.new_leaf(Style::default()).unwrap();
565 let node = taffy.new_with_children(Style::default(), &[child0, child1]).unwrap();
566
567 assert_eq!(taffy.child_count(node).unwrap(), 2);
568
569 taffy.remove_child_at_index(node, 0).unwrap();
570 assert_eq!(taffy.child_count(node).unwrap(), 1);
571 assert_eq!(taffy.children(node).unwrap()[0], child1);
572
573 taffy.remove_child_at_index(node, 0).unwrap();
574 assert_eq!(taffy.child_count(node).unwrap(), 0);
575 }
576
577 #[test]
578 fn replace_child_at_index() {
579 let mut taffy = Taffy::new();
580
581 let child0 = taffy.new_leaf(Style::default()).unwrap();
582 let child1 = taffy.new_leaf(Style::default()).unwrap();
583
584 let node = taffy.new_with_children(Style::default(), &[child0]).unwrap();
585 assert_eq!(taffy.child_count(node).unwrap(), 1);
586 assert_eq!(taffy.children(node).unwrap()[0], child0);
587
588 taffy.replace_child_at_index(node, 0, child1).unwrap();
589 assert_eq!(taffy.child_count(node).unwrap(), 1);
590 assert_eq!(taffy.children(node).unwrap()[0], child1);
591 }
592 #[test]
593 fn test_child_at_index() {
594 let mut taffy = Taffy::new();
595 let child0 = taffy.new_leaf(Style::default()).unwrap();
596 let child1 = taffy.new_leaf(Style::default()).unwrap();
597 let child2 = taffy.new_leaf(Style::default()).unwrap();
598 let node = taffy.new_with_children(Style::default(), &[child0, child1, child2]).unwrap();
599
600 assert!(if let Ok(result) = taffy.child_at_index(node, 0) { result == child0 } else { false });
601 assert!(if let Ok(result) = taffy.child_at_index(node, 1) { result == child1 } else { false });
602 assert!(if let Ok(result) = taffy.child_at_index(node, 2) { result == child2 } else { false });
603 }
604 #[test]
605 fn test_child_count() {
606 let mut taffy = Taffy::new();
607 let child0 = taffy.new_leaf(Style::default()).unwrap();
608 let child1 = taffy.new_leaf(Style::default()).unwrap();
609 let node = taffy.new_with_children(Style::default(), &[child0, child1]).unwrap();
610
611 assert!(if let Ok(count) = taffy.child_count(node) { count == 2 } else { false });
612 assert!(if let Ok(count) = taffy.child_count(child0) { count == 0 } else { false });
613 assert!(if let Ok(count) = taffy.child_count(child1) { count == 0 } else { false });
614 }
615
616 #[allow(clippy::vec_init_then_push)]
617 #[test]
618 fn test_children() {
619 let mut taffy = Taffy::new();
620 let child0 = taffy.new_leaf(Style::default()).unwrap();
621 let child1 = taffy.new_leaf(Style::default()).unwrap();
622 let node = taffy.new_with_children(Style::default(), &[child0, child1]).unwrap();
623
624 let mut children: sys::Vec<Node> = sys::Vec::new();
625 children.push(child0);
626 children.push(child1);
627
628 let children_result = taffy.children(node).unwrap();
629 assert_eq!(children_result, children);
630
631 assert!(taffy.children(child0).unwrap().is_empty());
632 }
633 #[test]
634 fn test_set_style() {
635 let mut taffy = Taffy::new();
636
637 let node = taffy.new_leaf(Style::default()).unwrap();
638 assert_eq!(taffy.style(node).unwrap().display, Display::Flex);
639
640 taffy.set_style(node, Style { display: Display::None, ..Style::default() }).unwrap();
641 assert_eq!(taffy.style(node).unwrap().display, Display::None);
642 }
643 #[test]
644 fn test_style() {
645 let mut taffy = Taffy::new();
646
647 let style = Style { display: Display::None, flex_direction: FlexDirection::RowReverse, ..Default::default() };
648
649 let node = taffy.new_leaf(style).unwrap();
650
651 let res = taffy.style(node);
652 assert!(res.is_ok());
653 assert!(res.unwrap() == &style);
654 }
655 #[test]
656 fn test_layout() {
657 let mut taffy = Taffy::new();
658 let node = taffy.new_leaf(Style::default()).unwrap();
659
660 // TODO: Improve this test?
661 let res = taffy.layout(node);
662 assert!(res.is_ok());
663 }
664
665 #[test]
666 fn test_mark_dirty() {
667 let mut taffy = Taffy::new();
668 let child0 = taffy.new_leaf(Style::default()).unwrap();
669 let child1 = taffy.new_leaf(Style::default()).unwrap();
670 let node = taffy.new_with_children(Style::default(), &[child0, child1]).unwrap();
671
672 taffy.compute_layout(node, Size::MAX_CONTENT).unwrap();
673
674 assert_eq!(taffy.dirty(child0).unwrap(), false);
675 assert_eq!(taffy.dirty(child1).unwrap(), false);
676 assert_eq!(taffy.dirty(node).unwrap(), false);
677
678 taffy.mark_dirty(node).unwrap();
679 assert_eq!(taffy.dirty(child0).unwrap(), false);
680 assert_eq!(taffy.dirty(child1).unwrap(), false);
681 assert_eq!(taffy.dirty(node).unwrap(), true);
682
683 taffy.compute_layout(node, Size::MAX_CONTENT).unwrap();
684 taffy.mark_dirty(child0).unwrap();
685 assert_eq!(taffy.dirty(child0).unwrap(), true);
686 assert_eq!(taffy.dirty(child1).unwrap(), false);
687 assert_eq!(taffy.dirty(node).unwrap(), true);
688 }
689
690 #[test]
691 fn compute_layout_should_produce_valid_result() {
692 let mut taffy = Taffy::new();
693 let node_result = taffy.new_leaf(Style {
694 size: Size { width: Dimension::Points(10f32), height: Dimension::Points(10f32) },
695 ..Default::default()
696 });
697 assert!(node_result.is_ok());
698 let node = node_result.unwrap();
699 let layout_result = taffy.compute_layout(
700 node,
701 Size { width: AvailableSpace::Definite(100.), height: AvailableSpace::Definite(100.) },
702 );
703 assert!(layout_result.is_ok());
704 }
705
706 #[test]
707 fn measure_func_is_send_and_sync() {
708 fn is_send_and_sync<T: Send + Sync>() {}
709 is_send_and_sync::<MeasureFunc>();
710 }
711}