use crate::input::Modifiers;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct MouseEvent {
pub kind: MouseEventKind,
pub column: u16,
pub row: u16,
pub modifiers: Modifiers,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MouseEventKind {
Down(MouseButton),
Up(MouseButton),
Drag(MouseButton),
Moved,
ScrollUp,
ScrollDown,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum MouseButton {
Left,
Right,
Middle,
}
impl TryFrom<crossterm::event::MouseButton> for MouseButton {
type Error = ();
fn try_from(b: crossterm::event::MouseButton) -> Result<Self, ()> {
match b {
crossterm::event::MouseButton::Left => Ok(MouseButton::Left),
crossterm::event::MouseButton::Right => Ok(MouseButton::Right),
crossterm::event::MouseButton::Middle => Ok(MouseButton::Middle),
}
}
}
impl TryFrom<crossterm::event::MouseEventKind> for MouseEventKind {
type Error = ();
fn try_from(k: crossterm::event::MouseEventKind) -> Result<Self, ()> {
use crossterm::event::MouseEventKind as Ck;
match k {
Ck::Down(b) => Ok(MouseEventKind::Down(b.try_into()?)),
Ck::Up(b) => Ok(MouseEventKind::Up(b.try_into()?)),
Ck::Drag(b) => Ok(MouseEventKind::Drag(b.try_into()?)),
Ck::Moved => Ok(MouseEventKind::Moved),
Ck::ScrollUp => Ok(MouseEventKind::ScrollUp),
Ck::ScrollDown => Ok(MouseEventKind::ScrollDown),
_ => Err(()),
}
}
}
impl TryFrom<crossterm::event::MouseEvent> for MouseEvent {
type Error = ();
fn try_from(m: crossterm::event::MouseEvent) -> Result<Self, ()> {
Ok(MouseEvent {
kind: m.kind.try_into()?,
column: m.column,
row: m.row,
modifiers: m.modifiers.into(),
})
}
}
#[cfg(test)]
mod tests {
use super::*;
use crossterm::event as ct;
#[test]
fn button_left() {
assert_eq!(
MouseButton::try_from(ct::MouseButton::Left),
Ok(MouseButton::Left)
);
}
#[test]
fn button_right() {
assert_eq!(
MouseButton::try_from(ct::MouseButton::Right),
Ok(MouseButton::Right)
);
}
#[test]
fn button_middle() {
assert_eq!(
MouseButton::try_from(ct::MouseButton::Middle),
Ok(MouseButton::Middle)
);
}
#[test]
fn kind_down_left() {
assert_eq!(
MouseEventKind::try_from(ct::MouseEventKind::Down(ct::MouseButton::Left)),
Ok(MouseEventKind::Down(MouseButton::Left))
);
}
#[test]
fn kind_up_right() {
assert_eq!(
MouseEventKind::try_from(ct::MouseEventKind::Up(ct::MouseButton::Right)),
Ok(MouseEventKind::Up(MouseButton::Right))
);
}
#[test]
fn kind_drag_middle() {
assert_eq!(
MouseEventKind::try_from(ct::MouseEventKind::Drag(ct::MouseButton::Middle)),
Ok(MouseEventKind::Drag(MouseButton::Middle))
);
}
#[test]
fn kind_moved() {
assert_eq!(
MouseEventKind::try_from(ct::MouseEventKind::Moved),
Ok(MouseEventKind::Moved)
);
}
#[test]
fn kind_scroll_up() {
assert_eq!(
MouseEventKind::try_from(ct::MouseEventKind::ScrollUp),
Ok(MouseEventKind::ScrollUp)
);
}
#[test]
fn kind_scroll_down() {
assert_eq!(
MouseEventKind::try_from(ct::MouseEventKind::ScrollDown),
Ok(MouseEventKind::ScrollDown)
);
}
#[test]
fn kind_scroll_left_is_err() {
assert!(
MouseEventKind::try_from(ct::MouseEventKind::ScrollLeft).is_err()
);
}
fn make_ct_event(
kind: ct::MouseEventKind,
col: u16,
row: u16,
mods: ct::KeyModifiers,
) -> ct::MouseEvent {
ct::MouseEvent {
kind,
column: col,
row,
modifiers: mods,
}
}
#[test]
fn mouse_event_success() {
let ev = MouseEvent::try_from(make_ct_event(
ct::MouseEventKind::Down(ct::MouseButton::Left),
10,
5,
ct::KeyModifiers::empty(),
))
.unwrap();
assert_eq!(ev.kind, MouseEventKind::Down(MouseButton::Left));
assert_eq!(ev.column, 10);
assert_eq!(ev.row, 5);
assert!(ev.modifiers.is_empty());
}
#[test]
fn mouse_event_with_ctrl_modifier() {
let ev = MouseEvent::try_from(make_ct_event(
ct::MouseEventKind::ScrollUp,
0,
0,
ct::KeyModifiers::CONTROL,
))
.unwrap();
assert!(ev.modifiers.contains(Modifiers::CTRL));
}
#[test]
fn mouse_event_unknown_kind_is_err() {
assert!(MouseEvent::try_from(make_ct_event(
ct::MouseEventKind::ScrollLeft,
0,
0,
ct::KeyModifiers::empty(),
))
.is_err());
}
#[test]
fn mouse_event_clone_eq() {
let ev = MouseEvent {
kind: MouseEventKind::Moved,
column: 1,
row: 2,
modifiers: Modifiers::empty(),
};
assert_eq!(ev.clone(), ev);
}
}