Change signature of mark_dirty method to match taffy 0.1 (#253)
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}