use crate::{Event, Input, Motion};
#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
pub enum Touch {
Start,
Move,
End,
Cancel,
}
#[derive(Copy, Clone, Deserialize, Serialize, PartialEq, PartialOrd, Debug)]
pub struct TouchArgs {
pub device: i64,
pub id: i64,
pub position_3d: [f64; 3],
pub pressure_3d: [f64; 3],
pub is_3d: bool,
pub touch: Touch,
}
impl TouchArgs {
pub fn new(device: i64, id: i64, position: [f64; 2], pressure: f64, touch: Touch) -> TouchArgs {
TouchArgs {
device,
id,
position_3d: [position[0], position[1], 0.0],
pressure_3d: [0.0, 0.0, pressure],
is_3d: false,
touch,
}
}
pub fn new_3d(
device: i64,
id: i64,
position_3d: [f64; 3],
pressure_3d: [f64; 3],
touch: Touch,
) -> TouchArgs {
TouchArgs {
device,
id,
position_3d,
pressure_3d,
is_3d: true,
touch,
}
}
pub fn position(&self) -> [f64; 2] {
[self.position_3d[0], self.position_3d[1]]
}
pub fn position_3d(&self) -> [f64; 3] {
self.position_3d
}
pub fn pressure(&self) -> f64 {
let px = self.pressure_3d[0];
let py = self.pressure_3d[1];
let pz = self.pressure_3d[2];
(px * px + py * py + pz * pz).sqrt()
}
pub fn pressure_3d(&self) -> [f64; 3] {
self.pressure_3d
}
}
pub trait TouchEvent: Sized {
fn from_touch_args(args: &TouchArgs, old_event: &Self) -> Option<Self>;
fn touch<U, F>(&self, f: F) -> Option<U>
where
F: FnMut(&TouchArgs) -> U;
fn touch_args(&self) -> Option<TouchArgs> {
self.touch(|args| *args)
}
}
impl TouchEvent for Event {
fn from_touch_args(args: &TouchArgs, old_event: &Self) -> Option<Self> {
let timestamp = if let Event::Input(_, x) = old_event {
*x
} else {
None
};
Some(Event::Input(Input::Move(Motion::Touch(*args)), timestamp))
}
fn touch<U, F>(&self, mut f: F) -> Option<U>
where
F: FnMut(&TouchArgs) -> U,
{
match *self {
Event::Input(Input::Move(Motion::Touch(ref args)), _) => Some(f(args)),
_ => None,
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_input_touch() {
let pos = [0.0; 2];
let e: Event = TouchArgs::new(0, 0, pos, 1.0, Touch::Start).into();
let a: Option<Event> =
TouchEvent::from_touch_args(&TouchArgs::new(0, 0, pos, 1.0, Touch::Start), &e);
let b: Option<Event> = a
.clone()
.unwrap()
.touch(|t| {
TouchEvent::from_touch_args(
&TouchArgs::new(t.device, t.id, t.position(), t.pressure(), Touch::Start),
a.as_ref().unwrap(),
)
})
.unwrap();
assert_eq!(a, b);
}
#[test]
fn test_input_touch_3d() {
use super::super::Event;
let pos = [0.0; 3];
let pressure = [0.0, 0.0, 1.0];
let e: Event = TouchArgs::new_3d(0, 0, pos, pressure, Touch::Start).into();
let a: Option<Event> =
TouchEvent::from_touch_args(&TouchArgs::new_3d(0, 0, pos, pressure, Touch::Start), &e);
let b: Option<Event> = a
.clone()
.unwrap()
.touch(|t| {
TouchEvent::from_touch_args(
&TouchArgs::new_3d(
t.device,
t.id,
t.position_3d(),
t.pressure_3d(),
Touch::Start,
),
a.as_ref().unwrap(),
)
})
.unwrap();
assert_eq!(a, b);
}
}