cranpose_ui/widgets/flow_row.rs
1//! FlowRow widget implementation
2
3use cranpose_core::NodeId;
4
5use super::layout::Layout;
6use crate::{composable, layout::policies::FlowRowMeasurePolicy, modifier::Modifier};
7
8/// Specification for FlowRow layout behavior.
9#[derive(Clone, Copy, Debug, PartialEq)]
10pub struct FlowRowSpec {
11 /// Horizontal gap between adjacent children on the same line, in dp
12 /// (Compose: `horizontalArrangement = Arrangement.spacedBy(..)`).
13 pub main_axis_spacing: f32,
14 /// Vertical gap between consecutive lines, in dp
15 /// (Compose: `verticalArrangement = Arrangement.spacedBy(..)`).
16 pub cross_axis_spacing: f32,
17}
18
19impl FlowRowSpec {
20 pub fn new() -> Self {
21 Self::default()
22 }
23
24 pub fn main_axis_spacing(mut self, spacing: f32) -> Self {
25 self.main_axis_spacing = spacing;
26 self
27 }
28
29 pub fn cross_axis_spacing(mut self, spacing: f32) -> Self {
30 self.cross_axis_spacing = spacing;
31 self
32 }
33}
34
35impl Default for FlowRowSpec {
36 fn default() -> Self {
37 Self {
38 main_axis_spacing: 0.0,
39 cross_axis_spacing: 0.0,
40 }
41 }
42}
43
44/// Places children across a row and starts a new row when the available width is full.
45/// The spec sets the space between children and between rows.
46///
47/// # Example
48///
49/// ```rust
50/// use cranpose_ui::{
51/// widgets::{FlowRow, FlowRowSpec},
52/// *,
53/// };
54///
55/// #[composable]
56/// fn Topics() {
57/// FlowRow(
58/// Modifier::empty().fill_max_width(),
59/// FlowRowSpec::new()
60/// .main_axis_spacing(8.0)
61/// .cross_axis_spacing(4.0),
62/// || {
63/// for label in ["Rust", "Compose", "Android"] {
64/// Text(label, Modifier::empty().padding(8.0), TextStyle::default());
65/// }
66/// },
67/// );
68/// }
69/// ```
70#[composable]
71pub fn FlowRow<F>(modifier: Modifier, spec: FlowRowSpec, content: F) -> NodeId
72where
73 F: FnMut() + 'static,
74{
75 let policy = FlowRowMeasurePolicy::new(spec.main_axis_spacing, spec.cross_axis_spacing);
76 Layout(modifier, policy, content)
77}