rlvgl_widgets/click_area.rs
1//! Transparent click-area widget used as the rlvgl-side analogue of
2//! QML's `MouseArea`. Renders nothing; reports clicks through an
3//! optional callback the caller registers with [`Self::set_on_click`].
4
5use alloc::boxed::Box;
6
7use rlvgl_core::event::Event;
8use rlvgl_core::renderer::Renderer;
9use rlvgl_core::widget::{Rect, Widget};
10
11type ClickHandler = Box<dyn FnMut(&mut ClickArea)>;
12
13/// Transparent rectangular hit area with an optional click callback.
14///
15/// Designed for the QML `MouseArea` lowering shipped by phase QT-04d
16/// (`docs/qt-support/04d-mousearea.md`). The widget intentionally
17/// has no visual: its [`Widget::draw`] is a no-op so the area never
18/// occludes its parent's pixels. Hit-testing happens on
19/// [`Event::PressRelease`].
20pub struct ClickArea {
21 bounds: Rect,
22 on_click: Option<ClickHandler>,
23}
24
25impl ClickArea {
26 /// Create a click area covering `bounds`.
27 pub fn new(bounds: Rect) -> Self {
28 Self {
29 bounds,
30 on_click: None,
31 }
32 }
33
34 /// Register a callback invoked when a click is released inside
35 /// `bounds`. The callback receives `&mut self` so it can mutate
36 /// the click area itself (e.g. resize after a click) — though
37 /// QT-04d's emitted closures typically only mutate `ScreenState`
38 /// captured by reference.
39 pub fn set_on_click<F: FnMut(&mut Self) + 'static>(&mut self, handler: F) {
40 self.on_click = Some(Box::new(handler));
41 }
42
43 fn inside_bounds(&self, x: i32, y: i32) -> bool {
44 let b = self.bounds;
45 x >= b.x && x < b.x + b.width && y >= b.y && y < b.y + b.height
46 }
47}
48
49impl Widget for ClickArea {
50 fn bounds(&self) -> Rect {
51 self.bounds
52 }
53
54 /// No-op — the click area is transparent.
55 fn draw(&self, _renderer: &mut dyn Renderer) {}
56
57 fn handle_event(&mut self, event: &Event) -> bool {
58 match event {
59 Event::PressRelease { x, y } if self.inside_bounds(*x, *y) => {
60 if let Some(mut cb) = self.on_click.take() {
61 cb(self);
62 self.on_click = Some(cb);
63 }
64 true
65 }
66 _ => false,
67 }
68 }
69}