Skip to content

Commit 47a5a3f

Browse files
committed
Add context type parameter to Taffy struct
1 parent 862559b commit 47a5a3f

File tree

4 files changed

+99
-61
lines changed

4 files changed

+99
-61
lines changed

src/compute/leaf.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! Computes size using styles and measure functions
22
3-
use crate::geometry::{Line, Point, Size};
3+
use crate::geometry::{Point, Size};
44
use crate::style::{AvailableSpace, Display, Overflow, Position, Style};
55
use crate::tree::{CollapsibleMarginSet, Measurable};
66
use crate::tree::{SizeBaselinesAndMargins, SizingMode};
@@ -12,39 +12,40 @@ use crate::util::{MaybeResolve, ResolveOrZero};
1212
use crate::util::debug::NODE_LOGGER;
1313

1414
/// Perform full layout on a leaf node
15-
pub(crate) fn perform_layout(
15+
pub(crate) fn perform_layout<Context>(
1616
style: &Style,
17-
measurable: Option<&impl Measurable>,
17+
measurable: Option<&impl Measurable<Context = Context>>,
1818
known_dimensions: Size<Option<f32>>,
1919
parent_size: Size<Option<f32>>,
2020
available_space: Size<AvailableSpace>,
2121
sizing_mode: SizingMode,
22-
_vertical_margins_are_collapsible: Line<bool>,
22+
context: &mut Context,
2323
) -> SizeBaselinesAndMargins {
24-
compute(style, measurable, known_dimensions, parent_size, available_space, sizing_mode)
24+
compute(style, measurable, known_dimensions, parent_size, available_space, sizing_mode, context)
2525
}
2626

2727
/// Measure a leaf node's size
28-
pub(crate) fn measure_size(
28+
pub(crate) fn measure_size<Context>(
2929
style: &Style,
30-
measurable: Option<&impl Measurable>,
30+
measurable: Option<&impl Measurable<Context = Context>>,
3131
known_dimensions: Size<Option<f32>>,
3232
parent_size: Size<Option<f32>>,
3333
available_space: Size<AvailableSpace>,
3434
sizing_mode: SizingMode,
35-
_vertical_margins_are_collapsible: Line<bool>,
35+
context: &mut Context,
3636
) -> Size<f32> {
37-
compute(style, measurable, known_dimensions, parent_size, available_space, sizing_mode).size
37+
compute(style, measurable, known_dimensions, parent_size, available_space, sizing_mode, context).size
3838
}
3939

4040
/// Compute the size of a leaf node (node with no children)
41-
pub fn compute(
41+
pub fn compute<Context>(
4242
style: &Style,
43-
measurable: Option<&impl Measurable>,
43+
measurable: Option<&impl Measurable<Context = Context>>,
4444
known_dimensions: Size<Option<f32>>,
4545
parent_size: Size<Option<f32>>,
4646
available_space: Size<AvailableSpace>,
4747
sizing_mode: SizingMode,
48+
context: &mut Context,
4849
) -> SizeBaselinesAndMargins {
4950
// Resolve node's preferred/min/max sizes (width/heights) against the available space (percentages resolve to pixel values)
5051
// For ContentSize mode, we pretend that the node has no size styles as these should be ignored.
@@ -141,7 +142,7 @@ pub fn compute(
141142
};
142143

143144
// Measure node
144-
let measured_size = measurable.measure(known_dimensions, available_space);
145+
let measured_size = measurable.measure(known_dimensions, available_space, context);
145146
let clamped_size = node_size.unwrap_or(measured_size).maybe_clamp(node_min_size, node_max_size);
146147
let size = Size {
147148
width: clamped_size.width,

src/compute/taffy_tree.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
use crate::compute::{leaf, LayoutAlgorithm};
44
use crate::geometry::{Line, Point, Size};
55
use crate::style::{AvailableSpace, Display};
6-
use crate::tree::{Layout, LayoutTree, NodeId, RunMode, SizeBaselinesAndMargins, SizingMode, Taffy, TaffyError};
6+
use crate::tree::{
7+
Layout, LayoutTree, Measurable, NodeId, RunMode, SizeBaselinesAndMargins, SizingMode, Taffy, TaffyError,
8+
};
79
use crate::util::sys::round;
810

911
#[cfg(feature = "block_layout")]
@@ -34,8 +36,8 @@ fn debug_log_node(
3436
}
3537

3638
/// Updates the stored layout of the provided `node` and its children
37-
pub(crate) fn compute_layout(
38-
taffy: &mut Taffy,
39+
pub(crate) fn compute_layout<Measure: Measurable>(
40+
taffy: &mut Taffy<Measure>,
3941
root: NodeId,
4042
available_space: Size<AvailableSpace>,
4143
) -> Result<(), TaffyError> {
@@ -62,8 +64,8 @@ pub(crate) fn compute_layout(
6264
}
6365

6466
/// Perform full layout on a node. Chooses which algorithm to use based on the `display` property.
65-
pub(crate) fn perform_node_layout(
66-
tree: &mut Taffy,
67+
pub(crate) fn perform_node_layout<Measure: Measurable>(
68+
tree: &mut Taffy<Measure>,
6769
node: NodeId,
6870
known_dimensions: Size<Option<f32>>,
6971
parent_size: Size<Option<f32>>,
@@ -84,8 +86,8 @@ pub(crate) fn perform_node_layout(
8486
}
8587

8688
/// Measure a node's size. Chooses which algorithm to use based on the `display` property.
87-
pub(crate) fn measure_node_size(
88-
tree: &mut Taffy,
89+
pub(crate) fn measure_node_size<Measure: Measurable>(
90+
tree: &mut Taffy<Measure>,
8991
node: NodeId,
9092
known_dimensions: Size<Option<f32>>,
9193
parent_size: Size<Option<f32>>,
@@ -108,8 +110,8 @@ pub(crate) fn measure_node_size(
108110

109111
/// Updates the stored layout of the provided `node` and its children
110112
#[allow(clippy::too_many_arguments)]
111-
fn compute_node_layout(
112-
tree: &mut Taffy,
113+
fn compute_node_layout<Measure: Measurable>(
114+
tree: &mut Taffy<Measure>,
113115
node: NodeId,
114116
known_dimensions: Size<Option<f32>>,
115117
parent_size: Size<Option<f32>>,
@@ -228,7 +230,7 @@ fn compute_node_layout(
228230
parent_size,
229231
available_space,
230232
sizing_mode,
231-
vertical_margins_are_collapsible,
233+
tree.context.as_mut().unwrap(),
232234
),
233235
RunMode::ComputeSize => leaf::measure_size(
234236
&tree.nodes[node_key].style,
@@ -237,7 +239,7 @@ fn compute_node_layout(
237239
parent_size,
238240
available_space,
239241
sizing_mode,
240-
vertical_margins_are_collapsible,
242+
tree.context.as_mut().unwrap(),
241243
)
242244
.into(),
243245
},
@@ -256,9 +258,9 @@ fn compute_node_layout(
256258

257259
/// Creates a layout for this node and its children, recursively.
258260
/// Each hidden node has zero size and is placed at the origin
259-
fn perform_taffy_tree_hidden_layout(tree: &mut Taffy, node: NodeId) {
261+
fn perform_taffy_tree_hidden_layout<Measure: Measurable>(tree: &mut Taffy<Measure>, node: NodeId) {
260262
/// Recursive function to apply hidden layout to all descendents
261-
fn perform_hidden_layout_inner(tree: &mut Taffy, node: NodeId, order: u32) {
263+
fn perform_hidden_layout_inner<Measure: Measurable>(tree: &mut Taffy<Measure>, node: NodeId, order: u32) {
262264
let node_key = node.into();
263265
*tree.layout_mut(node) = Layout::with_order(order);
264266
tree.nodes[node_key].cache.clear();

src/tree/measure_func.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,17 @@ pub trait Measurable: Send + Sync {
1818
&self,
1919
known_dimensions: Size<Option<f32>>,
2020
available_space: Size<AvailableSpace>,
21-
context: Self::Context,
21+
context: &mut Self::Context,
2222
) -> Size<f32>;
2323
}
2424

2525
/// A function that can be used to compute the intrinsic size of a node
2626
pub enum MeasureFunc<Context = ()> {
27-
/// Stores an unboxed function
28-
Raw(fn(Size<Option<f32>>, Size<AvailableSpace>, context: Context) -> Size<f32>),
27+
/// Stores an unboxed function with no context parameter
28+
Raw(fn(Size<Option<f32>>, Size<AvailableSpace>) -> Size<f32>),
29+
30+
/// Stores an unboxed function with a context parameter
31+
RawWithContext(fn(Size<Option<f32>>, Size<AvailableSpace>, context: &mut Context) -> Size<f32>),
2932

3033
/// Stores a boxed function
3134
#[cfg(any(feature = "std", feature = "alloc"))]
@@ -37,9 +40,15 @@ impl<Context> Measurable for MeasureFunc<Context> {
3740

3841
/// Call the measure function to measure to the node
3942
#[inline(always)]
40-
fn measure(&self, known_dimensions: Size<Option<f32>>, available_space: Size<AvailableSpace>, context: Context) -> Size<f32> {
43+
fn measure(
44+
&self,
45+
known_dimensions: Size<Option<f32>>,
46+
available_space: Size<AvailableSpace>,
47+
context: &mut Context,
48+
) -> Size<f32> {
4149
match self {
42-
Self::Raw(measure) => measure(known_dimensions, available_space, context),
50+
Self::Raw(measure) => measure(known_dimensions, available_space),
51+
Self::RawWithContext(measure) => measure(known_dimensions, available_space, context),
4352
#[cfg(any(feature = "std", feature = "alloc"))]
4453
Self::Boxed(measurable) => measurable.measure(known_dimensions, available_space, context),
4554
}

src/tree/taffy_tree/tree.rs

Lines changed: 57 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::compute::taffy_tree::{compute_layout, measure_node_size, perform_node
77
use crate::geometry::{Line, Size};
88
use crate::prelude::LayoutTree;
99
use crate::style::{AvailableSpace, Style};
10-
use crate::tree::{Layout, MeasureFunc, NodeData, NodeId, SizeBaselinesAndMargins, SizingMode};
10+
use crate::tree::{Layout, Measurable, MeasureFunc, NodeData, NodeId, SizeBaselinesAndMargins, SizingMode};
1111
use crate::util::sys::{new_vec_with_capacity, ChildrenVec, Vec};
1212

1313
use super::{TaffyError, TaffyResult};
@@ -25,12 +25,15 @@ impl Default for TaffyConfig {
2525
}
2626

2727
/// A tree of UI nodes suitable for UI layout
28-
pub struct Taffy {
28+
pub struct Taffy<Measure = MeasureFunc<()>>
29+
where
30+
Measure: Measurable,
31+
{
2932
/// The [`NodeData`] for each node stored in this tree
3033
pub(crate) nodes: SlotMap<DefaultKey, NodeData>,
3134

3235
/// Functions/closures that compute the intrinsic size of leaf nodes
33-
pub(crate) measure_funcs: SparseSecondaryMap<DefaultKey, MeasureFunc>,
36+
pub(crate) measure_funcs: SparseSecondaryMap<DefaultKey, MeasureFunc<Measure::Context>>,
3437

3538
/// The children of each node
3639
///
@@ -44,6 +47,9 @@ pub struct Taffy {
4447

4548
/// Layout mode configuration
4649
pub(crate) config: TaffyConfig,
50+
51+
/// Used to store the context during layout. Cleared before returning from `compute_layout`.
52+
pub(crate) context: Option<Measure::Context>,
4753
}
4854

4955
impl Default for Taffy {
@@ -62,8 +68,8 @@ impl<'a> Iterator for TaffyChildIter<'a> {
6268
}
6369
}
6470

65-
impl LayoutTree for Taffy {
66-
type ChildIter<'a> = TaffyChildIter<'a>;
71+
impl<Measure: Measurable> LayoutTree for Taffy<Measure> {
72+
type ChildIter<'a> = TaffyChildIter<'a> where Measure: 'a;
6773

6874
#[inline(always)]
6975
fn children(&self, node: NodeId) -> Self::ChildIter<'_> {
@@ -139,29 +145,7 @@ impl LayoutTree for Taffy {
139145
}
140146

141147
#[allow(clippy::iter_cloned_collect)] // due to no-std support, we need to use `iter_cloned` instead of `collect`
142-
impl Taffy {
143-
/// Creates a new [`Taffy`]
144-
///
145-
/// The default capacity of a [`Taffy`] is 16 nodes.
146-
#[must_use]
147-
pub fn new() -> Self {
148-
Self::with_capacity(16)
149-
}
150-
151-
/// Creates a new [`Taffy`] that can store `capacity` nodes before reallocation
152-
#[must_use]
153-
pub fn with_capacity(capacity: usize) -> Self {
154-
Self {
155-
// TODO: make this method const upstream,
156-
// so constructors here can be const
157-
nodes: SlotMap::with_capacity(capacity),
158-
children: SlotMap::with_capacity(capacity),
159-
parents: SlotMap::with_capacity(capacity),
160-
measure_funcs: SparseSecondaryMap::with_capacity(capacity),
161-
config: TaffyConfig::default(),
162-
}
163-
}
164-
148+
impl<Measure: Measurable> Taffy<Measure> {
165149
/// Enable rounding of layout values. Rounding is enabled by default.
166150
pub fn enable_rounding(&mut self) {
167151
self.config.use_rounding = true;
@@ -184,7 +168,11 @@ impl Taffy {
184168
/// Creates and adds a new unattached leaf node to the tree, and returns the node of the new node
185169
///
186170
/// Creates and adds a new leaf node with a supplied [`MeasureFunc`]
187-
pub fn new_leaf_with_measure(&mut self, layout: Style, measure: MeasureFunc) -> TaffyResult<NodeId> {
171+
pub fn new_leaf_with_measure(
172+
&mut self,
173+
layout: Style,
174+
measure: MeasureFunc<Measure::Context>,
175+
) -> TaffyResult<NodeId> {
188176
let mut data = NodeData::new(layout);
189177
data.needs_measure = true;
190178

@@ -237,7 +225,7 @@ impl Taffy {
237225
}
238226

239227
/// Sets the [`MeasureFunc`] of the associated node
240-
pub fn set_measure(&mut self, node: NodeId, measure: Option<MeasureFunc>) -> TaffyResult<()> {
228+
pub fn set_measure(&mut self, node: NodeId, measure: Option<MeasureFunc<Measure::Context>>) -> TaffyResult<()> {
241229
let key = node.into();
242230
if let Some(measure) = measure {
243231
self.nodes[key].needs_measure = true;
@@ -404,9 +392,47 @@ impl Taffy {
404392
Ok(self.nodes[node.into()].cache.is_empty())
405393
}
406394

395+
/// Updates the stored layout of the provided `node` and its children
396+
pub fn compute_layout_with_context(
397+
&mut self,
398+
node: NodeId,
399+
available_space: Size<AvailableSpace>,
400+
context: Measure::Context,
401+
) -> Result<(), TaffyError> {
402+
self.context = Some(context);
403+
let result = compute_layout(self, node, available_space);
404+
self.context = None;
405+
result
406+
}
407+
}
408+
409+
impl Taffy<MeasureFunc<()>> {
410+
/// Creates a new [`Taffy`]
411+
///
412+
/// The default capacity of a [`Taffy`] is 16 nodes.
413+
#[must_use]
414+
pub fn new() -> Self {
415+
Self::with_capacity(16)
416+
}
417+
418+
/// Creates a new [`Taffy`] that can store `capacity` nodes before reallocation
419+
#[must_use]
420+
pub fn with_capacity(capacity: usize) -> Self {
421+
Taffy {
422+
// TODO: make this method const upstream,
423+
// so constructors here can be const
424+
nodes: SlotMap::with_capacity(capacity),
425+
children: SlotMap::with_capacity(capacity),
426+
parents: SlotMap::with_capacity(capacity),
427+
measure_funcs: SparseSecondaryMap::with_capacity(capacity),
428+
config: TaffyConfig::default(),
429+
context: None,
430+
}
431+
}
432+
407433
/// Updates the stored layout of the provided `node` and its children
408434
pub fn compute_layout(&mut self, node: NodeId, available_space: Size<AvailableSpace>) -> Result<(), TaffyError> {
409-
compute_layout(self, node, available_space)
435+
self.compute_layout_with_context(node, available_space, ())
410436
}
411437
}
412438

0 commit comments

Comments
 (0)