makepad_widgets/
check_box.rs

1use {
2    crate::{
3        makepad_derive_widget::*,
4        makepad_draw::*,
5        widget::*,
6    }
7};
8
9live_design!{
10    DrawCheckBox = {{DrawCheckBox}} {}
11    CheckBoxBase = {{CheckBox}} {}
12}
13
14#[derive(Live, LiveHook)]
15#[repr(C)]
16pub struct DrawCheckBox {
17    #[deref] draw_super: DrawQuad,
18    #[live] check_type: CheckType,
19    #[live] hover: f32,
20    #[live] focus: f32,
21    #[live] selected: f32
22}
23
24#[derive(Live, LiveHook)]
25#[live_ignore]
26#[repr(u32)]
27pub enum CheckType {
28    #[pick] Check = shader_enum(1),
29    Radio = shader_enum(2),
30    Toggle = shader_enum(3),
31    None = shader_enum(4),
32}
33
34#[derive(Live)]
35pub struct CheckBox {
36    
37    #[walk] walk: Walk,
38    #[layout] layout: Layout,
39    #[animator] animator: Animator,
40    
41    #[live] icon_walk: Walk,
42    #[live] label_walk: Walk,
43    #[live] label_align: Align,
44    
45    #[live] draw_check: DrawCheckBox,
46    #[live] draw_text: DrawText,
47    #[live] draw_icon: DrawIcon,
48    
49    #[live] text: RcStringMut,
50    
51    #[live] bind: String,
52}
53
54impl LiveHook for CheckBox {
55    fn before_live_design(cx: &mut Cx) {
56        register_widget!(cx, CheckBox)
57    }
58}
59
60#[derive(Clone, WidgetAction)]
61pub enum CheckBoxAction {
62    Change(bool),
63    None
64}
65
66#[derive(Live, LiveHook)]#[repr(C)]
67struct DrawLabelText {
68    #[deref] draw_super: DrawText,
69    #[live] hover: f32,
70    #[live] pressed: f32,
71}
72
73impl CheckBox {
74    
75    pub fn handle_event_with(&mut self, cx: &mut Cx, event: &Event, dispatch_action: &mut dyn FnMut(&mut Cx, CheckBoxAction)) {
76        self.animator_handle_event(cx, event);
77        
78        match event.hits(cx, self.draw_check.area()) {
79            Hit::FingerHoverIn(_) => {
80                cx.set_cursor(MouseCursor::Hand);
81                self.animator_play(cx, id!(hover.on));
82            }
83            Hit::FingerHoverOut(_) => {
84                self.animator_play(cx, id!(hover.off));
85            },
86            Hit::FingerDown(_fe) => {
87                if self.animator_in_state(cx, id!(selected.on)) {
88                    self.animator_play(cx, id!(selected.off));
89                    dispatch_action(cx, CheckBoxAction::Change(false));
90                }
91                else {
92                    self.animator_play(cx, id!(selected.on));
93                    dispatch_action(cx, CheckBoxAction::Change(true));
94                }
95            },
96            Hit::FingerUp(_fe) => {
97                
98            }
99            Hit::FingerMove(_fe) => {
100                
101            }
102            _ => ()
103        }
104    }
105    
106    pub fn draw_walk(&mut self, cx: &mut Cx2d, walk: Walk) {
107        self.draw_check.begin(cx, walk, self.layout);
108        self.draw_text.draw_walk(cx, self.label_walk, self.label_align, self.text.as_ref());
109        self.draw_icon.draw_walk(cx, self.icon_walk);
110        self.draw_check.end(cx);
111    }
112}
113
114impl Widget for CheckBox {
115    
116    fn widget_to_data(&self, _cx: &mut Cx, actions: &WidgetActions, nodes: &mut LiveNodeVec, path: &[LiveId]) -> bool {
117        match actions.single_action(self.widget_uid()) {
118            CheckBoxAction::Change(v) => {
119                nodes.write_field_value(path, LiveValue::Bool(v));
120                true
121            }
122            _ => false
123        }
124    }
125    
126    fn data_to_widget(&mut self, cx: &mut Cx, nodes: &[LiveNode], path: &[LiveId]) {
127        if let Some(value) = nodes.read_field_value(path) {
128            if let Some(value) = value.as_bool() {
129                self.animator_toggle(cx, value, Animate::Yes, id!(selected.on), id!(selected.off));
130            }
131        }
132    }
133    
134    fn redraw(&mut self, cx: &mut Cx) {
135        self.draw_check.redraw(cx);
136    }
137    
138    fn handle_widget_event_with(&mut self, cx: &mut Cx, event: &Event, dispatch_action: &mut dyn FnMut(&mut Cx, WidgetActionItem)) {
139        let uid = self.widget_uid();
140        self.handle_event_with(cx, event, &mut | cx, action | {
141            dispatch_action(cx, WidgetActionItem::new(action.into(), uid))
142        });
143    }
144    
145    fn walk(&mut self, _cx: &mut Cx) -> Walk {self.walk}
146    
147    fn draw_walk_widget(&mut self, cx: &mut Cx2d, walk: Walk) -> WidgetDraw {
148        self.draw_walk(cx, walk);
149        WidgetDraw::done()
150    }
151    
152    fn text(&self) -> String {
153        self.text.as_ref().to_string()
154    }
155    
156    fn set_text(&mut self, v: &str) {
157        self.text.as_mut_empty().push_str(v);
158    }
159}
160
161#[derive(Clone, PartialEq, WidgetRef)]
162pub struct CheckBoxRef(WidgetRef);
163
164impl CheckBoxRef {
165    pub fn changed(&self, actions: &WidgetActions) -> Option<bool> {
166        if let Some(item) = actions.find_single_action(self.widget_uid()) {
167            if let CheckBoxAction::Change(b) = item.action() {
168                return Some(b)
169            }
170        }
171        None
172    }
173    
174    pub fn set_text(&self, text: &str) {
175        if let Some(mut inner) = self.borrow_mut() {
176            let s = inner.text.as_mut_empty();
177            s.push_str(text);
178        }
179    }
180    
181    pub fn selected(&self, cx: &Cx) -> bool {
182        if let Some(inner) = self.borrow() {
183            inner.animator_in_state(cx, id!(selected.on))
184        }
185        else {
186            false
187        }
188    }
189    
190    pub fn set_selected(&self, cx: &mut Cx, value: bool) {
191        if let Some(mut inner) = self.borrow_mut() {
192            inner.animator_toggle(cx, value, Animate::Yes, id!(selected.on), id!(selected.off));
193        }
194    }
195}