#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub struct Modifiers {
pub shift: bool,
pub alt: bool,
pub ctrl: bool,
}
impl Modifiers {
pub const NONE: Modifiers = Modifiers {
shift: false,
alt: false,
ctrl: false,
};
pub fn is_none(self) -> bool {
self == Modifiers::NONE
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum KeyCode {
Char(char),
Enter,
Tab,
Backspace,
Esc,
Up,
Down,
Left,
Right,
Home,
End,
PageUp,
PageDown,
Insert,
Delete,
F(u8),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Key {
pub code: KeyCode,
pub modifiers: Modifiers,
}
impl Key {
pub fn new(code: KeyCode) -> Key {
Key {
code,
modifiers: Modifiers::NONE,
}
}
pub fn is_char(&self, c: char) -> bool {
self.code == KeyCode::Char(c) && self.modifiers.is_none()
}
pub fn is_ctrl(&self, c: char) -> bool {
self.code == KeyCode::Char(c) && self.modifiers.ctrl
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum MouseButton {
Left,
Middle,
Right,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum MouseKind {
Down(MouseButton),
Up(MouseButton),
Drag(MouseButton),
Moved,
ScrollUp,
ScrollDown,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Mouse {
pub kind: MouseKind,
pub x: isize,
pub y: isize,
pub modifiers: Modifiers,
}
impl Mouse {
pub fn cell_in(&self, display: &terminal_graphics::Display) -> Option<(isize, isize)> {
let (width, height) = display.size();
let inside =
self.x >= 0 && self.y >= 0 && self.x < width as isize && self.y < height as isize;
inside.then_some((self.x, self.y))
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[non_exhaustive]
pub enum Event {
Key(Key),
KeyUp(Key),
Mouse(Mouse),
Paste(String),
}
#[cfg(test)]
mod tests {
use super::*;
use terminal_graphics::Display;
fn mouse_at(x: isize, y: isize) -> Mouse {
Mouse {
kind: MouseKind::Moved,
x,
y,
modifiers: Modifiers::NONE,
}
}
#[test]
fn cell_in_gives_the_cell_when_the_mouse_is_over_the_display() {
let display = Display::new(10, 4);
assert_eq!(mouse_at(0, 0).cell_in(&display), Some((0, 0)));
assert_eq!(mouse_at(9, 3).cell_in(&display), Some((9, 3)));
}
#[test]
fn cell_in_is_none_outside_the_display() {
let display = Display::new(10, 4);
assert_eq!(mouse_at(10, 0).cell_in(&display), None);
assert_eq!(mouse_at(0, 4).cell_in(&display), None);
assert_eq!(mouse_at(-1, 0).cell_in(&display), None);
assert_eq!(mouse_at(0, -1).cell_in(&display), None);
}
#[test]
fn cell_in_is_none_for_an_empty_display() {
assert_eq!(mouse_at(0, 0).cell_in(&Display::new(0, 0)), None);
}
}