makepad_widgets/
radio_button.rs

1use {
2    crate::{
3        makepad_derive_widget::*,
4        makepad_draw::*,
5        widget::*,
6    }
7};
8
9live_design!{
10    DrawRadioButton = {{DrawRadioButton}} {}
11    RadioButtonBase = {{RadioButton}} {}
12}
13
14#[derive(Live, LiveHook)]
15#[repr(C)]
16pub struct DrawRadioButton {
17    #[deref] draw_super: DrawQuad,
18    #[live] radio_type: RadioType,
19    #[live] hover: f32,
20    #[live] focus: f32,
21    #[live] selected: f32
22}
23
24
25#[derive(Live, LiveHook)]
26#[live_ignore]
27#[repr(u32)]
28pub enum RadioType {
29    #[pick] Round = shader_enum(1),
30    Tab = shader_enum(2),
31}
32
33#[derive(Live)]
34pub struct RadioButton {
35    #[live] draw_radio: DrawRadioButton,
36    #[live] draw_icon: DrawIcon,
37    #[live] draw_text: DrawText,
38    
39    #[live] icon_walk: Walk,
40    #[walk] walk: Walk,
41    
42    #[live] value: LiveValue,
43    
44    #[layout] layout: Layout,
45    #[animator] animator: Animator,
46    
47    #[live] label_walk: Walk,
48    #[live] label_align: Align,
49    #[live] label: String,
50    
51    #[live] bind: String,
52}
53
54impl LiveHook for RadioButton{
55    fn before_live_design(cx:&mut Cx){
56        register_widget!(cx,RadioButton)
57    }
58}
59
60#[derive(Clone, WidgetAction)]
61pub enum RadioButtonAction {
62    Clicked,
63    None
64}
65
66
67impl RadioButton {
68    
69    pub fn handle_event_with(&mut self, cx: &mut Cx, event: &Event, dispatch_action: &mut dyn FnMut(&mut Cx, RadioButtonAction)) {
70        self.animator_handle_event(cx, event);
71        
72        match event.hits(cx, self.draw_radio.area()) {
73            Hit::FingerHoverIn(_) => {
74                cx.set_cursor(MouseCursor::Hand);
75                self.animator_play(cx, id!(hover.on));
76            }
77            Hit::FingerHoverOut(_) => {
78                cx.set_cursor(MouseCursor::Arrow);
79                self.animator_play(cx, id!(hover.off));
80            },
81            Hit::FingerDown(_fe) => {
82                if self.animator_in_state(cx, id!(selected.off)) {
83                    self.animator_play(cx, id!(selected.on));
84                    dispatch_action(cx, RadioButtonAction::Clicked);
85                }
86            },
87            Hit::FingerUp(_fe) => {
88                
89            }
90            Hit::FingerMove(_fe) => {
91                
92            }
93            _ => ()
94        }
95    }
96    
97    pub fn draw_walk(&mut self, cx: &mut Cx2d, walk: Walk) {
98        self.draw_radio.begin(cx, walk, self.layout);
99        self.draw_icon.draw_walk(cx, self.icon_walk);
100        self.draw_text.draw_walk(cx, self.label_walk, self.label_align, &self.label);
101        self.draw_radio.end(cx);
102    }
103}
104
105impl Widget for RadioButton {
106    
107    fn redraw(&mut self, cx: &mut Cx) {
108        self.draw_radio.redraw(cx);
109    }
110    
111    fn handle_widget_event_with(&mut self, cx: &mut Cx, event: &Event, dispatch_action: &mut dyn FnMut(&mut Cx, WidgetActionItem)) {
112        let uid = self.widget_uid();
113        self.handle_event_with(cx, event, &mut | cx, action | {
114            dispatch_action(cx, WidgetActionItem::new(action.into(), uid))
115        });
116    }
117    
118    fn walk(&mut self, _cx:&mut Cx) -> Walk {self.walk}
119    
120    fn draw_walk_widget(&mut self, cx: &mut Cx2d, walk: Walk) -> WidgetDraw {
121        self.draw_walk(cx, walk);
122        WidgetDraw::done()
123    }
124}
125
126#[derive(Clone, PartialEq, WidgetRef)]
127pub struct RadioButtonRef(WidgetRef);
128
129impl RadioButtonRef{
130    fn unselect(&self, cx:&mut Cx){
131        if let Some(mut inner) = self.borrow_mut(){
132            inner.animator_play(cx, id!(selected.off));
133        }
134    }
135}
136
137#[derive(Clone, WidgetSet)]
138pub struct RadioButtonSet(WidgetSet);
139
140impl RadioButtonSet{
141    
142    pub fn selected(&self, cx: &mut Cx, actions: &WidgetActions)->Option<usize>{
143        for action in actions{
144            match action.action() {
145                RadioButtonAction::Clicked => if let Some(index) = self.0.iter().position(|v| v.widget_uid() == action.widget_uid){
146                    for (i, item) in self.0.iter().enumerate(){
147                        if i != index{
148                            RadioButtonRef(item).unselect(cx);
149                        }
150                    }
151                    return Some(index);
152                }
153                _ => ()
154            }
155        }
156        None
157    }
158    
159    pub fn selected_to_visible(&self, cx: &mut Cx, ui:&WidgetRef, actions: &WidgetActions, paths:&[&[LiveId]] ) {
160        // find a widget action that is in our radiogroup
161        if let Some(index) = self.selected(cx, actions){
162            // ok now we set visible
163            for (i,path) in paths.iter().enumerate(){
164                let widget = ui.widget(path);
165                widget.apply_over(cx, live!{visible:(i == index)});
166                widget.redraw(cx);
167            }
168        }
169    }
170}