1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
use {
    crossterm::{
        self,
        event::{
            KeyCode, KeyModifiers, MouseEventKind,
        },
    },
};

/// a valid user event
///
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Event {

    Key(crossterm::event::KeyEvent),

    Click(u16, u16, KeyModifiers),

    RightClick(u16, u16, KeyModifiers),

    DoubleClick(u16, u16),

    /// terminal was resized. Contains the new dimensions
    Resize(u16, u16),

    /// mouse wheel turns. contains -1 if up or 1 if down
    Wheel(i32),
}

impl Event {
    /// convert a crossterm event into a termimad one.
    ///
    /// normalize \r and \n into Enter (useful for key combinations)
    ///
    /// To get a double-click you'll either need to use a termimad event-source
    /// or to do the computation yourself.
    pub fn from_crossterm_event(
        crossterm_event: crossterm::event::Event
    ) -> Option<Event> {
        match crossterm_event {
            crossterm::event::Event::Key(mut key) => {
                if key.code==KeyCode::Char('\r') || key.code==KeyCode::Char('\n') {
                    key.code = KeyCode::Enter;
                }
                Some(Event::Key(key))
            }
            crossterm::event::Event::Resize(w, h) => {
                Some(Event::Resize(w, h))
            }
            crossterm::event::Event::Mouse(
                crossterm::event::MouseEvent {
                    kind: MouseEventKind::Up(button),
                    column,
                    row,
                    modifiers,
                }
            ) => {
                use crossterm::event::MouseButton::*;
                match button {
                    Left => Some(Event::Click(column, row, modifiers)),
                    Right => Some(Event::RightClick(column, row, modifiers)),
                    _ => None
                }
            }
            crossterm::event::Event::Mouse(
                crossterm::event::MouseEvent { kind: MouseEventKind::ScrollUp, .. }
            ) => {
                Some(Event::Wheel(-1))
            }
            crossterm::event::Event::Mouse(
                crossterm::event::MouseEvent { kind: MouseEventKind::ScrollDown, .. }
            ) => {
                Some(Event::Wheel(1))
            }
            _ => None,
        }
    }
    pub const fn crtl_key(code: KeyCode) -> Self {
        Event::Key(
            crossterm::event::KeyEvent {
                code,
                modifiers: KeyModifiers::CONTROL,
            }
        )
    }
    pub const fn simple_key(code: KeyCode) -> Self {
        Event::Key(
            crossterm::event::KeyEvent {
                code,
                modifiers: KeyModifiers::empty(),
            }
        )
    }
    /// In case the event is mouse related, give the position
    pub fn mouse_pos(self) -> Option<(u16, u16)> {
        match self {
            Event::Click(x, y, _) => Some((x, y)),
            Event::RightClick(x, y, _) => Some((x, y)),
            Event::DoubleClick(x, y) => Some((x, y)),
            _ => None,
        }
    }
}