makepad_widgets/
button.rs1use {
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 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