iced_core/mouse/
click.rs

1//! Track mouse clicks.
2use crate::mouse::Button;
3use crate::time::Instant;
4use crate::{Point, Transformation};
5
6use std::ops::Mul;
7
8/// A mouse click.
9#[derive(Debug, Clone, Copy)]
10pub struct Click {
11    kind: Kind,
12    button: Button,
13    position: Point,
14    time: Instant,
15}
16
17/// The kind of mouse click.
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub enum Kind {
20    /// A single click
21    Single,
22
23    /// A double click
24    Double,
25
26    /// A triple click
27    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    /// Creates a new [`Click`] with the given position and previous last
42    /// [`Click`].
43    pub fn new(
44        position: Point,
45        button: Button,
46        previous: Option<Click>,
47    ) -> Click {
48        let time = Instant::now();
49
50        let kind = if let Some(previous) = previous {
51            if previous.is_consecutive(position, time)
52                && button == previous.button
53            {
54                previous.kind.next()
55            } else {
56                Kind::Single
57            }
58        } else {
59            Kind::Single
60        };
61
62        Click {
63            kind,
64            button,
65            position,
66            time,
67        }
68    }
69
70    /// Returns the [`Kind`] of [`Click`].
71    pub fn kind(&self) -> Kind {
72        self.kind
73    }
74
75    /// Returns the position of the [`Click`].
76    pub fn position(&self) -> Point {
77        self.position
78    }
79
80    fn is_consecutive(&self, new_position: Point, time: Instant) -> bool {
81        let duration = if time > self.time {
82            Some(time - self.time)
83        } else {
84            None
85        };
86
87        self.position.distance(new_position) < 6.0
88            && duration
89                .map(|duration| duration.as_millis() <= 300)
90                .unwrap_or(false)
91    }
92}
93
94impl Mul<Transformation> for Click {
95    type Output = Click;
96
97    fn mul(self, transformation: Transformation) -> Click {
98        Click {
99            kind: self.kind,
100            button: self.button,
101            position: self.position * transformation,
102            time: self.time,
103        }
104    }
105}