summaryrefslogtreecommitdiffstats
path: root/core/src/mouse
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/mouse')
-rw-r--r--core/src/mouse/button.rs2
-rw-r--r--core/src/mouse/click.rs76
-rw-r--r--core/src/mouse/cursor.rs52
-rw-r--r--core/src/mouse/interaction.rs10
4 files changed, 132 insertions, 8 deletions
diff --git a/core/src/mouse/button.rs b/core/src/mouse/button.rs
index aeb8a55d..3eec7f42 100644
--- a/core/src/mouse/button.rs
+++ b/core/src/mouse/button.rs
@@ -11,5 +11,5 @@ pub enum Button {
Middle,
/// Some other button.
- Other(u8),
+ Other(u16),
}
diff --git a/core/src/mouse/click.rs b/core/src/mouse/click.rs
new file mode 100644
index 00000000..4a7d796c
--- /dev/null
+++ b/core/src/mouse/click.rs
@@ -0,0 +1,76 @@
+//! Track mouse clicks.
+use crate::time::Instant;
+use crate::Point;
+
+/// A mouse click.
+#[derive(Debug, Clone, Copy)]
+pub struct Click {
+ kind: Kind,
+ position: Point,
+ time: Instant,
+}
+
+/// The kind of mouse click.
+#[derive(Debug, Clone, Copy)]
+pub enum Kind {
+ /// A single click
+ Single,
+
+ /// A double click
+ Double,
+
+ /// A triple click
+ Triple,
+}
+
+impl Kind {
+ fn next(&self) -> Kind {
+ match self {
+ Kind::Single => Kind::Double,
+ Kind::Double => Kind::Triple,
+ Kind::Triple => Kind::Double,
+ }
+ }
+}
+
+impl Click {
+ /// Creates a new [`Click`] with the given position and previous last
+ /// [`Click`].
+ pub fn new(position: Point, previous: Option<Click>) -> Click {
+ let time = Instant::now();
+
+ let kind = if let Some(previous) = previous {
+ if previous.is_consecutive(position, time) {
+ previous.kind.next()
+ } else {
+ Kind::Single
+ }
+ } else {
+ Kind::Single
+ };
+
+ Click {
+ kind,
+ position,
+ time,
+ }
+ }
+
+ /// Returns the [`Kind`] of [`Click`].
+ pub fn kind(&self) -> Kind {
+ self.kind
+ }
+
+ fn is_consecutive(&self, new_position: Point, time: Instant) -> bool {
+ let duration = if time > self.time {
+ Some(time - self.time)
+ } else {
+ None
+ };
+
+ self.position == new_position
+ && duration
+ .map(|duration| duration.as_millis() <= 300)
+ .unwrap_or(false)
+ }
+}
diff --git a/core/src/mouse/cursor.rs b/core/src/mouse/cursor.rs
new file mode 100644
index 00000000..203526e9
--- /dev/null
+++ b/core/src/mouse/cursor.rs
@@ -0,0 +1,52 @@
+use crate::{Point, Rectangle, Vector};
+
+/// The mouse cursor state.
+#[derive(Debug, Clone, Copy, PartialEq, Default)]
+pub enum Cursor {
+ /// The cursor has a defined position.
+ Available(Point),
+
+ /// The cursor is currently unavailable (i.e. out of bounds or busy).
+ #[default]
+ Unavailable,
+}
+
+impl Cursor {
+ /// Returns the absolute position of the [`Cursor`], if available.
+ pub fn position(self) -> Option<Point> {
+ match self {
+ Cursor::Available(position) => Some(position),
+ Cursor::Unavailable => None,
+ }
+ }
+
+ /// Returns the absolute position of the [`Cursor`], if available and inside
+ /// the given bounds.
+ ///
+ /// If the [`Cursor`] is not over the provided bounds, this method will
+ /// return `None`.
+ pub fn position_over(self, bounds: Rectangle) -> Option<Point> {
+ self.position().filter(|p| bounds.contains(*p))
+ }
+
+ /// Returns the relative position of the [`Cursor`] inside the given bounds,
+ /// if available.
+ ///
+ /// If the [`Cursor`] is not over the provided bounds, this method will
+ /// return `None`.
+ pub fn position_in(self, bounds: Rectangle) -> Option<Point> {
+ self.position_over(bounds)
+ .map(|p| p - Vector::new(bounds.x, bounds.y))
+ }
+
+ /// Returns the relative position of the [`Cursor`] from the given origin,
+ /// if available.
+ pub fn position_from(self, origin: Point) -> Option<Point> {
+ self.position().map(|p| p - Vector::new(origin.x, origin.y))
+ }
+
+ /// Returns true if the [`Cursor`] is over the given `bounds`.
+ pub fn is_over(self, bounds: Rectangle) -> bool {
+ self.position_over(bounds).is_some()
+ }
+}
diff --git a/core/src/mouse/interaction.rs b/core/src/mouse/interaction.rs
index 664147a7..072033fd 100644
--- a/core/src/mouse/interaction.rs
+++ b/core/src/mouse/interaction.rs
@@ -1,7 +1,8 @@
/// The interaction of a mouse cursor.
-#[derive(Debug, Eq, PartialEq, Clone, Copy, PartialOrd, Ord)]
+#[derive(Debug, Eq, PartialEq, Clone, Copy, PartialOrd, Ord, Default)]
#[allow(missing_docs)]
pub enum Interaction {
+ #[default]
Idle,
Pointer,
Grab,
@@ -11,10 +12,5 @@ pub enum Interaction {
Grabbing,
ResizingHorizontally,
ResizingVertically,
-}
-
-impl Default for Interaction {
- fn default() -> Interaction {
- Interaction::Idle
- }
+ NotAllowed,
}