use crate::core::Point;
use crate::event::Event;
use super::{
DoubleTapGesture, FlingGesture, LongPressDragGesture, LongPressGesture, PanGesture,
PinchGesture, RotateGesture, SwipeGesture, TapGesture, TwoFingerSwipeGesture,
TwoFingerTapGesture,
};
pub(crate) const DOUBLE_TAP_TIMEOUT_MS: u64 = 400;
pub(crate) const LONG_PRESS_MIN_MS: u64 = 500;
pub(crate) const SWIPE_MIN_VELOCITY: f32 = 0.5;
pub(crate) const MAX_STATIONARY_DISTANCE: f32 = 15.0;
pub(crate) const LONG_PRESS_MAX_MOVE: f32 = 10.0;
pub(crate) const SWIPE_MIN_DISTANCE: f32 = 30.0;
pub(crate) const TAP_TIMEOUT_MS: u64 = 300;
pub trait GestureRecognizer: std::fmt::Debug + Send {
fn process(&mut self, event: &Event, now_ms: u64) -> Option<Event>;
fn reset(&mut self);
}
#[derive(Debug)]
pub struct GestureEngine {
recognizers: Vec<Box<dyn GestureRecognizer>>,
last_timestamp_ms: u64,
}
impl GestureEngine {
pub fn new() -> Self {
let recognizers: Vec<Box<dyn GestureRecognizer>> = vec![
Box::new(TapGesture::new()),
Box::new(DoubleTapGesture::new()),
Box::new(LongPressGesture::new()),
Box::new(LongPressDragGesture::new()),
Box::new(PanGesture::new()),
Box::new(SwipeGesture::new()),
Box::new(FlingGesture::new()),
Box::new(TwoFingerTapGesture::new()),
Box::new(TwoFingerSwipeGesture::new()),
Box::new(PinchGesture::new()),
Box::new(RotateGesture::new()),
];
Self { recognizers, last_timestamp_ms: 0 }
}
pub fn process(&mut self, event: &Event, now_ms: u64) -> Option<Event> {
self.last_timestamp_ms = now_ms;
for r in &mut self.recognizers {
if let Some(gesture_event) = r.process(event, now_ms) {
return Some(gesture_event);
}
}
None
}
pub fn reset_all(&mut self) {
for r in &mut self.recognizers {
r.reset();
}
}
}
impl Default for GestureEngine {
fn default() -> Self {
Self::new()
}
}
pub(crate) fn distance(a: Point, b: Point) -> f32 {
let dx = (a.x - b.x) as f32;
let dy = (a.y - b.y) as f32;
(dx * dx + dy * dy).sqrt()
}
#[cfg(test)]
mod tests {
use super::*;
use crate::event::Event;
#[test]
fn gesture_engine_new() {
let engine = GestureEngine::new();
assert_eq!(engine.recognizers.len(), 11);
}
#[test]
fn gesture_engine_process_none_for_unrelated_event() {
let mut engine = GestureEngine::new();
let result =
engine.process(&Event::MousePress { pos: crate::core::Point::new(0, 0), button: 0 }, 0);
assert!(result.is_none());
}
#[test]
fn gesture_engine_reset_all_clears_state() {
let mut engine = GestureEngine::new();
engine.reset_all();
assert_eq!(engine.recognizers.len(), 11);
}
}