1use alloc::boxed::Box;
8use rlvgl_core::{
9 event::Event,
10 renderer::Renderer,
11 widget::{Rect, Widget},
12};
13use rlvgl_widgets::{button::Button as BaseButton, slider::Slider as BaseSlider};
14
15pub trait OnClick {
17 fn on_click<F: FnMut(&mut Self) + 'static>(self, handler: F) -> Self;
19}
20
21impl OnClick for BaseButton {
22 fn on_click<F: FnMut(&mut Self) + 'static>(mut self, handler: F) -> Self {
23 self.set_on_click(handler);
24 self
25 }
26}
27
28pub struct Slider {
30 inner: BaseSlider,
31 on_change: Option<Box<dyn FnMut(i32)>>,
32}
33
34impl Slider {
35 pub fn new(bounds: Rect, min: i32, max: i32) -> Self {
37 let inner = BaseSlider::new(bounds, min, max);
38 Self {
39 inner,
40 on_change: None,
41 }
42 }
43
44 pub fn on_change<F: FnMut(i32) + 'static>(mut self, handler: F) -> Self {
46 self.on_change = Some(Box::new(handler));
47 self
48 }
49
50 pub fn value(&self) -> i32 {
52 self.inner.value()
53 }
54
55 pub fn set_value(&mut self, val: i32) {
57 self.inner.set_value(val);
58 }
59
60 pub fn style(&self) -> &rlvgl_core::style::Style {
62 &self.inner.style
63 }
64
65 pub fn style_mut(&mut self) -> &mut rlvgl_core::style::Style {
67 &mut self.inner.style
68 }
69}
70
71impl Widget for Slider {
72 fn bounds(&self) -> Rect {
73 self.inner.bounds()
74 }
75
76 fn draw(&self, renderer: &mut dyn Renderer) {
77 self.inner.draw(renderer);
78 }
79
80 fn handle_event(&mut self, event: &Event) -> bool {
81 let before = self.inner.value();
82 let handled = self.inner.handle_event(event);
83 let after = self.inner.value();
84 if !handled || after == before {
85 return handled;
86 }
87 if let Some(cb) = self.on_change.as_mut() {
88 cb(after);
89 }
90 handled
91 }
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97 use alloc::rc::Rc;
98 use core::cell::Cell;
99 use rlvgl_core::{event::Event, widget::Rect};
100 use rlvgl_widgets::button::Button;
101
102 #[test]
103 fn button_on_click_executes() {
104 let bounds = Rect {
105 x: 0,
106 y: 0,
107 width: 20,
108 height: 20,
109 };
110 let clicked = Rc::new(Cell::new(false));
111 let c = clicked.clone();
112 let mut btn = Button::new("ok", bounds).on_click(move |_| c.set(true));
113 let event = Event::PressRelease { x: 5, y: 5 };
114 btn.handle_event(&event);
115 assert!(clicked.get());
116 }
117
118 #[test]
119 fn slider_on_change_executes() {
120 let bounds = Rect {
121 x: 0,
122 y: 0,
123 width: 100,
124 height: 10,
125 };
126 let value = Rc::new(Cell::new(0));
127 let v = value.clone();
128 let mut slider = Slider::new(bounds, 0, 10).on_change(move |x| v.set(x));
129 let event = Event::PressRelease { x: 50, y: 5 };
130 slider.handle_event(&event);
131 assert_ne!(value.get(), 0);
132 }
133}