1use crate::mouse::Button;
3use crate::time::Instant;
4use crate::{Point, Transformation};
5
6use std::ops::Mul;
7
8#[derive(Debug, Clone, Copy)]
10pub struct Click {
11 kind: Kind,
12 button: Button,
13 position: Point,
14 time: Instant,
15}
16
17#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum Kind {
20 Single,
22
23 Double,
25
26 Triple,
28}
29
30impl Kind {
31 fn next(self) -> Kind {
32 match self {
33 Kind::Single => Kind::Double,
34 Kind::Double => Kind::Triple,
35 Kind::Triple => Kind::Double,
36 }
37 }
38}
39
40impl Click {
41 pub fn new(position: Point, button: Button, previous: Option<Click>) -> Click {
44 let time = Instant::now();
45
46 let kind = if let Some(previous) = previous {
47 if previous.is_consecutive(position, time) && button == previous.button {
48 previous.kind.next()
49 } else {
50 Kind::Single
51 }
52 } else {
53 Kind::Single
54 };
55
56 Click {
57 kind,
58 button,
59 position,
60 time,
61 }
62 }
63
64 pub fn kind(&self) -> Kind {
66 self.kind
67 }
68
69 pub fn position(&self) -> Point {
71 self.position
72 }
73
74 fn is_consecutive(&self, new_position: Point, time: Instant) -> bool {
75 let duration = if time > self.time {
76 Some(time - self.time)
77 } else {
78 None
79 };
80
81 self.position.distance(new_position) < 6.0
82 && duration
83 .map(|duration| duration.as_millis() <= 300)
84 .unwrap_or(false)
85 }
86}
87
88impl Mul<Transformation> for Click {
89 type Output = Click;
90
91 fn mul(self, transformation: Transformation) -> Click {
92 Click {
93 kind: self.kind,
94 button: self.button,
95 position: self.position * transformation,
96 time: self.time,
97 }
98 }
99}