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}