Skip to main content

cranpose_ui/widgets/
button.rs

1//! Button widget implementation
2
3#![allow(non_snake_case)]
4
5use crate::composable;
6use crate::layout::policies::FlexMeasurePolicy;
7use crate::modifier::Modifier;
8use crate::widgets::Layout;
9use cranpose_core::NodeId;
10use cranpose_ui_layout::{HorizontalAlignment, LinearArrangement};
11
12/// Creates a button widget with click handling.
13///
14/// This is now implemented using LayoutNode with FlexMeasurePolicy (column layout),
15/// following the Jetpack Compose pattern of using Layout for all widgets.
16/// The clickable behavior is provided via the `.clickable()` modifier, which is part
17/// of the modern modifier chain system.
18#[composable]
19pub fn Button<F, G>(modifier: Modifier, on_click: F, content: G) -> NodeId
20where
21    F: FnMut() + 'static,
22    G: FnMut() + 'static,
23{
24    use std::cell::RefCell;
25    use std::rc::Rc;
26
27    // Wrap the on_click handler in Rc<RefCell<>> to make it callable from Fn closure
28    let on_click_rc: Rc<RefCell<dyn FnMut()>> = Rc::new(RefCell::new(on_click));
29
30    // Add clickable modifier to handle click events
31    let clickable_modifier = modifier.clickable(move |_point| {
32        (on_click_rc.borrow_mut())();
33    });
34
35    // Use Layout with FlexMeasurePolicy (column) to arrange button content
36    // This matches how Button is implemented in Jetpack Compose
37    Layout(
38        clickable_modifier,
39        FlexMeasurePolicy::column(
40            LinearArrangement::Center,
41            HorizontalAlignment::CenterHorizontally,
42        ),
43        content,
44    )
45}