makepad_widgets/
radio_button.rs1use {
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 if let Some(index) = self.selected(cx, actions){
162 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}