HTML 5364Rust 86Markdown 12TOML 91841 Definiciones
Return iterator for children for `LayoutTree` (#260)
* Return iterator for children for `LayoutTree`
* Implement review changes
* Fix clippy warnings
* Add entry to RELEASES.md for LayoutTree changes
* 0.3 should be called out as unreleased
* Line break after heading
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
diff --git a/RELEASES.md b/RELEASES.md
index df4e77468..739c9cd4b 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,5 +1,16 @@
# Release Notes
+## 0.3.0 (Unreleased)
+
+### Breaking API changes
+
+#### Changes to `LayoutTree`
+
+- Added generic associated type to `LayoutTree` for a `ChildIter`, an iterator on the children of a given node.
+- Changed the `children` method of `LayoutTree` to return the `ChildIter` generic associated type to allow for custom tree storage implementations which do not store the children of a node contiguously.
+- Added `child_count` method to `LayoutTree` for querying the number of children of a node. Required because the `children` method now returns an iterator instead of an array.
+- Added `is_childless` method to `LayoutTree` for querying whether a node has no children.
+
## 0.2.0
### New features
diff --git a/src/compute/flexbox.rs b/src/compute/flexbox.rs
index f4bcdde79..a418fb444 100644
--- a/src/compute/flexbox.rs
+++ b/src/compute/flexbox.rs
@@ -332,7 +332,7 @@ fn compute_preliminary(
#[cfg(feature = "debug")]
NODE_LOGGER.log("hidden_layout");
- let len = tree.children(node).len();
+ let len = tree.child_count(node);
for order in 0..len {
let child = tree.child(node, order);
if tree.style(child).display == Display::None {
@@ -395,7 +395,6 @@ fn compute_constants(style: &Style, node_size: Size<Option<f32>>, parent_size: S
#[inline]
fn generate_anonymous_flex_items(tree: &impl LayoutTree, node: Node, constants: &AlgoConstants) -> Vec<FlexItem> {
tree.children(node)
- .iter()
.map(|child| (child, tree.style(*child)))
.filter(|(_, style)| style.position_type != PositionType::Absolute)
.filter(|(_, style)| style.display != Display::None)
@@ -974,20 +973,12 @@ fn calculate_children_base_lines(
) {
/// Recursively calculates the baseline for children
fn calc_baseline(db: &impl LayoutTree, node: Node, layout: &Layout) -> f32 {
- let children = db.children(node);
- if children.is_empty() {
- layout.size.height
+ if let Some(first_child) = db.children(node).next() {
+ let layout = db.layout(*first_child);
+ calc_baseline(db, *first_child, layout)
} else {
- let child = children[0];
- let layout = db.layout(child);
- calc_baseline(db, child, layout)
+ layout.size.height
}
- // if db.children[node].is_empty() {
- // layout.size.height
- // } else {
- // let child = db.children[node][0];
- // calc_baseline(db, child, &db.nodes[child].layout)
- // }
}
for line in flex_lines {
@@ -1027,7 +1018,7 @@ fn calculate_children_base_lines(
tree,
child.node,
&Layout {
- order: tree.children(node).iter().position(|n| *n == child.node).unwrap() as u32,
+ order: tree.children(node).position(|n| *n == child.node).unwrap() as u32,
size: preliminary_size,
location: Point::ZERO,
},
@@ -1579,8 +1570,10 @@ fn calculate_flex_item(
+ item.margin.cross_start(direction)
+ (item.position.cross_start(direction).unwrap_or(0.0) - item.position.cross_end(direction).unwrap_or(0.0));
+ let order = tree.children(node).position(|n| *n == item.node).unwrap() as u32;
+
*tree.layout_mut(item.node) = Layout {
- order: tree.children(node).iter().position(|n| *n == item.node).unwrap() as u32,
+ order,
size: preliminary_size,
location: Point {
x: if direction.is_row() { offset_main } else { offset_cross },
@@ -1673,7 +1666,6 @@ fn perform_absolute_layout_on_absolute_children(tree: &mut impl LayoutTree, node
// TODO: remove number of Vec<_> generated
let candidates = tree
.children(node)
- .iter()
.cloned()
.enumerate()
.filter(|(_, child)| tree.style(*child).position_type == PositionType::Absolute)
@@ -1829,7 +1821,7 @@ fn perform_absolute_layout_on_absolute_children(tree: &mut impl LayoutTree, node
fn hidden_layout(tree: &mut impl LayoutTree, node: Node, order: u32) {
*tree.layout_mut(node) = Layout::with_order(order);
- let len = tree.children(node).len();
+ let len = tree.child_count(node);
for order in 0..len {
hidden_layout(tree, tree.child(node, order), order as _);
}
diff --git a/src/compute/mod.rs b/src/compute/mod.rs
index dc1a0d9e7..bc6bbc39b 100644
--- a/src/compute/mod.rs
+++ b/src/compute/mod.rs
@@ -48,7 +48,7 @@ fn compute_node_layout(
println!();
// First we check if we have a cached result for the given input
- let cache_run_mode = if tree.children(node).is_empty() { RunMode::PeformLayout } else { run_mode };
+ let cache_run_mode = if tree.is_childless(node) { RunMode::PeformLayout } else { run_mode };
if let Some(cached_size) =
compute_from_cache(tree, node, known_dimensions, available_space, cache_run_mode, sizing_mode)
{
@@ -103,7 +103,7 @@ fn compute_node_layout(
// }
// If this is a leaf node we can skip a lot of this function in some cases
- let computed_size = if tree.children(node).is_empty() {
+ let computed_size = if tree.is_childless(node) {
#[cfg(feature = "debug")]
NODE_LOGGER.log("Algo: leaf");
self::leaf::compute(tree, node, known_dimensions, available_space, run_mode, sizing_mode)
@@ -196,7 +196,7 @@ fn round_layout(tree: &mut impl LayoutTree, root: Node, abs_x: f32, abs_y: f32)
layout.size.height = round(layout.size.height);
// Satisfy the borrow checker here by re-indexing to shorten the lifetime to the loop scope
- for x in 0..tree.children(root).len() {
+ for x in 0..tree.child_count(root) {
let child = tree.child(root, x);
round_layout(tree, child, abs_x, abs_y);
}
diff --git a/src/node.rs b/src/node.rs
index 9ad53f588..a280b366f 100644
--- a/src/node.rs
+++ b/src/node.rs
@@ -1,7 +1,7 @@
//! UI [`Node`] types and related data structures.
//!
//! Layouts are composed of multiple nodes, which live in a tree-like data structure.
-use slotmap::{SlotMap, SparseSecondaryMap};
+use slotmap::{DefaultKey, SlotMap, SparseSecondaryMap};
/// A node in a layout.
pub type Node = slotmap::DefaultKey;
@@ -58,8 +58,18 @@ impl Default for Taffy {
}
impl LayoutTree for Taffy {
- fn children(&self, node: Node) -> &[Node] {
- &self.children[node]
+ type ChildIter<'a> = std::slice::Iter<'a, DefaultKey>;
+
+ fn children(&self, node: Node) -> Self::ChildIter<'_> {
+ self.children[node].iter()
+ }
+
+ fn child_count(&self, node: Node) -> usize {
+ self.children[node].len()
+ }
+
+ fn is_childless(&self, node: Node) -> bool {
+ self.children[node].is_empty()
}
fn parent(&self, node: Node) -> Option<Node> {
diff --git a/src/tree.rs b/src/tree.rs
index ddd05b965..ca6248048 100644
--- a/src/tree.rs
+++ b/src/tree.rs
@@ -1,5 +1,7 @@
//! The baseline requirements of any UI Tree so Taffy can efficiently calculate the layout
+use slotmap::DefaultKey;
+
use crate::{
error::TaffyResult,
layout::{AvailableSpace, Cache, Layout},
@@ -11,8 +13,19 @@ use crate::{
/// Generally, Taffy expects your Node tree to be indexable by stable indices. A "stable" index means that the Node's ID
/// remains the same between re-layouts.
pub trait LayoutTree {
+ /// Type representing an iterator of the children of a node
+ type ChildIter<'a>: Iterator<Item = &'a DefaultKey>
+ where
+ Self: 'a;
+
/// Get the list of children IDs for the given node
- fn children(&self, node: Node) -> &[Node];
+ fn children(&self, node: Node) -> Self::ChildIter<'_>;
+
+ /// Get the number of children for the given node
+ fn child_count(&self, node: Node) -> usize;
+
+ /// Returns true if the node has no children
+ fn is_childless(&self, node: Node) -> bool;
/// Get a specific child of a node, where the index represents the nth child
fn child(&self, node: Node, index: usize) -> Node;