use serde::{Deserialize, Serialize};
use super::keyboard::KeyModifiers;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct MouseEvent {
pub kind: MouseEventKind,
pub column: u16,
pub row: u16,
pub modifiers: KeyModifiers,
}
impl MouseEvent {
pub fn new(kind: MouseEventKind, column: u16, row: u16, modifiers: KeyModifiers) -> Self {
Self {
kind,
column,
row,
modifiers,
}
}
pub fn is_left_click(&self) -> bool {
matches!(
self.kind,
MouseEventKind::Down(MouseButton::Left) | MouseEventKind::Up(MouseButton::Left)
)
}
pub fn is_right_click(&self) -> bool {
matches!(
self.kind,
MouseEventKind::Down(MouseButton::Right) | MouseEventKind::Up(MouseButton::Right)
)
}
pub fn is_scroll(&self) -> bool {
matches!(
self.kind,
MouseEventKind::ScrollUp | MouseEventKind::ScrollDown
)
}
pub fn is_drag(&self) -> bool {
matches!(self.kind, MouseEventKind::Drag(_))
}
pub fn is_move(&self) -> bool {
matches!(self.kind, MouseEventKind::Moved)
}
pub fn position(&self) -> (u16, u16) {
(self.column, self.row)
}
}
impl From<crossterm::event::MouseEvent> for MouseEvent {
fn from(event: crossterm::event::MouseEvent) -> Self {
Self {
kind: event.kind.into(),
column: event.column,
row: event.row,
modifiers: event.modifiers.into(),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum MouseEventKind {
Down(MouseButton),
Up(MouseButton),
Drag(MouseButton),
Moved,
ScrollUp,
ScrollDown,
ScrollLeft,
ScrollRight,
}
impl From<crossterm::event::MouseEventKind> for MouseEventKind {
fn from(kind: crossterm::event::MouseEventKind) -> Self {
use crossterm::event::MouseEventKind as CT;
match kind {
CT::Down(b) => MouseEventKind::Down(b.into()),
CT::Up(b) => MouseEventKind::Up(b.into()),
CT::Drag(b) => MouseEventKind::Drag(b.into()),
CT::Moved => MouseEventKind::Moved,
CT::ScrollUp => MouseEventKind::ScrollUp,
CT::ScrollDown => MouseEventKind::ScrollDown,
CT::ScrollLeft => MouseEventKind::ScrollLeft,
CT::ScrollRight => MouseEventKind::ScrollRight,
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
pub enum MouseButton {
Left,
Right,
Middle,
}
impl From<crossterm::event::MouseButton> for MouseButton {
fn from(button: crossterm::event::MouseButton) -> Self {
use crossterm::event::MouseButton as CT;
match button {
CT::Left => MouseButton::Left,
CT::Right => MouseButton::Right,
CT::Middle => MouseButton::Middle,
}
}
}
#[cfg(test)]
mod tests {
use super::{MouseButton, MouseEvent, MouseEventKind};
use crate::input::keyboard::KeyModifiers;
#[test]
fn test_mouse_event_new() {
let event = MouseEvent::new(
MouseEventKind::Down(MouseButton::Left),
10,
20,
KeyModifiers::NONE,
);
assert_eq!(event.column, 10);
assert_eq!(event.row, 20);
assert!(event.is_left_click());
}
#[test]
fn test_mouse_position() {
let event = MouseEvent::new(MouseEventKind::Moved, 5, 15, KeyModifiers::NONE);
assert_eq!(event.position(), (5, 15));
assert!(event.is_move());
}
#[test]
fn test_scroll() {
let event = MouseEvent::new(MouseEventKind::ScrollUp, 0, 0, KeyModifiers::NONE);
assert!(event.is_scroll());
}
}