tui_lipan/widgets/flow/
mod.rs1mod layout;
2mod node;
3mod reconcile;
4
5pub(crate) use self::layout::{measure_flow, pack_rows};
6pub use self::node::FlowNode;
7pub(crate) use self::reconcile::reconcile_flow;
8
9use crate::core::element::{Element, ElementKind};
10use crate::style::{
11 Align, BorderStyle, Justify, LayoutConstraints, Length, Padding, ShrinkPriority, Style,
12};
13
14#[derive(Clone)]
22pub struct Flow {
23 pub(crate) children: Vec<Element>,
24 pub(crate) gap: u16,
25 pub(crate) row_gap: Option<u16>,
28 pub(crate) align: Align,
29 pub(crate) justify: Justify,
30 pub(crate) padding: Padding,
31 pub(crate) border: bool,
32 pub(crate) border_style: BorderStyle,
33 pub(crate) style: Style,
34 pub(crate) width: Length,
35 pub(crate) height: Length,
36 pub(crate) shrinkable: bool,
41}
42
43impl Default for Flow {
44 fn default() -> Self {
45 Self {
46 children: Vec::new(),
47 gap: 0,
48 row_gap: None,
49 align: Align::Start,
50 justify: Justify::Start,
51 padding: Padding::default(),
52 border: false,
53 border_style: BorderStyle::Plain,
54 style: Style::default(),
55 width: Length::Flex(1),
56 height: Length::Auto,
57 shrinkable: false,
58 }
59 }
60}
61
62impl Flow {
63 pub fn new() -> Self {
65 Self::default()
66 }
67
68 pub fn child(mut self, child: impl Into<Element>) -> Self {
70 self.children.push(child.into());
71 self
72 }
73
74 pub fn children(mut self, children: impl IntoIterator<Item = Element>) -> Self {
77 self.children = children.into_iter().collect();
78 self
79 }
80
81 pub fn gap(mut self, gap: u16) -> Self {
83 self.gap = gap;
84 self
85 }
86
87 pub fn row_gap(mut self, row_gap: u16) -> Self {
91 self.row_gap = Some(row_gap);
92 self
93 }
94
95 pub fn shrinkable(mut self, shrinkable: bool) -> Self {
101 self.shrinkable = shrinkable;
102 self
103 }
104
105 pub fn align(mut self, align: Align) -> Self {
107 self.align = align;
108 self
109 }
110
111 pub fn justify(mut self, justify: Justify) -> Self {
119 self.justify = justify;
120 self
121 }
122
123 pub fn padding(mut self, padding: impl Into<Padding>) -> Self {
125 self.padding = padding.into();
126 self
127 }
128
129 pub fn border(mut self, border: bool) -> Self {
131 self.border = border;
132 self
133 }
134
135 pub fn border_style(mut self, border_style: BorderStyle) -> Self {
137 self.border_style = border_style;
138 self
139 }
140
141 pub fn style(mut self, style: Style) -> Self {
143 self.style = style;
144 self
145 }
146
147 pub fn width(mut self, width: Length) -> Self {
149 self.width = width;
150 self
151 }
152
153 pub fn height(mut self, height: Length) -> Self {
155 self.height = height;
156 self
157 }
158}
159
160impl From<Flow> for Element {
161 fn from(value: Flow) -> Self {
162 let shrink_priority = if value.shrinkable {
163 ShrinkPriority::First
164 } else {
165 ShrinkPriority::Normal
166 };
167 Element::new(ElementKind::Flow(value)).with_layout(
168 LayoutConstraints::default()
169 .reflows(true)
170 .shrink_priority(shrink_priority),
171 )
172 }
173}
174
175impl crate::layout::hash::LayoutHash for Flow {
176 fn layout_hash(
177 &self,
178 hasher: &mut impl std::hash::Hasher,
179 recurse: &dyn Fn(&Element) -> Option<u64>,
180 ) -> Option<()> {
181 use std::hash::Hash;
182
183 self.gap.hash(hasher);
184 self.row_gap.hash(hasher);
185 self.align.hash(hasher);
186 self.justify.hash(hasher);
187 self.padding.hash(hasher);
188 self.border.hash(hasher);
189 self.border_style.hash(hasher);
190 self.width.hash(hasher);
191 self.height.hash(hasher);
192 self.shrinkable.hash(hasher);
193
194 let non_portal_count = self
195 .children
196 .iter()
197 .filter(|child| !matches!(child.kind, ElementKind::Portal(_)))
198 .count();
199 non_portal_count.hash(hasher);
200 for child in &self.children {
201 if matches!(child.kind, ElementKind::Portal(_)) {
202 continue;
203 }
204 recurse(child)?.hash(hasher);
205 }
206
207 Some(())
208 }
209}