winio/widgets/
radio_button.rs1use std::{
2 hint::unreachable_unchecked,
3 ops::{Deref, DerefMut},
4};
5
6use inherit_methods_macro::inherit_methods;
7use winio_elm::{Child, Component, ComponentSender};
8use winio_handle::BorrowedContainer;
9use winio_primitive::{Enable, Failable, Layoutable, Point, Size, TextWidget, ToolTip, Visible};
10
11use crate::{
12 sys,
13 sys::{Error, Result},
14};
15
16#[derive(Debug)]
18pub struct RadioButton {
19 widget: sys::RadioButton,
20}
21
22impl Failable for RadioButton {
23 type Error = Error;
24}
25
26#[inherit_methods(from = "self.widget")]
27impl ToolTip for RadioButton {
28 fn tooltip(&self) -> Result<String>;
29
30 fn set_tooltip(&mut self, s: impl AsRef<str>) -> Result<()>;
31}
32
33#[inherit_methods(from = "self.widget")]
34impl TextWidget for RadioButton {
35 fn text(&self) -> Result<String>;
36
37 fn set_text(&mut self, s: impl AsRef<str>) -> Result<()>;
38}
39
40#[inherit_methods(from = "self.widget")]
41impl RadioButton {
42 pub fn is_checked(&self) -> Result<bool>;
44
45 pub fn set_checked(&mut self, v: bool) -> Result<()>;
47}
48
49#[inherit_methods(from = "self.widget")]
50impl Visible for RadioButton {
51 fn is_visible(&self) -> Result<bool>;
52
53 fn set_visible(&mut self, v: bool) -> Result<()>;
54}
55
56#[inherit_methods(from = "self.widget")]
57impl Enable for RadioButton {
58 fn is_enabled(&self) -> Result<bool>;
59
60 fn set_enabled(&mut self, v: bool) -> Result<()>;
61}
62
63#[inherit_methods(from = "self.widget")]
64impl Layoutable for RadioButton {
65 fn loc(&self) -> Result<Point>;
66
67 fn set_loc(&mut self, p: Point) -> Result<()>;
68
69 fn size(&self) -> Result<Size>;
70
71 fn set_size(&mut self, v: Size) -> Result<()>;
72
73 fn preferred_size(&self) -> Result<Size>;
74}
75
76#[derive(Debug)]
78#[non_exhaustive]
79pub enum RadioButtonEvent {
80 Click,
82}
83
84#[derive(Debug)]
86#[non_exhaustive]
87pub enum RadioButtonMessage {}
88
89impl Component for RadioButton {
90 type Error = Error;
91 type Event = RadioButtonEvent;
92 type Init<'a> = BorrowedContainer<'a>;
93 type Message = RadioButtonMessage;
94
95 async fn init(init: Self::Init<'_>, _sender: &ComponentSender<Self>) -> Result<Self> {
96 let widget = sys::RadioButton::new(init)?;
97 Ok(Self { widget })
98 }
99
100 async fn start(&mut self, sender: &ComponentSender<Self>) -> ! {
101 loop {
102 self.widget.wait_click().await;
103 sender.output(RadioButtonEvent::Click);
104 }
105 }
106}
107
108winio_handle::impl_as_widget!(RadioButton, widget);
109
110pub struct RadioButtonGroup {
112 radios: Vec<Child<RadioButton>>,
113}
114
115#[derive(Debug)]
117#[non_exhaustive]
118pub enum RadioButtonGroupEvent {
119 Click(usize),
121}
122
123#[derive(Debug)]
125#[non_exhaustive]
126pub enum RadioButtonGroupMessage {
127 Click(usize),
129}
130
131impl Component for RadioButtonGroup {
132 type Error = Error;
133 type Event = RadioButtonGroupEvent;
134 type Init<'a> = Vec<Child<RadioButton>>;
135 type Message = RadioButtonGroupMessage;
136
137 async fn init(init: Self::Init<'_>, _sender: &ComponentSender<Self>) -> Result<Self> {
138 Ok(Self { radios: init })
139 }
140
141 async fn start(&mut self, sender: &ComponentSender<Self>) -> ! {
142 let futures = self
143 .radios
144 .iter_mut()
145 .enumerate()
146 .map(|(i, c)| {
147 c.start(
148 sender,
149 move |e| match e {
150 RadioButtonEvent::Click => Some(RadioButtonGroupMessage::Click(i)),
151 },
152 || unsafe { unreachable_unchecked() },
154 )
155 })
156 .collect::<Vec<_>>();
157 futures_util::future::join_all(futures).await;
158 std::future::pending().await
159 }
160
161 async fn update(
162 &mut self,
163 message: Self::Message,
164 sender: &ComponentSender<Self>,
165 ) -> Result<bool> {
166 match message {
167 RadioButtonGroupMessage::Click(i) => {
168 for (idx, r) in self.radios.iter_mut().enumerate() {
169 r.set_checked(idx == i)?;
170 }
171 sender.output(RadioButtonGroupEvent::Click(i));
172 Ok(false)
173 }
174 }
175 }
176}
177
178impl Deref for RadioButtonGroup {
179 type Target = Vec<Child<RadioButton>>;
180
181 fn deref(&self) -> &Self::Target {
182 &self.radios
183 }
184}
185
186impl DerefMut for RadioButtonGroup {
187 fn deref_mut(&mut self) -> &mut Self::Target {
188 &mut self.radios
189 }
190}