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(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    /// Returns the [`Kind`] of [`Click`].
65    pub fn kind(&self) -> Kind {
66        self.kind
67    }
68
69    /// Returns the position of the [`Click`].
70    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}