cranpose-foundation 0.1.164

Modifiers, nodes, and foundation elements for Cranpose
Documentation
use cranpose_ui_graphics::Point;

use crate::{
    gesture_constants::DRAG_THRESHOLD,
    nodes::input::{PointerEvent, PointerEventKind, PointerId},
};

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum TapGestureEvent {
    None,
    Pressed(Point),
    Tapped(Point),
    Canceled,
}

#[derive(Default, Debug, Clone, Copy, PartialEq)]
pub struct TapGesture {
    pointer_id: Option<PointerId>,
    down_position: Point,
    canceled_by_drag: bool,
}

impl TapGesture {
    pub fn new() -> Self {
        Self::default()
    }

    pub fn handle_event(&mut self, event: &PointerEvent) -> TapGestureEvent {
        match event.kind {
            PointerEventKind::Down if !event.is_consumed() => {
                self.pointer_id = Some(event.id);
                self.down_position = event.travelled_to();
                self.canceled_by_drag = false;
                TapGestureEvent::Pressed(event.position)
            }
            PointerEventKind::Move if self.pointer_id == Some(event.id) => {
                if !self.canceled_by_drag
                    && distance(self.down_position, event.travelled_to()) > DRAG_THRESHOLD
                {
                    self.canceled_by_drag = true;
                    TapGestureEvent::Canceled
                } else {
                    TapGestureEvent::None
                }
            }
            PointerEventKind::Up if self.pointer_id == Some(event.id) => {
                let tapped = !self.canceled_by_drag && !event.is_consumed();
                let position = event.position;
                self.reset();
                if tapped {
                    TapGestureEvent::Tapped(position)
                } else {
                    TapGestureEvent::Canceled
                }
            }
            PointerEventKind::Cancel if self.pointer_id == Some(event.id) => {
                self.reset();
                TapGestureEvent::Canceled
            }
            _ => TapGestureEvent::None,
        }
    }

    pub fn reset(&mut self) {
        self.pointer_id = None;
        self.down_position = Point { x: 0.0, y: 0.0 };
        self.canceled_by_drag = false;
    }
}

fn distance(a: Point, b: Point) -> f32 {
    let dx = b.x - a.x;
    let dy = b.y - a.y;
    (dx * dx + dy * dy).sqrt()
}

#[cfg(test)]
#[path = "tests/tap_tests.rs"]
mod tests;