tawasuyu

tawasuyu/taffy

A high performance rust-powered UI layout library

Rust 497HTML 254C 19JavaScript 81329 Sutichaykuna

⎇ 08376be245a487c3d3438dfd5108a67f48222739 src/tree/mod.rs Rust · 142 siq'ikuna · 5.2 KB Ñawpa willay Pi imata llamkarqan ch'uya

Add `taffy_tree` feature to opt-out of default Taffy tree (#448) fda1f88ed · Martijn Arts ·

1//! Contains both [a high-level interface to Taffy](crate::Taffy) using a ready-made node tree, and [a trait for defining a custom node trees](crate::tree::LayoutTree) / utility types to help with that.
2
3use crate::geometry::{Point, Size};
4use crate::style::{AvailableSpace, Style};
5
6// Submodules
7mod cache;
8pub use cache::{Cache, CacheEntry};
9mod measure_func;
10pub use measure_func::{Measurable, MeasureFunc};
11mod node;
12#[cfg(feature = "taffy_tree")]
13pub(self) use node::NodeData;
14pub use node::NodeId;
15#[cfg(feature = "taffy_tree")]
16mod taffy_tree;
17#[cfg(feature = "taffy_tree")]
18pub use taffy_tree::{Taffy, TaffyChildIter, TaffyError, TaffyResult};
19mod layout;
20
21/// Any item that implements the LayoutTree can be layed out using Taffy's algorithms.
22///
23/// Generally, Taffy expects your Node tree to be indexable by stable indices. A "stable" index means that the Node's ID
24/// remains the same between re-layouts.
25pub trait LayoutTree {
26    /// Type representing an iterator of the children of a node
27    type ChildIter<'a>: Iterator<Item = NodeId>
28    where
29        Self: 'a;
30
31    /// Get the list of children IDs for the given node
32    fn children(&self, node: NodeId) -> Self::ChildIter<'_>;
33
34    /// Get the number of children for the given node
35    fn child_count(&self, node: NodeId) -> usize;
36
37    /// Get a specific child of a node, where the index represents the nth child
38    fn child(&self, node: NodeId, index: usize) -> NodeId;
39
40    /// Get the [`Style`] for this node.
41    fn style(&self, node: NodeId) -> &Style;
42
43    /// Get a reference to the node's output layout
44    fn layout(&self, node: NodeId) -> &Layout;
45
46    /// Modify the node's output layout
47    fn layout_mut(&mut self, node: NodeId) -> &mut Layout;
48
49    /// Compute the size of the node given the specified constraints
50    fn measure_child_size(
51        &mut self,
52        node: NodeId,
53        known_dimensions: Size<Option<f32>>,
54        parent_size: Size<Option<f32>>,
55        available_space: Size<AvailableSpace>,
56        sizing_mode: SizingMode,
57    ) -> Size<f32>;
58
59    /// Perform a full layout on the node given the specified constraints
60    fn perform_child_layout(
61        &mut self,
62        node: NodeId,
63        known_dimensions: Size<Option<f32>>,
64        parent_size: Size<Option<f32>>,
65        available_space: Size<AvailableSpace>,
66        sizing_mode: SizingMode,
67    ) -> SizeAndBaselines;
68}
69
70/// Whether we are performing a full layout, or we merely need to size the node
71#[derive(Copy, Clone, Debug, PartialEq, Eq)]
72pub enum RunMode {
73    /// A full layout for this node and all children should be computed
74    PeformLayout,
75    /// The layout algorithm should be executed such that an accurate container size for the node can be determined.
76    /// Layout steps that aren't necessary for determining the container size of the current node can be skipped.
77    ComputeSize,
78}
79
80/// Whether styles should be taken into account when computing size
81#[derive(Copy, Clone, Debug, PartialEq, Eq)]
82pub enum SizingMode {
83    /// Only content contributions should be taken into account
84    ContentSize,
85    /// Inherent size styles should be taken into account in addition to content contributions
86    InherentSize,
87}
88
89/// A struct containing both the size of a node and it's first baseline in each dimension (if it has any)
90///
91/// A baseline is the line on which text sits. Your node likely has a baseline if it is a text node, or contains
92/// children that may be text nodes. See <https://www.w3.org/TR/css-writing-modes-3/#intro-baselines> for details.
93/// If your node does not have a baseline (or you are unsure how to compute it), then simply return `Point::NONE`
94/// for the first_baselines field
95#[derive(Debug, Copy, Clone)]
96pub struct SizeAndBaselines {
97    /// The size of the node
98    pub size: Size<f32>,
99    /// The first baseline of the node in each dimension, if any
100    pub first_baselines: Point<Option<f32>>,
101}
102
103impl From<Size<f32>> for SizeAndBaselines {
104    fn from(size: Size<f32>) -> Self {
105        Self { size, first_baselines: Point::NONE }
106    }
107}
108
109/// The final result of a layout algorithm for a single node.
110#[derive(Debug, Copy, Clone)]
111pub struct Layout {
112    /// The relative ordering of the node
113    ///
114    /// Nodes with a higher order should be rendered on top of those with a lower order.
115    /// This is effectively a topological sort of each tree.
116    pub order: u32,
117    /// The width and height of the node
118    pub size: Size<f32>,
119    /// The bottom-left corner of the node
120    pub location: Point<f32>,
121}
122
123impl Layout {
124    /// Creates a new zero-[`Layout`].
125    ///
126    /// The Zero-layout has size and location set to ZERO.
127    /// The `order` value of this layout is set to the minimum value of 0.
128    /// This means it should be rendered below all other [`Layout`]s.
129    #[must_use]
130    pub const fn new() -> Self {
131        Self { order: 0, size: Size::zero(), location: Point::ZERO }
132    }
133
134    /// Creates a new zero-[`Layout`] with the supplied `order` value.
135    ///
136    /// Nodes with a higher order should be rendered on top of those with a lower order.
137    /// The Zero-layout has size and location set to ZERO.
138    #[must_use]
139    pub const fn with_order(order: u32) -> Self {
140        Self { order, size: Size::zero(), location: Point::ZERO }
141    }
142}