use std::rc::Rc;
use crate::{
prelude::*,
proc_macros::{Event, IntoHandler},
shell::MouseButton,
utils::*,
};
pub fn check_mouse_condition(mouse_position: Point, widget: &WidgetContainer<'_>) -> bool {
let enabled = widget.get::<bool>("enabled");
if !enabled {
return false;
}
let bounds = widget.get::<Rectangle>("bounds");
let position = widget.get::<Point>("position");
let mut rect = Rectangle::new((0.0, 0.0), (bounds.width(), bounds.height()));
rect.set_x(position.x());
rect.set_y(position.y());
rect.contains(mouse_position)
}
#[derive(Event)]
pub struct MouseMoveEvent {
pub position: Point,
}
#[derive(Event)]
pub struct ScrollEvent {
pub delta: Point,
}
#[derive(Debug, Copy, Clone)]
pub struct Mouse {
pub button: MouseButton,
pub position: Point,
}
#[derive(Event)]
pub struct MouseUpEvent {
pub button: MouseButton,
pub position: Point,
}
#[derive(Event)]
pub struct ClickEvent {
pub position: Point,
}
#[derive(Event)]
pub struct MouseDownEvent {
pub button: MouseButton,
pub position: Point,
}
#[derive(Event)]
pub struct GlobalMouseUpEvent {
pub button: MouseButton,
pub position: Point,
}
pub type MouseHandlerFunction = dyn Fn(&mut StatesContext, Mouse) -> bool + 'static;
pub type PositionHandlerFunction = dyn Fn(&mut StatesContext, Point) -> bool + 'static;
pub type GlobalMouseHandlerFunction = dyn Fn(&mut StatesContext, Mouse) + 'static;
pub struct ClickEventHandler {
handler: Rc<PositionHandlerFunction>,
}
impl Into<Rc<dyn EventHandler>> for ClickEventHandler {
fn into(self) -> Rc<dyn EventHandler> {
Rc::new(self)
}
}
impl EventHandler for ClickEventHandler {
fn handle_event(&self, state_context: &mut StatesContext, event: &EventBox) -> bool {
event
.downcast_ref::<ClickEvent>()
.ok()
.map_or(false, |event| (self.handler)(state_context, event.position))
}
fn handles_event(&self, event: &EventBox) -> bool {
event.is_type::<ClickEvent>()
}
}
#[derive(IntoHandler)]
pub struct MouseDownEventHandler {
handler: Rc<MouseHandlerFunction>,
}
impl EventHandler for MouseDownEventHandler {
fn handle_event(&self, state_context: &mut StatesContext, event: &EventBox) -> bool {
event
.downcast_ref::<MouseDownEvent>()
.ok()
.map_or(false, |event| {
(self.handler)(
state_context,
Mouse {
button: event.button,
position: event.position,
},
)
})
}
fn handles_event(&self, event: &EventBox) -> bool {
event.is_type::<MouseDownEvent>()
}
}
#[derive(IntoHandler)]
pub struct GlobalMouseUpEventHandler {
handler: Rc<GlobalMouseHandlerFunction>,
}
impl EventHandler for GlobalMouseUpEventHandler {
fn handle_event(&self, state_context: &mut StatesContext, event: &EventBox) -> bool {
event
.downcast_ref::<GlobalMouseUpEvent>()
.ok()
.map_or(false, |event| {
(self.handler)(
state_context,
Mouse {
button: event.button,
position: event.position,
},
);
false
})
}
fn handles_event(&self, event: &EventBox) -> bool {
event.is_type::<GlobalMouseUpEvent>()
}
}
#[derive(IntoHandler)]
pub struct MouseUpEventHandler {
handler: Rc<MouseHandlerFunction>,
}
impl EventHandler for MouseUpEventHandler {
fn handle_event(&self, state_context: &mut StatesContext, event: &EventBox) -> bool {
event
.downcast_ref::<MouseUpEvent>()
.ok()
.map_or(false, |event| {
(self.handler)(
state_context,
Mouse {
button: event.button,
position: event.position,
},
)
})
}
fn handles_event(&self, event: &EventBox) -> bool {
event.is_type::<MouseUpEvent>()
}
}
#[derive(IntoHandler)]
pub struct MouseMoveEventHandler {
handler: Rc<PositionHandlerFunction>,
}
impl EventHandler for MouseMoveEventHandler {
fn handle_event(&self, state_context: &mut StatesContext, event: &EventBox) -> bool {
event
.downcast_ref::<MouseMoveEvent>()
.ok()
.map_or(false, |event| (self.handler)(state_context, event.position))
}
fn handles_event(&self, event: &EventBox) -> bool {
event.is_type::<MouseMoveEvent>()
}
}
#[derive(IntoHandler)]
pub struct ScrollEventHandler {
handler: Rc<PositionHandlerFunction>,
}
impl EventHandler for ScrollEventHandler {
fn handle_event(&self, state_context: &mut StatesContext, event: &EventBox) -> bool {
event
.downcast_ref::<ScrollEvent>()
.ok()
.map_or(false, |event| (self.handler)(state_context, event.delta))
}
fn handles_event(&self, event: &EventBox) -> bool {
event.is_type::<ScrollEvent>()
}
}
pub trait MouseHandler: Sized + Widget {
fn on_click<H: Fn(&mut StatesContext, Point) -> bool + 'static>(self, handler: H) -> Self {
self.insert_handler(ClickEventHandler {
handler: Rc::new(handler),
})
}
fn on_mouse_down<H: Fn(&mut StatesContext, Mouse) -> bool + 'static>(self, handler: H) -> Self {
self.insert_handler(MouseDownEventHandler {
handler: Rc::new(handler),
})
}
fn on_mouse_up<H: Fn(&mut StatesContext, Mouse) -> bool + 'static>(self, handler: H) -> Self {
self.insert_handler(MouseUpEventHandler {
handler: Rc::new(handler),
})
}
fn on_global_mouse_up<H: Fn(&mut StatesContext, Mouse) + 'static>(self, handler: H) -> Self {
self.insert_handler(GlobalMouseUpEventHandler {
handler: Rc::new(handler),
})
}
fn on_mouse_move<H: Fn(&mut StatesContext, Point) -> bool + 'static>(self, handler: H) -> Self {
self.insert_handler(MouseMoveEventHandler {
handler: Rc::new(handler),
})
}
fn on_scroll<H: Fn(&mut StatesContext, Point) -> bool + 'static>(self, handler: H) -> Self {
self.insert_handler(ScrollEventHandler {
handler: Rc::new(handler),
})
}
}