Setup empty morphorm compute module
1//! The layout algorithms themselves
2
3pub(crate) mod common;
4pub(crate) mod leaf;
5
6pub use leaf::compute;
7
8#[cfg(feature = "block_layout")]
9pub(crate) mod block;
10
11#[cfg(feature = "flexbox")]
12pub(crate) mod flexbox;
13
14#[cfg(feature = "grid")]
15pub(crate) mod grid;
16
17#[cfg(feature = "morphorm")]
18pub(crate) mod morphorm;
19
20use crate::geometry::{Line, Size};
21use crate::style::AvailableSpace;
22use crate::tree::{Layout, LayoutTree, NodeId, SizeBaselinesAndMargins, SizingMode};
23
24#[cfg(feature = "block_layout")]
25pub use self::block::BlockAlgorithm;
26
27#[cfg(feature = "flexbox")]
28pub use self::flexbox::FlexboxAlgorithm;
29
30#[cfg(feature = "grid")]
31pub use self::grid::CssGridAlgorithm;
32
33#[cfg(feature = "morphorm")]
34pub use self::morphorm::MorphormAlgorithm;
35
36#[cfg(feature = "taffy_tree")]
37pub(crate) mod taffy_tree;
38
39/// A common interface that all Taffy layout algorithms conform to
40pub trait LayoutAlgorithm {
41 /// The name of the algorithm (mainly used for debug purposes)
42 const NAME: &'static str;
43
44 /// Compute the size of the node given the specified constraints
45 fn measure_size(
46 tree: &mut impl LayoutTree,
47 node: NodeId,
48 known_dimensions: Size<Option<f32>>,
49 parent_size: Size<Option<f32>>,
50 available_space: Size<AvailableSpace>,
51 sizing_mode: SizingMode,
52 vertical_margins_are_collapsible: Line<bool>,
53 ) -> Size<f32>;
54
55 /// Perform a full layout on the node given the specified constraints
56 fn perform_layout(
57 tree: &mut impl LayoutTree,
58 node: NodeId,
59 known_dimensions: Size<Option<f32>>,
60 parent_size: Size<Option<f32>>,
61 available_space: Size<AvailableSpace>,
62 sizing_mode: SizingMode,
63 vertical_margins_are_collapsible: Line<bool>,
64 ) -> SizeBaselinesAndMargins;
65}
66
67/// The public interface to Taffy's hidden node algorithm implementation
68pub struct HiddenAlgorithm;
69impl LayoutAlgorithm for HiddenAlgorithm {
70 const NAME: &'static str = "NONE";
71
72 fn perform_layout(
73 tree: &mut impl LayoutTree,
74 node: NodeId,
75 _known_dimensions: Size<Option<f32>>,
76 _parent_size: Size<Option<f32>>,
77 _available_space: Size<AvailableSpace>,
78 _sizing_mode: SizingMode,
79 _vertical_margins_are_collapsible: Line<bool>,
80 ) -> SizeBaselinesAndMargins {
81 perform_hidden_layout(tree, node);
82 SizeBaselinesAndMargins::HIDDEN
83 }
84
85 fn measure_size(
86 _tree: &mut impl LayoutTree,
87 _node: NodeId,
88 _known_dimensions: Size<Option<f32>>,
89 _parent_size: Size<Option<f32>>,
90 _available_space: Size<AvailableSpace>,
91 _sizing_mode: SizingMode,
92 _vertical_margins_are_collapsible: Line<bool>,
93 ) -> Size<f32> {
94 Size::ZERO
95 }
96}
97
98/// Creates a layout for this node and its children, recursively.
99/// Each hidden node has zero size and is placed at the origin
100fn perform_hidden_layout(tree: &mut impl LayoutTree, node: NodeId) {
101 /// Recursive function to apply hidden layout to all descendents
102 fn perform_hidden_layout_inner(tree: &mut impl LayoutTree, node: NodeId, order: u32) {
103 *tree.layout_mut(node) = Layout::with_order(order);
104 for order in 0..tree.child_count(node) {
105 perform_hidden_layout_inner(tree, tree.child(node, order), order as _);
106 }
107 }
108
109 for order in 0..tree.child_count(node) {
110 perform_hidden_layout_inner(tree, tree.child(node, order), order as _);
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use super::perform_hidden_layout;
117 use crate::geometry::{Point, Size};
118 use crate::style::{Display, Style};
119 use crate::tree::TaffyView;
120 use crate::Taffy;
121
122 #[test]
123 fn hidden_layout_should_hide_recursively() {
124 let mut taffy: Taffy<()> = Taffy::new();
125
126 let style: Style = Style { display: Display::Flex, size: Size::from_lengths(50.0, 50.0), ..Default::default() };
127
128 let grandchild_00 = taffy.new_leaf(style.clone()).unwrap();
129 let grandchild_01 = taffy.new_leaf(style.clone()).unwrap();
130 let child_00 = taffy.new_with_children(style.clone(), &[grandchild_00, grandchild_01]).unwrap();
131
132 let grandchild_02 = taffy.new_leaf(style.clone()).unwrap();
133 let child_01 = taffy.new_with_children(style.clone(), &[grandchild_02]).unwrap();
134
135 let root = taffy
136 .new_with_children(
137 Style { display: Display::None, size: Size::from_lengths(50.0, 50.0), ..Default::default() },
138 &[child_00, child_01],
139 )
140 .unwrap();
141
142 perform_hidden_layout(
143 &mut TaffyView { taffy: &mut taffy, measure_function: |_, _, _, _| Size::ZERO },
144 root.into(),
145 );
146
147 // Whatever size and display-mode the nodes had previously,
148 // all layouts should resolve to ZERO due to the root's DISPLAY::NONE
149 for (node, _) in taffy.nodes.iter().filter(|(node, _)| *node != root.into()) {
150 if let Ok(layout) = taffy.layout(node.into()) {
151 assert_eq!(layout.size, Size::zero());
152 assert_eq!(layout.location, Point::zero());
153 }
154 }
155 }
156}