makepad_widgets/
button.rs

1use {
2    crate::{
3        makepad_derive_widget::*,
4        makepad_draw::*,
5        widget::*
6    }
7};
8live_design!{
9    ButtonBase = {{Button}} {}
10}
11
12#[derive(Clone, WidgetAction)]
13pub enum ButtonAction {
14    None,
15    Clicked,
16    Pressed,
17    Released
18}
19
20#[derive(Live)]
21pub struct Button {
22    #[animator] animator: Animator,
23
24    #[live] draw_bg: DrawQuad,
25    #[live] draw_text: DrawText,
26    #[live] draw_icon: DrawIcon,
27    #[live] icon_walk: Walk,
28    #[live] label_walk: Walk,
29    #[walk] walk: Walk,
30    
31    #[layout] layout: Layout,
32
33    #[live(true)] grab_key_focus: bool,
34
35    #[live] pub text: RcStringMut,
36}
37
38impl LiveHook for Button{
39    fn before_live_design(cx:&mut Cx){
40        register_widget!(cx, Button)
41    }
42}
43
44impl Widget for Button{
45   fn handle_widget_event_with(
46        &mut self,
47        cx: &mut Cx,
48        event: &Event,
49        dispatch_action: &mut dyn FnMut(&mut Cx, WidgetActionItem)
50    ) {
51        let uid = self.widget_uid();
52        self.handle_event_with(cx, event, &mut | cx, action | {
53            dispatch_action(cx, WidgetActionItem::new(action.into(),uid));
54        });
55    }
56
57    fn walk(&mut self, _cx:&mut Cx)->Walk{
58        self.walk
59    }
60    
61    fn redraw(&mut self, cx:&mut Cx){
62        self.draw_bg.redraw(cx)
63    }
64    
65    fn draw_walk_widget(&mut self, cx: &mut Cx2d, walk: Walk) -> WidgetDraw {
66        let _ = self.draw_walk(cx, walk);
67        WidgetDraw::done()
68    }
69    
70    fn text(&self)->String{
71        self.text.as_ref().to_string()
72    }
73    
74    fn set_text(&mut self, v:&str){
75        self.text.as_mut_empty().push_str(v);
76    }
77}
78
79impl Button {
80    
81    pub fn handle_event_with(&mut self, cx: &mut Cx, event: &Event, dispatch_action: &mut dyn FnMut(&mut Cx, ButtonAction)) {
82        self.animator_handle_event(cx, event);
83        match event.hits(cx, self.draw_bg.area()) {
84            Hit::FingerDown(_fe) => {
85                if self.grab_key_focus{
86                    cx.set_key_focus(self.draw_bg.area());
87                }
88                dispatch_action(cx, ButtonAction::Pressed);
89                self.animator_play(cx, id!(hover.pressed));
90            },
91            Hit::FingerHoverIn(_) => {
92                cx.set_cursor(MouseCursor::Hand);
93                 self.animator_play(cx, id!(hover.on));
94            }
95            Hit::FingerHoverOut(_) => {
96                self.animator_play(cx, id!(hover.off));
97            }
98            Hit::FingerUp(fe) => if fe.is_over {
99                dispatch_action(cx, ButtonAction::Clicked);
100                if fe.device.has_hovers() {
101                    self.animator_play(cx, id!(hover.on));
102                }
103                else{
104                    self.animator_play(cx, id!(hover.off));
105                }
106            }
107            else {
108                dispatch_action(cx, ButtonAction::Released);
109                self.animator_play(cx, id!(hover.off));
110            }
111            _ => ()
112        };
113    }
114    /*
115    pub fn draw_text(&mut self, cx: &mut Cx2d, label: &str) {
116        self.draw_bg.begin(cx, self.walk, self.layout);
117        self.draw_text.draw_walk(cx, Walk::fit(), Align::default(), label);
118        self.draw_bg.end(cx);
119    }*/
120    
121    pub fn draw_walk(&mut self, cx: &mut Cx2d, walk: Walk) {
122        self.draw_bg.begin(cx, walk, self.layout);
123        self.draw_text.draw_walk(cx, self.label_walk, Align::default(), self.text.as_ref());
124        self.draw_icon.draw_walk(cx, self.icon_walk);
125        self.draw_bg.end(cx);
126    }
127}
128
129#[derive(Clone, Debug, PartialEq, WidgetRef)]
130pub struct ButtonRef(WidgetRef); 
131
132impl ButtonRef {
133    
134    pub fn clicked(&self, actions:&WidgetActions) -> bool {
135        if let Some(item) = actions.find_single_action(self.widget_uid()) {
136            if let ButtonAction::Clicked = item.action() {
137                return true
138            }
139        }
140        false
141    }
142
143    pub fn pressed(&self, actions:&WidgetActions) -> bool {
144        if let Some(item) = actions.find_single_action(self.widget_uid()) {
145            if let ButtonAction::Pressed = item.action() {
146                return true
147            }
148        }
149        false
150    }
151
152}
153
154#[derive(Clone, Debug, WidgetSet)]
155pub struct ButtonSet(WidgetSet);
156impl ButtonSet{
157    pub fn clicked(&self, actions: &WidgetActions)->bool{
158        for button in self.iter(){
159            if button.clicked(actions){
160                return true
161            }
162        }
163        false
164    }
165    pub fn pressed(&self, actions: &WidgetActions)->bool{
166        for button in self.iter(){
167            if button.pressed(actions){
168                return true
169            }
170        }
171        false
172    }
173}
174