Make low-level layout algorithm functions public (#434)
1//! The baseline requirements of any UI Tree so Taffy can efficiently calculate the layout
2use crate::{
3 layout::{Layout, SizeAndBaselines, SizingMode},
4 prelude::*,
5};
6use slotmap::{DefaultKey, Key, KeyData};
7
8/// A type representing the id of a single node in a tree of nodes
9///
10/// Internally it is a wrapper around a u64 and a `NodeId` can be converted to and from
11/// and u64 if needed.
12#[derive(Copy, Clone, Debug, PartialEq, Eq)]
13pub struct NodeId(u64);
14impl NodeId {
15 /// Create a new NodeId from a u64 value
16 pub const fn new(val: u64) -> Self {
17 Self(val)
18 }
19}
20
21impl From<u64> for NodeId {
22 #[inline]
23 fn from(raw: u64) -> Self {
24 Self(raw)
25 }
26}
27impl From<NodeId> for u64 {
28 #[inline]
29 fn from(id: NodeId) -> Self {
30 id.0
31 }
32}
33impl From<usize> for NodeId {
34 #[inline]
35 fn from(raw: usize) -> Self {
36 Self(raw as u64)
37 }
38}
39impl From<NodeId> for usize {
40 #[inline]
41 fn from(id: NodeId) -> Self {
42 id.0 as usize
43 }
44}
45impl From<DefaultKey> for NodeId {
46 #[inline]
47 fn from(key: DefaultKey) -> Self {
48 Self(key.data().as_ffi())
49 }
50}
51impl From<NodeId> for DefaultKey {
52 #[inline]
53 fn from(key: NodeId) -> Self {
54 KeyData::from_ffi(key.0).into()
55 }
56}
57
58/// Any item that implements the LayoutTree can be layed out using Taffy's algorithms.
59///
60/// Generally, Taffy expects your Node tree to be indexable by stable indices. A "stable" index means that the Node's ID
61/// remains the same between re-layouts.
62pub trait LayoutTree {
63 /// Type representing an iterator of the children of a node
64 type ChildIter<'a>: Iterator<Item = NodeId>
65 where
66 Self: 'a;
67
68 /// Get the list of children IDs for the given node
69 fn children(&self, node: NodeId) -> Self::ChildIter<'_>;
70
71 /// Get the number of children for the given node
72 fn child_count(&self, node: NodeId) -> usize;
73
74 /// Get a specific child of a node, where the index represents the nth child
75 fn child(&self, node: NodeId, index: usize) -> NodeId;
76
77 // todo: allow abstractions over this so we don't prescribe how layout works
78 // for reference, CSS cascades require context, and storing a full flexbox layout for each node could be inefficient
79 //
80 /// Get the [`Style`] for this node.
81 fn style(&self, node: NodeId) -> &Style;
82
83 /// Modify the node's output layout
84 fn layout_mut(&mut self, node: NodeId) -> &mut Layout;
85
86 /// Compute the size of the node given the specified constraints
87 fn measure_child_size(
88 &mut self,
89 node: NodeId,
90 known_dimensions: Size<Option<f32>>,
91 parent_size: Size<Option<f32>>,
92 available_space: Size<AvailableSpace>,
93 sizing_mode: SizingMode,
94 ) -> Size<f32>;
95
96 /// Perform a full layout on the node given the specified constraints
97 fn perform_child_layout(
98 &mut self,
99 node: NodeId,
100 known_dimensions: Size<Option<f32>>,
101 parent_size: Size<Option<f32>>,
102 available_space: Size<AvailableSpace>,
103 sizing_mode: SizingMode,
104 ) -> SizeAndBaselines;
105}