ui_layout/node.rs
1use crate::{FragmentPlacement, ItemFragment, LayoutBoxes, Style};
2
3type LayoutCache = (u32, (LayoutBoxes, ((f32, f32), f32)));
4
5/// A node in the layout tree.
6///
7/// A `LayoutNode` represents a single layout object and is responsible for:
8///
9/// - Holding layout-related style information
10/// - Owning child layout nodes (structural hierarchy)
11/// - Providing inline fragment inputs
12/// - Storing layout results (box model and fragment placements)
13///
14/// ## Fragment model
15///
16/// `self_fragments` represent the **input fragments** provided by the user.
17/// They are immutable logical units and are never reordered by the layout engine.
18///
19/// `placements` represent the **layout result** for fragments.
20/// Each entry corresponds 1:1 to `self_fragments` and stores relative placement
21/// information computed during layout.
22///
23/// Only inline-level nodes are expected to have non-empty `self_fragments`.
24/// For block-level or flex-level nodes, this vector should be empty.
25///
26/// ## Layout invariants
27///
28/// - The order of `self_fragments` is preserved during layout
29/// - `placements.len() == self_fragments.len()` after layout
30/// - `placements` are meaningful only after layout computation
31///
32/// This structure intentionally does not distinguish between inline, block,
33/// or flex nodes at the type level; their behavior is defined by `Style::display`.
34///
35/// ## Results storage
36/// Results of the layout process are stored directly within each `LayoutNode`,
37/// allowing for easy access and further processing after layout computation.
38/// This includes the computed `BoxModel` and fragment placements.
39/// - `layout_boxes`: The computed box model for this node after layout.
40/// - `placements`: The computed placements for each fragment in `self_fragments`.
41#[non_exhaustive]
42#[derive(Debug)]
43pub struct LayoutNode {
44 pub style: Style,
45 pub self_fragments: Vec<ItemFragment>,
46
47 pub children: Vec<LayoutNode>,
48
49 pub layout_boxes: LayoutBoxes,
50 pub placements: Vec<FragmentPlacement>,
51
52 // --- cache ---
53 pub(crate) layout_boxes_cache: LayoutCache, // (key, layout_boxes, ((f32, f32), f32))
54}
55
56impl LayoutNode {
57 pub fn new(style: Style) -> Self {
58 Self {
59 style,
60 self_fragments: Vec::new(),
61 placements: Vec::new(),
62 layout_boxes: LayoutBoxes::default(),
63 children: Vec::new(),
64 layout_boxes_cache: (0, (LayoutBoxes::default(), ((0.0, 0.0), 0.0))),
65 }
66 }
67
68 pub fn with_children(style: Style, children: Vec<LayoutNode>) -> Self {
69 Self {
70 style,
71 self_fragments: Vec::new(),
72 placements: Vec::new(),
73 layout_boxes: LayoutBoxes::default(),
74 children,
75 layout_boxes_cache: (0, (LayoutBoxes::default(), ((0.0, 0.0), 0.0))),
76 }
77 }
78
79 /// Sets input fragments for this node.
80 ///
81 /// This method defines the inline content owned by the node.
82 /// Any previously computed fragment placements become invalid and must
83 /// be recomputed during the next layout pass.
84 pub fn set_fragments(&mut self, fragments: Vec<ItemFragment>) {
85 self.self_fragments = fragments;
86 self.placements.reserve(self.self_fragments.len());
87 }
88}