Skip to main content

cranpose_ui/widgets/
column.rs

1//! Column widget implementation
2
3use cranpose_core::NodeId;
4use cranpose_ui_layout::{HorizontalAlignment, LinearArrangement};
5
6use super::layout::compose_layout;
7use crate::{composable, layout::policies::FlexMeasurePolicy, modifier::Modifier};
8
9/// Specification for Column layout behavior.
10#[derive(Clone, Copy, Debug, PartialEq)]
11pub struct ColumnSpec {
12    /// How children are spaced along the vertical axis. Defaults to `Start`.
13    pub vertical_arrangement: LinearArrangement,
14    /// How children align on the horizontal axis. Defaults to `Start`.
15    pub horizontal_alignment: HorizontalAlignment,
16}
17
18impl ColumnSpec {
19    /// Creates a spec with start arrangement and start alignment.
20    pub fn new() -> Self {
21        Self::default()
22    }
23
24    /// Sets how children are spaced along the vertical axis.
25    pub fn vertical_arrangement(mut self, arrangement: LinearArrangement) -> Self {
26        self.vertical_arrangement = arrangement;
27        self
28    }
29
30    /// Sets how children align on the horizontal axis.
31    pub fn horizontal_alignment(mut self, alignment: HorizontalAlignment) -> Self {
32        self.horizontal_alignment = alignment;
33        self
34    }
35}
36
37impl Default for ColumnSpec {
38    fn default() -> Self {
39        Self {
40            vertical_arrangement: LinearArrangement::Start,
41            horizontal_alignment: HorizontalAlignment::Start,
42        }
43    }
44}
45
46/// Places children from top to bottom. `spec` sets vertical space and horizontal alignment.
47/// Use [`Row`](crate::Row) for a horizontal sequence.
48///
49/// # Example
50///
51/// ```rust
52/// use cranpose_ui::*;
53///
54/// #[composable]
55/// fn Details() {
56///     Column(
57///         Modifier::empty().padding(16.0),
58///         ColumnSpec::default().vertical_arrangement(LinearArrangement::spaced_by(8.0)),
59///         || {
60///             Text("Title", Modifier::empty(), TextStyle::default());
61///             Text("Subtitle", Modifier::empty(), TextStyle::default());
62///         },
63///     );
64/// }
65/// ```
66#[composable]
67pub fn Column<F>(modifier: Modifier, spec: ColumnSpec, content: F) -> NodeId
68where
69    F: FnMut() + 'static,
70{
71    let density = crate::density::density();
72    let mut policy = FlexMeasurePolicy::column(
73        spec.vertical_arrangement,
74        spec.horizontal_alignment,
75        density.density(),
76    );
77    policy.layout_direction = crate::layout_direction();
78    compose_layout(modifier, policy, density, content)
79}