1use slotmap::{DefaultKey, SlotMap, SparseSecondaryMap};
3
4use crate::geometry::Size;
5use crate::style::{AvailableSpace, Display, Style};
6use crate::tree::{Cache, Layout, LayoutInput, LayoutOutput, LayoutTree, NodeData, NodeId, PartialLayoutTree, RunMode};
7use crate::util::debug::{debug_log, debug_log_node};
8use crate::util::sys::{new_vec_with_capacity, ChildrenVec, Vec};
9
10#[cfg(feature = "block_layout")]
11use crate::compute::compute_block_layout;
12#[cfg(feature = "flexbox")]
13use crate::compute::compute_flexbox_layout;
14#[cfg(feature = "grid")]
15use crate::compute::compute_grid_layout;
16use crate::compute::{compute_cached_layout, compute_hidden_layout, compute_layout, compute_leaf_layout, round_layout};
17
18pub type TaffyResult<T> = Result<T, TaffyError>;
20
21#[derive(Debug)]
23pub enum TaffyError {
24 ChildIndexOutOfBounds {
26 parent: NodeId,
28 child_index: usize,
30 child_count: usize,
32 },
33 InvalidParentNode(NodeId),
35 InvalidChildNode(NodeId),
37 InvalidInputNode(NodeId),
39}
40
41impl core::fmt::Display for TaffyError {
42 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
43 match self {
44 TaffyError::ChildIndexOutOfBounds { parent, child_index, child_count } => {
45 write!(f, "Index (is {child_index}) should be < child_count ({child_count}) for parent node {parent:?}")
46 }
47 TaffyError::InvalidParentNode(parent) => {
48 write!(f, "Parent Node {parent:?} is not in the TaffyTree instance")
49 }
50 TaffyError::InvalidChildNode(child) => write!(f, "Child Node {child:?} is not in the TaffyTree instance"),
51 TaffyError::InvalidInputNode(node) => write!(f, "Supplied Node {node:?} is not in the TaffyTree instance"),
52 }
53 }
54}
55
56#[cfg(feature = "std")]
57impl std::error::Error for TaffyError {}
58
59pub(crate) struct TaffyConfig {
61 pub(crate) use_rounding: bool,
63}
64
65impl Default for TaffyConfig {
66 fn default() -> Self {
67 Self { use_rounding: true }
68 }
69}
70
71pub struct TaffyTree<NodeContext = ()> {
75 pub(crate) nodes: SlotMap<DefaultKey, NodeData>,
77
78 pub(crate) node_context_data: SparseSecondaryMap<DefaultKey, NodeContext>,
80
81 pub(crate) children: SlotMap<DefaultKey, ChildrenVec<NodeId>>,
85
86 pub(crate) parents: SlotMap<DefaultKey, Option<NodeId>>,
90
91 pub(crate) config: TaffyConfig,
93}
94
95impl Default for TaffyTree {
96 fn default() -> TaffyTree<()> {
97 TaffyTree::new()
98 }
99}
100
101pub(crate) struct TaffyChildIter<'a>(core::slice::Iter<'a, NodeId>);
103impl<'a> Iterator for TaffyChildIter<'a> {
104 type Item = NodeId;
105
106 fn next(&mut self) -> Option<Self::Item> {
107 self.0.next().copied()
108 }
109}
110
111pub(crate) struct TaffyView<'t, NodeContext, MeasureFunction>
115where
116 MeasureFunction: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>) -> Size<f32>,
117{
118 pub(crate) taffy: &'t mut TaffyTree<NodeContext>,
120 pub(crate) measure_function: MeasureFunction,
122}
123
124impl<'t, NodeContext, MeasureFunction> PartialLayoutTree for TaffyView<'t, NodeContext, MeasureFunction>
125where
126 MeasureFunction: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>) -> Size<f32>,
127{
128 type ChildIter<'a> = TaffyChildIter<'a> where Self: 'a;
129
130 #[inline(always)]
131 fn child_ids(&self, node: NodeId) -> Self::ChildIter<'_> {
132 TaffyChildIter(self.taffy.children[node.into()].iter())
133 }
134
135 #[inline(always)]
136 fn child_count(&self, node: NodeId) -> usize {
137 self.taffy.children[node.into()].len()
138 }
139
140 #[inline(always)]
141 fn get_child_id(&self, node: NodeId, id: usize) -> NodeId {
142 self.taffy.children[node.into()][id]
143 }
144
145 #[inline(always)]
146 fn get_style(&self, node: NodeId) -> &Style {
147 &self.taffy.nodes[node.into()].style
148 }
149
150 #[inline(always)]
151 fn get_cache_mut(&mut self, node: NodeId) -> &mut Cache {
152 &mut self.taffy.nodes[node.into()].cache
153 }
154
155 #[inline(always)]
156 fn set_unrounded_layout(&mut self, node_id: NodeId, layout: &Layout) {
157 self.taffy.nodes[node_id.into()].unrounded_layout = *layout;
158 }
159
160 #[inline(always)]
161 fn compute_child_layout(&mut self, node: NodeId, inputs: LayoutInput) -> LayoutOutput {
162 if inputs.run_mode == RunMode::PerformHiddenLayout {
165 debug_log!("HIDDEN");
166 return compute_hidden_layout(self, node);
167 }
168
169 compute_cached_layout(self, node, inputs, |tree, node, inputs| {
175 let display_mode = tree.get_style(node).display;
176 let has_children = tree.child_count(node) > 0;
177
178 debug_log!(display_mode);
179 debug_log_node!(
180 inputs.known_dimensions,
181 inputs.parent_size,
182 inputs.available_space,
183 inputs.run_mode,
184 inputs.sizing_mode
185 );
186
187 match (display_mode, has_children) {
189 (Display::None, _) => compute_hidden_layout(tree, node),
190 #[cfg(feature = "block_layout")]
191 (Display::Block, true) => compute_block_layout(tree, node, inputs),
192 #[cfg(feature = "flexbox")]
193 (Display::Flex, true) => compute_flexbox_layout(tree, node, inputs),
194 #[cfg(feature = "grid")]
195 (Display::Grid, true) => compute_grid_layout(tree, node, inputs),
196 (_, false) => {
197 let node_key = node.into();
198 let style = &tree.taffy.nodes[node_key].style;
199 let needs_measure = tree.taffy.nodes[node_key].needs_measure;
200 let measure_function = needs_measure.then_some(|known_dimensions, available_space| {
201 let node_context = tree.taffy.node_context_data.get_mut(node_key);
202 (tree.measure_function)(known_dimensions, available_space, node, node_context)
203 });
204 compute_leaf_layout(inputs, style, measure_function)
205 }
206 }
207 })
208 }
209}
210
211impl<'t, NodeContext, MeasureFunction> LayoutTree for TaffyView<'t, NodeContext, MeasureFunction>
212where
213 MeasureFunction: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>) -> Size<f32>,
214{
215 #[inline(always)]
216 fn get_unrounded_layout(&self, node: NodeId) -> &Layout {
217 &self.taffy.nodes[node.into()].unrounded_layout
218 }
219
220 #[inline(always)]
221 fn get_final_layout(&self, node: NodeId) -> &Layout {
222 &self.taffy.nodes[node.into()].final_layout
223 }
224
225 #[inline(always)]
226 fn set_final_layout(&mut self, node_id: NodeId, layout: &Layout) {
227 self.taffy.nodes[node_id.into()].final_layout = *layout;
228 }
229}
230
231#[allow(clippy::iter_cloned_collect)] impl<NodeContext> TaffyTree<NodeContext> {
233 #[must_use]
237 pub fn new() -> Self {
238 Self::with_capacity(16)
239 }
240
241 #[must_use]
243 pub fn with_capacity(capacity: usize) -> Self {
244 TaffyTree {
245 nodes: SlotMap::with_capacity(capacity),
248 children: SlotMap::with_capacity(capacity),
249 parents: SlotMap::with_capacity(capacity),
250 node_context_data: SparseSecondaryMap::with_capacity(capacity),
251 config: TaffyConfig::default(),
252 }
253 }
254
255 pub fn enable_rounding(&mut self) {
257 self.config.use_rounding = true;
258 }
259
260 pub fn disable_rounding(&mut self) {
262 self.config.use_rounding = false;
263 }
264
265 pub fn new_leaf(&mut self, layout: Style) -> TaffyResult<NodeId> {
267 let id = self.nodes.insert(NodeData::new(layout));
268 let _ = self.children.insert(new_vec_with_capacity(0));
269 let _ = self.parents.insert(None);
270
271 Ok(id.into())
272 }
273
274 pub fn new_leaf_with_context(&mut self, layout: Style, context: NodeContext) -> TaffyResult<NodeId> {
278 let mut data = NodeData::new(layout);
279 data.needs_measure = true;
280
281 let id = self.nodes.insert(data);
282 self.node_context_data.insert(id, context);
283
284 let _ = self.children.insert(new_vec_with_capacity(0));
285 let _ = self.parents.insert(None);
286
287 Ok(id.into())
288 }
289
290 pub fn new_with_children(&mut self, layout: Style, children: &[NodeId]) -> TaffyResult<NodeId> {
292 let id = NodeId::from(self.nodes.insert(NodeData::new(layout)));
293
294 for child in children {
295 self.parents[(*child).into()] = Some(id);
296 }
297
298 let _ = self.children.insert(children.iter().copied().collect::<_>());
299 let _ = self.parents.insert(None);
300
301 Ok(id)
302 }
303
304 pub fn clear(&mut self) {
306 self.nodes.clear();
307 self.children.clear();
308 self.parents.clear();
309 }
310
311 pub fn remove(&mut self, node: NodeId) -> TaffyResult<NodeId> {
315 let key = node.into();
316 if let Some(parent) = self.parents[key] {
317 if let Some(children) = self.children.get_mut(parent.into()) {
318 children.retain(|f| *f != node);
319 }
320 }
321
322 if let Some(children) = self.children.get(key) {
324 for child in children.iter().copied() {
325 self.parents[child.into()] = None;
326 }
327 }
328
329 let _ = self.children.remove(key);
330 let _ = self.parents.remove(key);
331 let _ = self.nodes.remove(key);
332
333 Ok(node)
334 }
335
336 pub fn set_node_context(&mut self, node: NodeId, measure: Option<NodeContext>) -> TaffyResult<()> {
338 let key = node.into();
339 if let Some(measure) = measure {
340 self.nodes[key].needs_measure = true;
341 self.node_context_data.insert(key, measure);
342 } else {
343 self.nodes[key].needs_measure = false;
344 self.node_context_data.remove(key);
345 }
346
347 self.mark_dirty(node)?;
348
349 Ok(())
350 }
351
352 pub fn get_node_context(&self, node: NodeId) -> Option<&NodeContext> {
354 self.node_context_data.get(node.into())
355 }
356
357 pub fn get_node_context_mut(&mut self, node: NodeId) -> Option<&mut NodeContext> {
359 self.node_context_data.get_mut(node.into())
360 }
361
362 pub fn add_child(&mut self, parent: NodeId, child: NodeId) -> TaffyResult<()> {
364 let parent_key = parent.into();
365 let child_key = child.into();
366 self.parents[child_key] = Some(parent);
367 self.children[parent_key].push(child);
368 self.mark_dirty(parent)?;
369
370 Ok(())
371 }
372
373 pub fn insert_child_at_index(&mut self, parent: NodeId, child_index: usize, child: NodeId) -> TaffyResult<()> {
375 let parent_key = parent.into();
376
377 let child_count = self.children[parent_key].len();
378 if child_index > child_count {
379 return Err(TaffyError::ChildIndexOutOfBounds { parent, child_index, child_count });
380 }
381
382 self.parents[child.into()] = Some(parent);
383 self.children[parent_key].insert(child_index, child);
384 self.mark_dirty(parent)?;
385
386 Ok(())
387 }
388
389 pub fn set_children(&mut self, parent: NodeId, children: &[NodeId]) -> TaffyResult<()> {
391 let parent_key = parent.into();
392
393 for child in &self.children[parent_key] {
395 self.parents[(*child).into()] = None;
396 }
397
398 for child in children {
400 self.parents[(*child).into()] = Some(parent);
401 }
402
403 let parent_children = &mut self.children[parent_key];
404 parent_children.clear();
405 children.iter().for_each(|child| parent_children.push(*child));
406
407 self.mark_dirty(parent)?;
408
409 Ok(())
410 }
411
412 pub fn remove_child(&mut self, parent: NodeId, child: NodeId) -> TaffyResult<NodeId> {
416 let index = self.children[parent.into()].iter().position(|n| *n == child).unwrap();
417 self.remove_child_at_index(parent, index)
418 }
419
420 pub fn remove_child_at_index(&mut self, parent: NodeId, child_index: usize) -> TaffyResult<NodeId> {
424 let parent_key = parent.into();
425 let child_count = self.children[parent_key].len();
426 if child_index >= child_count {
427 return Err(TaffyError::ChildIndexOutOfBounds { parent, child_index, child_count });
428 }
429
430 let child = self.children[parent_key].remove(child_index);
431 self.parents[child.into()] = None;
432
433 self.mark_dirty(parent)?;
434
435 Ok(child)
436 }
437
438 pub fn replace_child_at_index(
442 &mut self,
443 parent: NodeId,
444 child_index: usize,
445 new_child: NodeId,
446 ) -> TaffyResult<NodeId> {
447 let parent_key = parent.into();
448
449 let child_count = self.children[parent_key].len();
450 if child_index >= child_count {
451 return Err(TaffyError::ChildIndexOutOfBounds { parent, child_index, child_count });
452 }
453
454 self.parents[new_child.into()] = Some(parent);
455 let old_child = core::mem::replace(&mut self.children[parent_key][child_index], new_child);
456 self.parents[old_child.into()] = None;
457
458 self.mark_dirty(parent)?;
459
460 Ok(old_child)
461 }
462
463 pub fn child_at_index(&self, parent: NodeId, child_index: usize) -> TaffyResult<NodeId> {
465 let parent_key = parent.into();
466 let child_count = self.children[parent_key].len();
467 if child_index >= child_count {
468 return Err(TaffyError::ChildIndexOutOfBounds { parent, child_index, child_count });
469 }
470
471 Ok(self.children[parent_key][child_index])
472 }
473
474 pub fn total_node_count(&self) -> usize {
476 self.nodes.len()
477 }
478
479 pub fn child_count(&self, parent: NodeId) -> TaffyResult<usize> {
481 Ok(self.children[parent.into()].len())
482 }
483
484 pub fn children(&self, parent: NodeId) -> TaffyResult<Vec<NodeId>> {
486 Ok(self.children[parent.into()].iter().copied().collect::<_>())
487 }
488
489 pub fn set_style(&mut self, node: NodeId, style: Style) -> TaffyResult<()> {
491 self.nodes[node.into()].style = style;
492 self.mark_dirty(node)?;
493 Ok(())
494 }
495
496 pub fn style(&self, node: NodeId) -> TaffyResult<&Style> {
498 Ok(&self.nodes[node.into()].style)
499 }
500
501 pub fn layout(&self, node: NodeId) -> TaffyResult<&Layout> {
503 if self.config.use_rounding {
504 Ok(&self.nodes[node.into()].final_layout)
505 } else {
506 Ok(&self.nodes[node.into()].unrounded_layout)
507 }
508 }
509
510 pub fn mark_dirty(&mut self, node: NodeId) -> TaffyResult<()> {
516 fn mark_dirty_recursive(
518 nodes: &mut SlotMap<DefaultKey, NodeData>,
519 parents: &SlotMap<DefaultKey, Option<NodeId>>,
520 node_key: DefaultKey,
521 ) {
522 nodes[node_key].mark_dirty();
523
524 if let Some(Some(node)) = parents.get(node_key) {
525 mark_dirty_recursive(nodes, parents, (*node).into());
526 }
527 }
528
529 mark_dirty_recursive(&mut self.nodes, &self.parents, node.into());
530
531 Ok(())
532 }
533
534 pub fn dirty(&self, node: NodeId) -> TaffyResult<bool> {
536 Ok(self.nodes[node.into()].cache.is_empty())
537 }
538
539 pub fn compute_layout_with_measure<MeasureFunction>(
541 &mut self,
542 node_id: NodeId,
543 available_space: Size<AvailableSpace>,
544 measure_function: MeasureFunction,
545 ) -> Result<(), TaffyError>
546 where
547 MeasureFunction: FnMut(Size<Option<f32>>, Size<AvailableSpace>, NodeId, Option<&mut NodeContext>) -> Size<f32>,
548 {
549 let use_rounding = self.config.use_rounding;
550 let mut taffy_view = TaffyView { taffy: self, measure_function };
551 compute_layout(&mut taffy_view, node_id, available_space);
552 if use_rounding {
553 round_layout(&mut taffy_view, node_id);
554 }
555 Ok(())
556 }
557
558 pub fn compute_layout(&mut self, node: NodeId, available_space: Size<AvailableSpace>) -> Result<(), TaffyError> {
560 self.compute_layout_with_measure(node, available_space, |_, _, _, _| Size::ZERO)
561 }
562
563 #[cfg(feature = "std")]
565 pub fn print_tree(&mut self, root: NodeId) {
566 let taffy_view = TaffyView { taffy: self, measure_function: |_, _, _, _| Size::ZERO };
567 crate::util::print_tree(&taffy_view, root)
568 }
569
570 #[cfg(test)]
572 pub(crate) fn as_layout_tree(&mut self) -> impl LayoutTree + '_ {
573 TaffyView { taffy: self, measure_function: |_, _, _, _| Size::ZERO }
574 }
575}
576
577#[cfg(test)]
578mod tests {
579 #![allow(clippy::bool_assert_comparison)]
580
581 use super::*;
582 use crate::style::{Dimension, Display, FlexDirection};
583 use crate::style_helpers::*;
584 use crate::util::sys;
585
586 fn size_measure_function(
587 known_dimensions: Size<Option<f32>>,
588 _available_space: Size<AvailableSpace>,
589 _node_id: NodeId,
590 node_context: Option<&mut Size<f32>>,
591 ) -> Size<f32> {
592 known_dimensions.unwrap_or(node_context.cloned().unwrap_or(Size::ZERO))
593 }
594
595 #[test]
596 fn new_should_allocate_default_capacity() {
597 const DEFAULT_CAPACITY: usize = 16; let taffy: TaffyTree<()> = TaffyTree::new();
599
600 assert!(taffy.children.capacity() >= DEFAULT_CAPACITY);
601 assert!(taffy.parents.capacity() >= DEFAULT_CAPACITY);
602 assert!(taffy.nodes.capacity() >= DEFAULT_CAPACITY);
603 }
604
605 #[test]
606 fn test_with_capacity() {
607 const CAPACITY: usize = 8;
608 let taffy: TaffyTree<()> = TaffyTree::with_capacity(CAPACITY);
609
610 assert!(taffy.children.capacity() >= CAPACITY);
611 assert!(taffy.parents.capacity() >= CAPACITY);
612 assert!(taffy.nodes.capacity() >= CAPACITY);
613 }
614
615 #[test]
616 fn test_new_leaf() {
617 let mut taffy: TaffyTree<()> = TaffyTree::new();
618
619 let res = taffy.new_leaf(Style::default());
620 assert!(res.is_ok());
621 let node = res.unwrap();
622
623 assert!(taffy.child_count(node).unwrap() == 0);
625 }
626
627 #[test]
628 fn new_leaf_with_context() {
629 let mut taffy: TaffyTree<Size<f32>> = TaffyTree::new();
630
631 let res = taffy.new_leaf_with_context(Style::default(), Size::ZERO);
632 assert!(res.is_ok());
633 let node = res.unwrap();
634
635 assert!(taffy.child_count(node).unwrap() == 0);
637 }
638
639 #[test]
641 fn test_new_with_children() {
642 let mut taffy: TaffyTree<()> = TaffyTree::new();
643 let child0 = taffy.new_leaf(Style::default()).unwrap();
644 let child1 = taffy.new_leaf(Style::default()).unwrap();
645 let node = taffy.new_with_children(Style::default(), &[child0, child1]).unwrap();
646
647 assert_eq!(taffy.child_count(node).unwrap(), 2);
649 assert_eq!(taffy.children(node).unwrap()[0], child0);
650 assert_eq!(taffy.children(node).unwrap()[1], child1);
651 }
652
653 #[test]
654 fn remove_node_should_remove() {
655 let mut taffy: TaffyTree<()> = TaffyTree::new();
656
657 let node = taffy.new_leaf(Style::default()).unwrap();
658
659 let _ = taffy.remove(node).unwrap();
660 }
661
662 #[test]
663 fn remove_node_should_detach_herarchy() {
664 let mut taffy: TaffyTree<()> = TaffyTree::new();
665
666 let node2 = taffy.new_leaf(Style::default()).unwrap();
668 let node1 = taffy.new_with_children(Style::default(), &[node2]).unwrap();
669 let node0 = taffy.new_with_children(Style::default(), &[node1]).unwrap();
670
671 assert_eq!(taffy.children(node0).unwrap().as_slice(), &[node1]);
673 assert_eq!(taffy.children(node1).unwrap().as_slice(), &[node2]);
674
675 let _ = taffy.remove(node1).unwrap();
677
678 assert!(taffy.children(node0).unwrap().is_empty());
680 assert!(taffy.children(node2).unwrap().is_empty());
681 }
682
683 #[test]
684 fn remove_last_node() {
685 let mut taffy: TaffyTree<()> = TaffyTree::new();
686
687 let parent = taffy.new_leaf(Style::default()).unwrap();
688 let child = taffy.new_leaf(Style::default()).unwrap();
689 taffy.add_child(parent, child).unwrap();
690
691 taffy.remove(child).unwrap();
692 taffy.remove(parent).unwrap();
693 }
694
695 #[test]
696 fn set_measure() {
697 let mut taffy: TaffyTree<Size<f32>> = TaffyTree::new();
698 let node = taffy.new_leaf_with_context(Style::default(), Size { width: 200.0, height: 200.0 }).unwrap();
699 taffy.compute_layout_with_measure(node, Size::MAX_CONTENT, size_measure_function).unwrap();
700 assert_eq!(taffy.layout(node).unwrap().size.width, 200.0);
701
702 taffy.set_node_context(node, Some(Size { width: 100.0, height: 100.0 })).unwrap();
703 taffy.compute_layout_with_measure(node, Size::MAX_CONTENT, size_measure_function).unwrap();
704 assert_eq!(taffy.layout(node).unwrap().size.width, 100.0);
705 }
706
707 #[test]
708 fn set_measure_of_previously_unmeasured_node() {
709 let mut taffy: TaffyTree<Size<f32>> = TaffyTree::new();
710 let node = taffy.new_leaf(Style::default()).unwrap();
711 taffy.compute_layout_with_measure(node, Size::MAX_CONTENT, size_measure_function).unwrap();
712 assert_eq!(taffy.layout(node).unwrap().size.width, 0.0);
713
714 taffy.set_node_context(node, Some(Size { width: 100.0, height: 100.0 })).unwrap();
715 taffy.compute_layout_with_measure(node, Size::MAX_CONTENT, size_measure_function).unwrap();
716 assert_eq!(taffy.layout(node).unwrap().size.width, 100.0);
717 }
718
719 #[test]
721 fn add_child() {
722 let mut taffy: TaffyTree<()> = TaffyTree::new();
723 let node = taffy.new_leaf(Style::default()).unwrap();
724 assert_eq!(taffy.child_count(node).unwrap(), 0);
725
726 let child0 = taffy.new_leaf(Style::default()).unwrap();
727 taffy.add_child(node, child0).unwrap();
728 assert_eq!(taffy.child_count(node).unwrap(), 1);
729
730 let child1 = taffy.new_leaf(Style::default()).unwrap();
731 taffy.add_child(node, child1).unwrap();
732 assert_eq!(taffy.child_count(node).unwrap(), 2);
733 }
734
735 #[test]
736 fn insert_child_at_index() {
737 let mut taffy: TaffyTree<()> = TaffyTree::new();
738
739 let child0 = taffy.new_leaf(Style::default()).unwrap();
740 let child1 = taffy.new_leaf(Style::default()).unwrap();
741 let child2 = taffy.new_leaf(Style::default()).unwrap();
742
743 let node = taffy.new_leaf(Style::default()).unwrap();
744 assert_eq!(taffy.child_count(node).unwrap(), 0);
745
746 taffy.insert_child_at_index(node, 0, child0).unwrap();
747 assert_eq!(taffy.child_count(node).unwrap(), 1);
748 assert_eq!(taffy.children(node).unwrap()[0], child0);
749
750 taffy.insert_child_at_index(node, 0, child1).unwrap();
751 assert_eq!(taffy.child_count(node).unwrap(), 2);
752 assert_eq!(taffy.children(node).unwrap()[0], child1);
753 assert_eq!(taffy.children(node).unwrap()[1], child0);
754
755 taffy.insert_child_at_index(node, 1, child2).unwrap();
756 assert_eq!(taffy.child_count(node).unwrap(), 3);
757 assert_eq!(taffy.children(node).unwrap()[0], child1);
758 assert_eq!(taffy.children(node).unwrap()[1], child2);
759 assert_eq!(taffy.children(node).unwrap()[2], child0);
760 }
761
762 #[test]
763 fn set_children() {
764 let mut taffy: TaffyTree<()> = TaffyTree::new();
765
766 let child0 = taffy.new_leaf(Style::default()).unwrap();
767 let child1 = taffy.new_leaf(Style::default()).unwrap();
768 let node = taffy.new_with_children(Style::default(), &[child0, child1]).unwrap();
769
770 assert_eq!(taffy.child_count(node).unwrap(), 2);
771 assert_eq!(taffy.children(node).unwrap()[0], child0);
772 assert_eq!(taffy.children(node).unwrap()[1], child1);
773
774 let child2 = taffy.new_leaf(Style::default()).unwrap();
775 let child3 = taffy.new_leaf(Style::default()).unwrap();
776 taffy.set_children(node, &[child2, child3]).unwrap();
777
778 assert_eq!(taffy.child_count(node).unwrap(), 2);
779 assert_eq!(taffy.children(node).unwrap()[0], child2);
780 assert_eq!(taffy.children(node).unwrap()[1], child3);
781 }
782
783 #[test]
785 fn remove_child() {
786 let mut taffy: TaffyTree<()> = TaffyTree::new();
787 let child0 = taffy.new_leaf(Style::default()).unwrap();
788 let child1 = taffy.new_leaf(Style::default()).unwrap();
789 let node = taffy.new_with_children(Style::default(), &[child0, child1]).unwrap();
790
791 assert_eq!(taffy.child_count(node).unwrap(), 2);
792
793 taffy.remove_child(node, child0).unwrap();
794 assert_eq!(taffy.child_count(node).unwrap(), 1);
795 assert_eq!(taffy.children(node).unwrap()[0], child1);
796
797 taffy.remove_child(node, child1).unwrap();
798 assert_eq!(taffy.child_count(node).unwrap(), 0);
799 }
800
801 #[test]
802 fn remove_child_at_index() {
803 let mut taffy: TaffyTree<()> = TaffyTree::new();
804 let child0 = taffy.new_leaf(Style::default()).unwrap();
805 let child1 = taffy.new_leaf(Style::default()).unwrap();
806 let node = taffy.new_with_children(Style::default(), &[child0, child1]).unwrap();
807
808 assert_eq!(taffy.child_count(node).unwrap(), 2);
809
810 taffy.remove_child_at_index(node, 0).unwrap();
811 assert_eq!(taffy.child_count(node).unwrap(), 1);
812 assert_eq!(taffy.children(node).unwrap()[0], child1);
813
814 taffy.remove_child_at_index(node, 0).unwrap();
815 assert_eq!(taffy.child_count(node).unwrap(), 0);
816 }
817
818 #[test]
820 fn remove_child_updates_parents() {
821 let mut taffy: TaffyTree<()> = TaffyTree::new();
822
823 let parent = taffy.new_leaf(Style::default()).unwrap();
824 let child = taffy.new_leaf(Style::default()).unwrap();
825
826 taffy.add_child(parent, child).unwrap();
827
828 taffy.remove(parent).unwrap();
829
830 assert!(taffy.set_children(child, &[]).is_ok());
832 }
833
834 #[test]
835 fn replace_child_at_index() {
836 let mut taffy: TaffyTree<()> = TaffyTree::new();
837
838 let child0 = taffy.new_leaf(Style::default()).unwrap();
839 let child1 = taffy.new_leaf(Style::default()).unwrap();
840
841 let node = taffy.new_with_children(Style::default(), &[child0]).unwrap();
842 assert_eq!(taffy.child_count(node).unwrap(), 1);
843 assert_eq!(taffy.children(node).unwrap()[0], child0);
844
845 taffy.replace_child_at_index(node, 0, child1).unwrap();
846 assert_eq!(taffy.child_count(node).unwrap(), 1);
847 assert_eq!(taffy.children(node).unwrap()[0], child1);
848 }
849 #[test]
850 fn test_child_at_index() {
851 let mut taffy: TaffyTree<()> = TaffyTree::new();
852 let child0 = taffy.new_leaf(Style::default()).unwrap();
853 let child1 = taffy.new_leaf(Style::default()).unwrap();
854 let child2 = taffy.new_leaf(Style::default()).unwrap();
855 let node = taffy.new_with_children(Style::default(), &[child0, child1, child2]).unwrap();
856
857 assert!(if let Ok(result) = taffy.child_at_index(node, 0) { result == child0 } else { false });
858 assert!(if let Ok(result) = taffy.child_at_index(node, 1) { result == child1 } else { false });
859 assert!(if let Ok(result) = taffy.child_at_index(node, 2) { result == child2 } else { false });
860 }
861 #[test]
862 fn test_child_count() {
863 let mut taffy: TaffyTree<()> = TaffyTree::new();
864 let child0 = taffy.new_leaf(Style::default()).unwrap();
865 let child1 = taffy.new_leaf(Style::default()).unwrap();
866 let node = taffy.new_with_children(Style::default(), &[child0, child1]).unwrap();
867
868 assert!(if let Ok(count) = taffy.child_count(node) { count == 2 } else { false });
869 assert!(if let Ok(count) = taffy.child_count(child0) { count == 0 } else { false });
870 assert!(if let Ok(count) = taffy.child_count(child1) { count == 0 } else { false });
871 }
872
873 #[allow(clippy::vec_init_then_push)]
874 #[test]
875 fn test_children() {
876 let mut taffy: TaffyTree<()> = TaffyTree::new();
877 let child0 = taffy.new_leaf(Style::default()).unwrap();
878 let child1 = taffy.new_leaf(Style::default()).unwrap();
879 let node = taffy.new_with_children(Style::default(), &[child0, child1]).unwrap();
880
881 let mut children = sys::Vec::new();
882 children.push(child0);
883 children.push(child1);
884
885 let children_result = taffy.children(node).unwrap();
886 assert_eq!(children_result, children);
887
888 assert!(taffy.children(child0).unwrap().is_empty());
889 }
890 #[test]
891 fn test_set_style() {
892 let mut taffy: TaffyTree<()> = TaffyTree::new();
893
894 let node = taffy.new_leaf(Style::default()).unwrap();
895 assert_eq!(taffy.style(node).unwrap().display, Display::Flex);
896
897 taffy.set_style(node, Style { display: Display::None, ..Style::default() }).unwrap();
898 assert_eq!(taffy.style(node).unwrap().display, Display::None);
899 }
900 #[test]
901 fn test_style() {
902 let mut taffy: TaffyTree<()> = TaffyTree::new();
903
904 let style = Style { display: Display::None, flex_direction: FlexDirection::RowReverse, ..Default::default() };
905
906 let node = taffy.new_leaf(style.clone()).unwrap();
907
908 let res = taffy.style(node);
909 assert!(res.is_ok());
910 assert!(res.unwrap() == &style);
911 }
912 #[test]
913 fn test_layout() {
914 let mut taffy: TaffyTree<()> = TaffyTree::new();
915 let node = taffy.new_leaf(Style::default()).unwrap();
916
917 let res = taffy.layout(node);
919 assert!(res.is_ok());
920 }
921
922 #[test]
923 fn test_mark_dirty() {
924 let mut taffy: TaffyTree<()> = TaffyTree::new();
925 let child0 = taffy.new_leaf(Style::default()).unwrap();
926 let child1 = taffy.new_leaf(Style::default()).unwrap();
927 let node = taffy.new_with_children(Style::default(), &[child0, child1]).unwrap();
928
929 taffy.compute_layout(node, Size::MAX_CONTENT).unwrap();
930
931 assert_eq!(taffy.dirty(child0).unwrap(), false);
932 assert_eq!(taffy.dirty(child1).unwrap(), false);
933 assert_eq!(taffy.dirty(node).unwrap(), false);
934
935 taffy.mark_dirty(node).unwrap();
936 assert_eq!(taffy.dirty(child0).unwrap(), false);
937 assert_eq!(taffy.dirty(child1).unwrap(), false);
938 assert_eq!(taffy.dirty(node).unwrap(), true);
939
940 taffy.compute_layout(node, Size::MAX_CONTENT).unwrap();
941 taffy.mark_dirty(child0).unwrap();
942 assert_eq!(taffy.dirty(child0).unwrap(), true);
943 assert_eq!(taffy.dirty(child1).unwrap(), false);
944 assert_eq!(taffy.dirty(node).unwrap(), true);
945 }
946
947 #[test]
948 fn compute_layout_should_produce_valid_result() {
949 let mut taffy: TaffyTree<()> = TaffyTree::new();
950 let node_result = taffy.new_leaf(Style {
951 size: Size { width: Dimension::Length(10f32), height: Dimension::Length(10f32) },
952 ..Default::default()
953 });
954 assert!(node_result.is_ok());
955 let node = node_result.unwrap();
956 let layout_result = taffy.compute_layout(
957 node,
958 Size { width: AvailableSpace::Definite(100.), height: AvailableSpace::Definite(100.) },
959 );
960 assert!(layout_result.is_ok());
961 }
962
963 #[test]
964 fn make_sure_layout_location_is_top_left() {
965 use crate::prelude::Rect;
966
967 let mut taffy: TaffyTree<()> = TaffyTree::new();
968
969 let node = taffy
970 .new_leaf(Style {
971 size: Size { width: Dimension::Percent(1f32), height: Dimension::Percent(1f32) },
972 ..Default::default()
973 })
974 .unwrap();
975
976 let root = taffy
977 .new_with_children(
978 Style {
979 size: Size { width: Dimension::Length(100f32), height: Dimension::Length(100f32) },
980 padding: Rect {
981 left: length(10f32),
982 right: length(20f32),
983 top: length(30f32),
984 bottom: length(40f32),
985 },
986 ..Default::default()
987 },
988 &[node],
989 )
990 .unwrap();
991
992 taffy.compute_layout(root, Size::MAX_CONTENT).unwrap();
993
994 let layout = taffy.layout(node).unwrap();
1003 assert_eq!(layout.location.x, 10f32);
1004 assert_eq!(layout.location.y, 30f32);
1005 }
1006}