Skip to main content

cranpose_ui/widgets/
flow_row.rs

1//! FlowRow widget implementation
2
3#![allow(non_snake_case)]
4
5use cranpose_core::NodeId;
6
7use super::layout::Layout;
8use crate::{composable, layout::policies::FlowRowMeasurePolicy, modifier::Modifier};
9
10/// Specification for FlowRow layout behavior.
11#[derive(Clone, Copy, Debug, PartialEq)]
12pub struct FlowRowSpec {
13    /// Horizontal gap between adjacent children on the same line, in dp
14    /// (Compose: `horizontalArrangement = Arrangement.spacedBy(..)`).
15    pub main_axis_spacing: f32,
16    /// Vertical gap between consecutive lines, in dp
17    /// (Compose: `verticalArrangement = Arrangement.spacedBy(..)`).
18    pub cross_axis_spacing: f32,
19}
20
21impl FlowRowSpec {
22    pub fn new() -> Self {
23        Self::default()
24    }
25
26    pub fn main_axis_spacing(mut self, spacing: f32) -> Self {
27        self.main_axis_spacing = spacing;
28        self
29    }
30
31    pub fn cross_axis_spacing(mut self, spacing: f32) -> Self {
32        self.cross_axis_spacing = spacing;
33        self
34    }
35}
36
37impl Default for FlowRowSpec {
38    fn default() -> Self {
39        Self {
40            main_axis_spacing: 0.0,
41            cross_axis_spacing: 0.0,
42        }
43    }
44}
45
46/// A layout composable that places its children in horizontal sequence and
47/// wraps to the next line when it runs out of width (Jetpack Compose's
48/// `FlowRow`).
49///
50/// # When to use
51/// Use `FlowRow` for content whose item count or widths vary — chip groups,
52/// tag clouds, toolbars on narrow screens. For a single non-wrapping line,
53/// use [`Row`](crate::widgets::Row).
54///
55/// # Arguments
56///
57/// * `modifier` - Modifiers to apply to the flow layout.
58/// * `spec` - Spacing between items on a line and between lines.
59/// * `content` - The children composables to layout.
60///
61/// # Example
62///
63/// ```rust,ignore
64/// FlowRow(
65///     Modifier::fill_max_width(),
66///     FlowRowSpec::new().main_axis_spacing(8.0).cross_axis_spacing(4.0),
67///     || {
68///         for label in ["Rust", "Compose", "Android"] {
69///             Chip(label);
70///         }
71///     },
72/// );
73/// ```
74#[composable]
75pub fn FlowRow<F>(modifier: Modifier, spec: FlowRowSpec, content: F) -> NodeId
76where
77    F: FnMut() + 'static,
78{
79    let policy = FlowRowMeasurePolicy::new(spec.main_axis_spacing, spec.cross_axis_spacing);
80    Layout(modifier, policy, content)
81}