use crossterm::event;
use crate::{core::message::RawEvent, node::Node, utils::NodeRef};
pub trait Event: TryFrom<RawEvent> {}
pub trait Listener {
type EventType: Event;
fn on_event(&mut self, node: NodeRef, event: Self::EventType) -> bool;
}
pub struct NodeUpdate(pub Box<dyn FnMut(NodeRef, u64) -> bool + Send + Sync>);
impl Listener for NodeUpdate {
type EventType = u64;
fn on_event(&mut self, node: NodeRef, t: Self::EventType) -> bool {
(self.0)(node, t)
}
}
pub struct MouseClick(pub Box<dyn FnMut(NodeRef, MouseEvent) -> bool + Send + Sync>);
impl Listener for MouseClick {
type EventType = MouseEvent;
fn on_event(&mut self, node: NodeRef, event: Self::EventType) -> bool {
if (event.x as i32) >= Node::get_left(node.as_ref())
&& (event.x as i32) <= Node::get_right(node.as_ref())
&& (event.y as i32) >= Node::get_top(node.as_ref())
&& (event.y as i32) <= Node::get_bottom(node.as_ref())
{
let mut event = event.clone();
event.window_x = event.x;
event.window_y = event.y;
event.x = event.x.saturating_sub(Node::get_left(node.as_ref()) as u16);
event.y = event.y.saturating_sub(Node::get_top(node.as_ref()) as u16);
(self.0)(node, event)
} else {
true
}
}
}
pub struct KeyboardPress(pub Box<dyn FnMut(NodeRef, KeyPressEvent) -> bool + Send + Sync>);
impl Listener for KeyboardPress {
type EventType = KeyPressEvent;
fn on_event(&mut self, node: NodeRef, event: Self::EventType) -> bool {
(self.0)(node, event)
}
}
impl Event for u64 {}
impl TryFrom<RawEvent> for u64 {
type Error = ();
fn try_from(value: RawEvent) -> Result<Self, Self::Error> {
if let RawEvent::Update(t) = value {
Ok(t)
} else {
Err(())
}
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct KeyPressEvent {
pub key: Key,
}
impl KeyPressEvent {
pub fn new(key: Key) -> Self {
KeyPressEvent { key }
}
}
impl Event for KeyPressEvent {}
impl TryFrom<RawEvent> for KeyPressEvent {
type Error = ();
fn try_from(value: RawEvent) -> Result<Self, Self::Error> {
if let RawEvent::Key(code, modifier) = value {
Ok(KeyPressEvent {
key: raw_key_to_key(code, modifier),
})
} else {
Err(())
}
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct MouseEvent {
pub x: u16,
pub y: u16,
pub window_x: u16,
pub window_y: u16,
pub state: MouseState,
pub button: Button,
}
impl MouseEvent {
pub fn new(
x: u16,
y: u16,
window_x: u16,
window_y: u16,
state: MouseState,
button: Button,
) -> Self {
MouseEvent {
x,
y,
window_x,
window_y,
state,
button,
}
}
}
impl Event for MouseEvent {}
impl TryFrom<RawEvent> for MouseEvent {
type Error = ();
fn try_from(value: RawEvent) -> Result<Self, Self::Error> {
if let RawEvent::Mouse(x, y, kind) = value {
match kind {
event::MouseEventKind::Down(button) => Ok(MouseEvent::new(
x,
y,
x,
y,
MouseState::Press,
raw_button_to_button(button),
)),
event::MouseEventKind::Up(button) => Ok(MouseEvent::new(
x,
y,
x,
y,
MouseState::Release,
raw_button_to_button(button),
)),
event::MouseEventKind::Drag(button) => Ok(MouseEvent::new(
x,
y,
x,
y,
MouseState::Hold,
raw_button_to_button(button),
)),
event::MouseEventKind::ScrollUp => Ok(MouseEvent::new(
x,
y,
x,
y,
MouseState::ScrollUp,
Button::WheelUp,
)),
event::MouseEventKind::ScrollDown => Ok(MouseEvent::new(
x,
y,
x,
y,
MouseState::ScrollDown,
Button::WheelDown,
)),
event::MouseEventKind::ScrollLeft => Ok(MouseEvent::new(
x,
y,
x,
y,
MouseState::ScrollLeft,
Button::WheelLeft,
)),
event::MouseEventKind::ScrollRight => Ok(MouseEvent::new(
x,
y,
x,
y,
MouseState::ScrollRight,
Button::WheelRight,
)),
event::MouseEventKind::Moved => {
Ok(MouseEvent::new(x, y, x, y, MouseState::Move, Button::Left))
}
}
} else {
Err(())
}
}
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub enum Key {
Up,
Down,
Left,
Right,
Escape,
Backspace,
Space,
Char(char),
Ctrl(Box<Key>),
Alt(Box<Key>),
Shift(Box<Key>),
Unknown,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum Button {
Left,
Right,
Middle,
WheelUp,
WheelDown,
WheelLeft,
WheelRight,
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum MouseState {
Press,
Release,
Hold,
Scroll,
ScrollUp,
ScrollDown,
ScrollLeft,
ScrollRight,
Move,
}
fn raw_key_to_key(key: event::KeyCode, modifier: event::KeyModifiers) -> Key {
let modify = |key: Key| match modifier {
event::KeyModifiers::CONTROL => Key::Ctrl(key.into()),
event::KeyModifiers::ALT => Key::Alt(key.into()),
event::KeyModifiers::SHIFT => Key::Shift(key.into()),
event::KeyModifiers::NONE => key,
_ => Key::Unknown,
};
match key {
event::KeyCode::Up => modify(Key::Up),
event::KeyCode::Down => modify(Key::Down),
event::KeyCode::Left => modify(Key::Left),
event::KeyCode::Right => modify(Key::Right),
event::KeyCode::Esc => Key::Escape,
event::KeyCode::Backspace => Key::Backspace,
event::KeyCode::Enter => Key::Char('\n'),
event::KeyCode::Char(c) => modify(Key::Char(c)),
_ => Key::Unknown,
}
}
fn raw_button_to_button(button: event::MouseButton) -> Button {
match button {
event::MouseButton::Left => Button::Left,
event::MouseButton::Right => Button::Right,
event::MouseButton::Middle => Button::Middle,
}
}