iced_core/mouse/
cursor.rs

1use crate::{Point, Rectangle, Transformation, Vector};
2
3/// The mouse cursor state.
4#[derive(Debug, Clone, Copy, PartialEq, Default)]
5pub enum Cursor {
6    /// The cursor has a defined position.
7    Available(Point),
8
9    /// The cursor has a defined position, but it's levitating over a layer above.
10    Levitating(Point),
11
12    /// The cursor is currently unavailable (i.e. out of bounds or busy).
13    #[default]
14    Unavailable,
15}
16
17impl Cursor {
18    /// Returns the absolute position of the [`Cursor`], if available.
19    pub fn position(self) -> Option<Point> {
20        match self {
21            Cursor::Available(position) => Some(position),
22            Cursor::Levitating(_) | Cursor::Unavailable => None,
23        }
24    }
25
26    /// Returns the absolute position of the [`Cursor`], if available and inside
27    /// the given bounds.
28    ///
29    /// If the [`Cursor`] is not over the provided bounds, this method will
30    /// return `None`.
31    pub fn position_over(self, bounds: Rectangle) -> Option<Point> {
32        self.position().filter(|p| bounds.contains(*p))
33    }
34
35    /// Returns the relative position of the [`Cursor`] inside the given bounds,
36    /// if available.
37    ///
38    /// If the [`Cursor`] is not over the provided bounds, this method will
39    /// return `None`.
40    pub fn position_in(self, bounds: Rectangle) -> Option<Point> {
41        self.position_over(bounds)
42            .map(|p| p - Vector::new(bounds.x, bounds.y))
43    }
44
45    /// Returns the relative position of the [`Cursor`] from the given origin,
46    /// if available.
47    pub fn position_from(self, origin: Point) -> Option<Point> {
48        self.position().map(|p| p - Vector::new(origin.x, origin.y))
49    }
50
51    /// Returns true if the [`Cursor`] is over the given `bounds`.
52    pub fn is_over(self, bounds: Rectangle) -> bool {
53        self.position_over(bounds).is_some()
54    }
55
56    /// Returns true if the [`Cursor`] is levitating over a layer above.
57    pub fn is_levitating(self) -> bool {
58        matches!(self, Self::Levitating(_))
59    }
60
61    /// Makes the [`Cursor`] levitate over a layer above.
62    pub fn levitate(self) -> Self {
63        match self {
64            Self::Available(position) => Self::Levitating(position),
65            _ => self,
66        }
67    }
68
69    /// Brings the [`Cursor`] back to the current layer.
70    pub fn land(self) -> Self {
71        match self {
72            Cursor::Levitating(position) => Cursor::Available(position),
73            _ => self,
74        }
75    }
76}
77
78impl std::ops::Mul<Transformation> for Cursor {
79    type Output = Self;
80
81    fn mul(self, transformation: Transformation) -> Self {
82        match self {
83            Self::Available(position) => {
84                Self::Available(position * transformation)
85            }
86            Self::Levitating(position) => {
87                Self::Levitating(position * transformation)
88            }
89            Self::Unavailable => Self::Unavailable,
90        }
91    }
92}