tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5544Rust 88Markdown 11TOML 91926 Definiciones

⎇ dfaec22a1b31ebce5f35169e9af99807bb93a1b4 src/node.rs Rust · 701 líneas · 24.8 KB Historia Quién tocó qué crudo

Change signature of mark_dirty method to match taffy 0.1 (#253) dfaec22a1 · Nico Burns ·

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