1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
use crate::;
use ;
/// The measured size of a [`FlowLayouter`] object.
///
/// Returned by [`FlowLayouter::measure`] to report the object's
/// intrinsic dimensions for use in flex sizing and container
/// auto-sizing.
/// Context passed to [`FlowLayouter::layout`] for inline flow
/// participation.
///
/// Provides the positional and dimensional information an object
/// needs to determine where it should place its content when
/// participating in an inline formatting context.
/// A self-layouting object that participates in layout flows.
///
/// `FlowLayouter` allows custom types to be embedded directly in
/// a layout tree via [`LayoutChild::Object`](crate::LayoutChild::Object).
/// The trait has two responsibilities:
///
/// - **`measure`** — reports the object's intrinsic size for flex
/// sizing and container auto-sizing.
/// - **`layout`** — performs inline-level layout and returns
/// [`LineSpan`]s describing how the object occupies space in the
/// current formatting context.
///
/// # Flow layout
///
/// In an inline formatting context, the engine calls [`layout`](Self::layout)
/// passing the object's start position, the remaining space on the
/// current line, and the container's line height. The returned spans
/// describe which regions of the inline coordinate space the object
/// consumes. When a span does not fit on the current line, the engine
/// advances to the next line and calls `layout` again.
///
/// # Flex layout
///
/// In a flex formatting context, the engine uses [`measure`](Self::measure)
/// to determine the object's main-axis and cross-axis size. The object
/// is then positioned by the flex algorithm (grow, shrink, alignment,
/// justification, reverse direction, gaps, etc.) like any other flex item.
///
/// # Examples
///
/// ```rust
/// use ui_layout::*;
///
/// #[derive(Debug)]
/// struct MyWidget {
/// width: f32,
/// height: f32,
/// }
///
/// impl FlowLayouter for MyWidget {
/// fn layout(&self, ctx: &FlowLayoutContext) -> Vec<LineSpan> {
/// let (x, y) = ctx.start_pos;
/// vec![LineSpan {
/// x_range: x..(x + self.width),
/// line_pos: (x, y),
/// line_index: 0,
/// }]
/// }
///
/// fn measure(&self, _ctx: &LayoutContext) -> MeasureResult {
/// MeasureResult { width: self.width, height: self.height }
/// }
/// }
///
/// let mut root = LayoutNode::with_children(
/// Style::default(),
/// [LayoutChild::Object(Box::new(MyWidget { width: 50.0, height: 20.0 }))],
/// );
/// LayoutEngine::layout(&mut root, 800.0, 600.0);
/// ```