nuit_core/compose/view/widget/
button.rs

1use nuit_derive::Bind;
2
3use crate::{View, Node, Context, Event, IdPath, Id, IdentifyExt};
4
5use super::Text;
6
7/// A widget that performs an action when pressed/tapped.
8#[derive(Debug, Clone, PartialEq, Eq, Bind)]
9pub struct Button<T, F> {
10    label: T,
11    action: Option<F>,
12}
13
14impl<T, F> Button<T, F> {
15    pub fn new(label: T, action: F) -> Self {
16        Self {
17            label,
18            action: Some(action),
19        }
20    }
21}
22
23impl<F> Button<Text, F> {
24    pub fn with_text(label: impl Into<String>, action: F) -> Self {
25        Self {
26            label: Text::new(label),
27            action: Some(action),
28        }
29    }
30}
31
32impl<T, F> View for Button<T, F> where T: View, F: Fn() + 'static {
33    fn fire(&self, event: &Event, event_path: &IdPath, context: &Context) {
34        if let Some(head) = event_path.head() {
35            match head {
36                Id::Index(0) => self.label.fire(event, &event_path.tail(), &context.child(0)),
37                i => panic!("Cannot fire event for child id {} on Button which only has one child", i)
38            }
39        } else if let Event::ButtonTap {} = event {
40            if let Some(ref action) = self.action {
41                action();
42            }
43        }
44    }
45
46    fn render(&self, context: &Context) -> Node {
47        Node::Button { label: Box::new(self.label.render(&context.child(0)).identify(0)) }
48    }
49}