use alloc::string::String;
use rlvgl_core::event::Event;
use rlvgl_core::renderer::Renderer;
use rlvgl_core::style::Style;
use rlvgl_core::widget::{Color, Rect, Widget};
pub struct Radio {
bounds: Rect,
text: String,
pub style: Style,
pub text_color: Color,
pub dot_color: Color,
selected: bool,
}
impl Radio {
pub fn new(text: impl Into<String>, bounds: Rect) -> Self {
Self {
bounds,
text: text.into(),
style: Style::default(),
text_color: Color(0, 0, 0, 255),
dot_color: Color(0, 0, 0, 255),
selected: false,
}
}
pub fn is_selected(&self) -> bool {
self.selected
}
pub fn set_selected(&mut self, value: bool) {
self.selected = value;
}
}
impl Widget for Radio {
fn bounds(&self) -> Rect {
self.bounds
}
fn draw(&self, renderer: &mut dyn Renderer) {
renderer.fill_rect(self.bounds, self.style.bg_color);
let size = 10;
let circle_rect = Rect {
x: self.bounds.x,
y: self.bounds.y,
width: size,
height: size,
};
renderer.fill_rect(circle_rect, self.style.border_color);
if self.selected {
let inner = Rect {
x: circle_rect.x + 3,
y: circle_rect.y + 3,
width: circle_rect.width - 6,
height: circle_rect.height - 6,
};
renderer.fill_rect(inner, self.dot_color);
}
let text_pos = (self.bounds.x + size + 4, self.bounds.y + self.bounds.height);
renderer.draw_text(text_pos, &self.text, self.text_color);
}
fn handle_event(&mut self, event: &Event) -> bool {
if let Event::PointerUp { x, y } = event {
let inside = *x >= self.bounds.x
&& *x < self.bounds.x + self.bounds.width
&& *y >= self.bounds.y
&& *y < self.bounds.y + self.bounds.height;
if inside {
self.selected = !self.selected;
return true;
}
}
false
}
}
#[cfg(test)]
mod tests {
use super::*;
use rlvgl_core::{event::Event, widget::Widget};
#[test]
fn radio_toggle_and_bounds() {
let rect = Rect {
x: 0,
y: 0,
width: 20,
height: 20,
};
let mut radio = Radio::new("A", rect);
assert_eq!(radio.bounds().x, rect.x);
assert_eq!(radio.bounds().y, rect.y);
let evt = Event::PointerUp { x: 5, y: 5 };
assert!(radio.handle_event(&evt));
assert!(radio.is_selected());
}
}