Skip to main content

cranpose_ui/widgets/
box_widget.rs

1//! Box widget implementation
2
3use cranpose_core::NodeId;
4use cranpose_ui_layout::Alignment;
5
6use super::layout::compose_layout;
7use crate::{composable, layout::policies::BoxMeasurePolicy, modifier::Modifier};
8
9/// Specification for Box layout behavior.
10#[derive(Clone, Copy, Debug, PartialEq)]
11pub struct BoxSpec {
12    pub content_alignment: Alignment,
13    pub propagate_min_constraints: bool,
14}
15
16impl BoxSpec {
17    pub fn new() -> Self {
18        Self::default()
19    }
20
21    pub fn content_alignment(mut self, alignment: Alignment) -> Self {
22        self.content_alignment = alignment;
23        self
24    }
25
26    pub fn propagate_min_constraints(mut self, propagate: bool) -> Self {
27        self.propagate_min_constraints = propagate;
28        self
29    }
30}
31
32impl Default for BoxSpec {
33    fn default() -> Self {
34        Self {
35            content_alignment: Alignment::TOP_START,
36            propagate_min_constraints: false,
37        }
38    }
39}
40
41/// Places children over the same area. `content_alignment` selects each child's
42/// position within the box; later children draw above earlier children.
43///
44/// # Example
45///
46/// ```rust
47/// use cranpose_ui::*;
48///
49/// #[composable]
50/// fn Badge() {
51///     Box(
52///         Modifier::empty()
53///             .size_points(100.0, 100.0)
54///             .background(Color(0.1, 0.3, 0.9, 1.0)),
55///         BoxSpec::default().content_alignment(Alignment::CENTER),
56///         || {
57///             Text("Centered", Modifier::empty(), TextStyle::default());
58///         },
59///     );
60/// }
61/// ```
62#[composable]
63pub fn Box<F>(modifier: Modifier, spec: BoxSpec, content: F) -> NodeId
64where
65    F: FnMut() + 'static,
66{
67    let policy = BoxMeasurePolicy::new(spec.content_alignment, spec.propagate_min_constraints);
68    compose_layout(modifier, policy, crate::density::density(), content)
69}