iced_core/mouse/
click.rs

1//! Track mouse clicks.
2use crate::mouse::Button;
3use crate::time::Instant;
4use crate::Point;
5
6/// A mouse click.
7#[derive(Debug, Clone, Copy)]
8pub struct Click {
9    kind: Kind,
10    button: Button,
11    position: Point,
12    time: Instant,
13}
14
15/// The kind of mouse click.
16#[derive(Debug, Clone, Copy)]
17pub enum Kind {
18    /// A single click
19    Single,
20
21    /// A double click
22    Double,
23
24    /// A triple click
25    Triple,
26}
27
28impl Kind {
29    fn next(self) -> Kind {
30        match self {
31            Kind::Single => Kind::Double,
32            Kind::Double => Kind::Triple,
33            Kind::Triple => Kind::Double,
34        }
35    }
36}
37
38impl Click {
39    /// Creates a new [`Click`] with the given position and previous last
40    /// [`Click`].
41    pub fn new(
42        position: Point,
43        button: Button,
44        previous: Option<Click>,
45    ) -> Click {
46        let time = Instant::now();
47
48        let kind = if let Some(previous) = previous {
49            if previous.is_consecutive(position, time)
50                && button == previous.button
51            {
52                previous.kind.next()
53            } else {
54                Kind::Single
55            }
56        } else {
57            Kind::Single
58        };
59
60        Click {
61            kind,
62            button,
63            position,
64            time,
65        }
66    }
67
68    /// Returns the [`Kind`] of [`Click`].
69    pub fn kind(&self) -> Kind {
70        self.kind
71    }
72
73    /// Returns the position of the [`Click`].
74    pub fn position(&self) -> Point {
75        self.position
76    }
77
78    fn is_consecutive(&self, new_position: Point, time: Instant) -> bool {
79        let duration = if time > self.time {
80            Some(time - self.time)
81        } else {
82            None
83        };
84        self.position.distance(new_position) < 6.0
85            && duration
86                .map(|duration| duration.as_millis() <= 300)
87                .unwrap_or(false)
88    }
89}