Files
wayvr/wgui/src/event.rs
2025-06-18 01:14:04 +09:00

109 lines
2.5 KiB
Rust

use glam::Vec2;
use crate::{
animation,
layout::{WidgetID, WidgetMap},
transform_stack::Transform,
widget::{WidgetData, WidgetObj},
};
// TODO: mouse index
pub struct MouseDownEvent {
pub pos: Vec2,
}
pub struct MouseMotionEvent {
pub pos: Vec2,
}
pub struct MouseUpEvent {
pub pos: Vec2,
}
pub struct MouseWheelEvent {
pub pos: Vec2,
pub shift: Vec2,
}
pub enum Event {
MouseDown(MouseDownEvent),
MouseMotion(MouseMotionEvent),
MouseUp(MouseUpEvent),
MouseWheel(MouseWheelEvent),
}
impl Event {
fn test_transform_pos(&self, transform: &Transform, pos: &Vec2) -> bool {
pos.x >= transform.pos.x
&& pos.x < transform.pos.x + transform.dim.x
&& pos.y >= transform.pos.y
&& pos.y < transform.pos.y + transform.dim.y
}
pub fn test_mouse_within_transform(&self, transform: &Transform) -> bool {
match self {
Event::MouseDown(evt) => self.test_transform_pos(transform, &evt.pos),
Event::MouseMotion(evt) => self.test_transform_pos(transform, &evt.pos),
Event::MouseUp(evt) => self.test_transform_pos(transform, &evt.pos),
Event::MouseWheel(evt) => self.test_transform_pos(transform, &evt.pos),
}
}
}
pub trait WidgetCallback<'a> {
fn call_on_widget<WIDGET, FUNC>(&self, widget_id: WidgetID, func: FUNC)
where
WIDGET: WidgetObj,
FUNC: FnOnce(&mut WIDGET),
{
let Some(widget) = self.get_widgets().get(widget_id) else {
debug_assert!(false);
return;
};
let mut lock = widget.lock().unwrap();
let m = lock.obj.get_as_mut::<WIDGET>();
func(m);
}
fn get_widgets(&self) -> &'a WidgetMap;
fn mark_redraw(&mut self);
fn mark_dirty(&mut self, node_id: taffy::NodeId);
}
pub struct CallbackData<'a> {
pub obj: &'a mut dyn WidgetObj,
pub widget_data: &'a mut WidgetData,
pub animations: &'a mut Vec<animation::Animation>,
pub widgets: &'a WidgetMap,
pub widget_id: WidgetID,
pub node_id: taffy::NodeId,
pub dirty_nodes: &'a mut Vec<taffy::NodeId>,
pub needs_redraw: bool,
}
impl<'a> WidgetCallback<'a> for CallbackData<'a> {
fn get_widgets(&self) -> &'a WidgetMap {
self.widgets
}
fn mark_redraw(&mut self) {
self.needs_redraw = true;
}
fn mark_dirty(&mut self, node_id: taffy::NodeId) {
self.dirty_nodes.push(node_id);
}
}
pub type MouseEnterCallback = Box<dyn Fn(&mut CallbackData)>;
pub type MouseLeaveCallback = Box<dyn Fn(&mut CallbackData)>;
pub type MouseClickCallback = Box<dyn Fn(&mut CallbackData)>;
pub enum EventListener {
MouseEnter(MouseEnterCallback),
MouseLeave(MouseLeaveCallback),
MouseClick(MouseClickCallback),
}