1use rlvgl_core::draw::{draw_widget_bg, fill_rounded_rect};
4use rlvgl_core::event::Event;
5use rlvgl_core::renderer::Renderer;
6use rlvgl_core::style::Style;
7use rlvgl_core::widget::{Color, Rect, Widget};
8
9pub struct Switch {
11 bounds: Rect,
12 pub style: Style,
14 pub knob_color: Color,
16 on: bool,
17}
18
19impl Switch {
20 pub fn new(bounds: Rect) -> Self {
22 Self {
23 bounds,
24 style: Style::default(),
25 knob_color: Color(0, 0, 0, 255),
26 on: false,
27 }
28 }
29
30 pub fn is_on(&self) -> bool {
32 self.on
33 }
34
35 pub fn set_on(&mut self, value: bool) {
37 self.on = value;
38 }
39}
40
41impl Widget for Switch {
42 fn bounds(&self) -> Rect {
43 self.bounds
44 }
45
46 fn draw(&self, renderer: &mut dyn Renderer) {
47 let a = self.style.alpha;
48 let r = self.style.radius;
49 draw_widget_bg(renderer, self.bounds, &self.style);
51
52 let knob_width = self.bounds.width / 2;
54 let knob_rect = if self.on {
55 Rect {
56 x: self.bounds.x + self.bounds.width - knob_width,
57 y: self.bounds.y,
58 width: knob_width,
59 height: self.bounds.height,
60 }
61 } else {
62 Rect {
63 x: self.bounds.x,
64 y: self.bounds.y,
65 width: knob_width,
66 height: self.bounds.height,
67 }
68 };
69 fill_rounded_rect(renderer, knob_rect, self.knob_color.with_alpha(a), r);
70 }
71
72 fn handle_event(&mut self, event: &Event) -> bool {
73 if let Event::PressRelease { x, y } = event {
74 let inside = *x >= self.bounds.x
75 && *x < self.bounds.x + self.bounds.width
76 && *y >= self.bounds.y
77 && *y < self.bounds.y + self.bounds.height;
78 if inside {
79 self.on = !self.on;
80 return true;
81 }
82 }
83 false
84 }
85}
86
87#[cfg(test)]
88mod tests {
89 use super::*;
90 use rlvgl_core::{event::Event, widget::Widget};
91
92 #[test]
93 fn switch_toggle_and_bounds() {
94 let rect = Rect {
95 x: 0,
96 y: 0,
97 width: 40,
98 height: 20,
99 };
100 let mut sw = Switch::new(rect);
101 assert_eq!(sw.bounds().x, rect.x);
102 assert_eq!(sw.bounds().y, rect.y);
103 assert_eq!(sw.bounds().width, rect.width);
104 assert_eq!(sw.bounds().height, rect.height);
105 let evt = Event::PressRelease { x: 5, y: 5 };
106 assert!(sw.handle_event(&evt));
107 assert!(sw.is_on());
108 }
109}