use core::time::Duration;
use crate::primitives::Point;
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum Event {
Touch(embedded_touch::Touch),
Scroll(Point),
External,
Exit,
}
impl Event {
#[must_use]
pub fn offset(&self, offset: Point) -> Self {
let mut event = self.clone();
match &mut event {
Self::Touch(touch) => {
touch.location += offset.into();
}
Self::Scroll(_) | Self::External | Self::Exit => {}
}
event
}
}
#[derive(Debug, Default, Clone, PartialEq, Eq)]
pub struct EventResult {
pub handled: bool,
pub recompute_view: bool,
}
impl EventResult {
#[must_use]
pub const fn new(handled: bool, recompute_view: bool) -> Self {
Self {
handled,
recompute_view,
}
}
#[expect(clippy::needless_pass_by_value)]
pub fn merge(&mut self, other: Self) {
self.handled |= other.handled;
self.recompute_view |= other.recompute_view;
}
#[must_use]
#[expect(clippy::needless_pass_by_value)]
pub fn merging(self, other: Self) -> Self {
Self {
handled: self.handled || other.handled,
recompute_view: self.recompute_view || other.recompute_view,
}
}
}
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct EventContext {
pub app_time: Duration,
}
impl EventContext {
#[must_use]
pub const fn new(app_time: Duration) -> Self {
Self { app_time }
}
}
#[cfg(feature = "embedded-graphics-simulator")]
pub mod simulator {
use crate::primitives::Point;
use super::Event;
use embedded_graphics_simulator::SimulatorEvent;
use embedded_touch::{Phase, PointerButton, Tool, Touch, TouchPoint};
#[derive(Debug, Default)]
pub struct MouseTracker {
touch: Option<Touch>,
}
impl MouseTracker {
#[must_use]
pub fn new() -> Self {
Self { touch: None }
}
pub fn process_event(&mut self, event: SimulatorEvent) -> Option<Event> {
match event {
SimulatorEvent::MouseButtonDown { point, mouse_btn } => {
let touch = Touch {
id: 0,
location: TouchPoint::new(point.x, point.y),
phase: Phase::Started,
tool: Tool::Pointer {
button: map_button(mouse_btn),
},
};
self.touch = Some(touch.clone());
Some(Event::Touch(touch))
}
SimulatorEvent::MouseButtonUp { point, mouse_btn } => {
let touch = Touch {
id: 0,
location: TouchPoint::new(point.x, point.y),
phase: Phase::Ended,
tool: Tool::Pointer {
button: map_button(mouse_btn),
},
};
self.touch = None;
Some(Event::Touch(touch))
}
SimulatorEvent::MouseMove { point } => {
if let Some(touch) = &mut self.touch {
touch.location = TouchPoint::new(point.x, point.y);
touch.phase = Phase::Moved;
Some(Event::Touch(touch.clone()))
} else {
let touch = Touch {
id: 0,
location: TouchPoint::new(point.x, point.y),
phase: Phase::Hovering(None),
tool: Tool::Pointer {
button: PointerButton::None,
},
};
Some(Event::Touch(touch))
}
}
SimulatorEvent::MouseWheel {
scroll_delta,
direction,
} => {
if direction == embedded_graphics_simulator::sdl2::MouseWheelDirection::Flipped
{
Some(Event::Scroll(Point::new(
scroll_delta.x * 4,
scroll_delta.y * 4,
)))
} else {
Some(Event::Scroll(Point::new(
-scroll_delta.x * 4,
-scroll_delta.y * 4,
)))
}
}
SimulatorEvent::Quit => Some(Event::Exit),
SimulatorEvent::KeyDown { .. } | SimulatorEvent::KeyUp { .. } => None,
}
}
}
fn map_button(mouse_btn: embedded_graphics_simulator::sdl2::MouseButton) -> PointerButton {
match mouse_btn {
embedded_graphics_simulator::sdl2::MouseButton::Left => PointerButton::Primary,
embedded_graphics_simulator::sdl2::MouseButton::Right => PointerButton::Secondary,
embedded_graphics_simulator::sdl2::MouseButton::Middle => PointerButton::Tertiary,
_ => PointerButton::None,
}
}
}