Skip to main content

cranpose_ui/widgets/
flow_row.rs

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