use alloc::{boxed::Box, string::String};
use rlvgl_core::event::Event;
use rlvgl_core::renderer::Renderer;
use rlvgl_core::widget::{Rect, Widget};
use crate::label::Label;
use rlvgl_core::style::Style;
type ClickHandler = Box<dyn FnMut(&mut Button)>;
pub struct Button {
label: Label,
on_click: Option<ClickHandler>,
}
impl Button {
pub fn new(text: impl Into<String>, bounds: Rect) -> Self {
Self {
label: Label::new(text, bounds),
on_click: None,
}
}
pub fn style(&self) -> &Style {
&self.label.style
}
pub fn style_mut(&mut self) -> &mut Style {
&mut self.label.style
}
pub fn set_text(&mut self, text: impl Into<String>) {
self.label.set_text(text);
}
pub fn text(&self) -> &str {
self.label.text()
}
pub fn set_on_click<F: FnMut(&mut Self) + 'static>(&mut self, handler: F) {
self.on_click = Some(Box::new(handler));
}
fn inside_bounds(&self, x: i32, y: i32) -> bool {
let b = self.label.bounds();
x >= b.x && x < b.x + b.width && y >= b.y && y < b.y + b.height
}
}
impl Widget for Button {
fn bounds(&self) -> Rect {
self.label.bounds()
}
fn draw(&self, renderer: &mut dyn Renderer) {
self.label.draw(renderer);
}
fn handle_event(&mut self, event: &Event) -> bool {
match event {
Event::PointerUp { x, y } if self.inside_bounds(*x, *y) => {
if let Some(mut cb) = self.on_click.take() {
cb(self);
self.on_click = Some(cb);
}
return true;
}
_ => {}
}
false
}
}