use std::time::Instant;
use teksilo_canvas::{Point, Vec2};
use crate::event::{Modifiers, PointerButton};
mod arena;
mod drag;
mod long_press;
mod multi_tap;
mod swipe;
mod tap;
pub use arena::GestureArena;
pub use drag::DragRecognizer;
pub use long_press::LongPressRecognizer;
pub use multi_tap::{DoubleTapRecognizer, TripleTapRecognizer};
pub use swipe::SwipeRecognizer;
pub use tap::TapRecognizer;
#[derive(Debug, Clone, Copy)]
#[non_exhaustive]
pub struct TapEvent {
pub position: Point,
pub button: PointerButton,
pub modifiers: Modifiers,
}
impl TapEvent {
pub fn new(position: Point, button: PointerButton, modifiers: Modifiers) -> Self {
Self {
position,
button,
modifiers,
}
}
}
#[derive(Debug, Clone, Copy)]
pub enum RawPointerEvent {
Down {
position: Point,
button: PointerButton,
modifiers: Modifiers,
},
Move {
position: Point,
},
Up {
position: Point,
button: PointerButton,
modifiers: Modifiers,
},
}
#[derive(Debug, Clone)]
pub enum GestureResult {
Pending,
Recognized(GestureEvent),
Failed,
}
#[derive(Debug, Clone, Copy)]
pub enum GestureEvent {
Tap(TapEvent),
DoubleTap(TapEvent),
TripleTap(TapEvent),
LongPress(TapEvent),
DragStarted {
position: Point,
button: PointerButton,
},
DragMoved {
position: Point,
delta: Vec2,
},
DragEnded {
position: Point,
},
PinchStarted {
center: Point,
},
PinchChanged {
center: Point,
scale: f32,
rotation: f32,
},
PinchEnded,
Swipe {
direction: SwipeDirection,
velocity: f32,
},
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SwipeDirection {
Left,
Right,
Up,
Down,
}
#[derive(Debug, Clone, Copy)]
pub enum DragPhase {
Started {
position: Point,
button: PointerButton,
},
Moved {
position: Point,
delta: Vec2,
},
Ended {
position: Point,
},
}
#[derive(Debug, Clone, Copy)]
pub enum PinchPhase {
Started {
center: Point,
},
Changed {
center: Point,
scale: f32,
rotation: f32,
},
Ended,
}
pub trait GestureRecognizer {
fn process(&mut self, event: &RawPointerEvent) -> GestureResult;
fn reset(&mut self);
fn priority(&self) -> u32;
fn tick(&mut self, _now: Instant) -> GestureResult {
GestureResult::Pending
}
fn next_deadline(&self) -> Option<Instant> {
None
}
fn resets_on_peer_recognition(&self) -> bool {
true
}
}
pub(crate) fn distance(a: Point, b: Point) -> f32 {
let dx = a.x - b.x;
let dy = a.y - b.y;
(dx * dx + dy * dy).sqrt()
}
#[cfg(test)]
pub(crate) mod test_helpers {
use super::{Modifiers, Point, PointerButton, RawPointerEvent};
pub fn down(pos: Point) -> RawPointerEvent {
down_btn(pos, PointerButton::Primary)
}
pub fn down_btn(pos: Point, button: PointerButton) -> RawPointerEvent {
down_full(pos, button, Modifiers::NONE)
}
pub fn down_full(pos: Point, button: PointerButton, modifiers: Modifiers) -> RawPointerEvent {
RawPointerEvent::Down {
position: pos,
button,
modifiers,
}
}
pub fn up(pos: Point) -> RawPointerEvent {
up_btn(pos, PointerButton::Primary)
}
pub fn up_btn(pos: Point, button: PointerButton) -> RawPointerEvent {
up_full(pos, button, Modifiers::NONE)
}
pub fn up_full(pos: Point, button: PointerButton, modifiers: Modifiers) -> RawPointerEvent {
RawPointerEvent::Up {
position: pos,
button,
modifiers,
}
}
pub fn move_to(pos: Point) -> RawPointerEvent {
RawPointerEvent::Move { position: pos }
}
}