use std::time::Duration;
use bevy::{app::AppExit, prelude::*};
use color_eyre::Result;
use crossterm::event::{self, Event::Key, KeyCode, KeyEventKind, KeyModifiers};
use ratatui::layout::Size;
use crate::error::exit_on_error;
pub struct EventPlugin;
impl Plugin for EventPlugin {
fn build(&self, app: &mut App) {
app.add_event::<KeyEvent>()
.add_event::<MouseEvent>()
.add_event::<FocusEvent>()
.add_event::<ResizeEvent>()
.add_event::<PasteEvent>()
.add_event::<CrosstermEvent>()
.add_systems(PreUpdate, crossterm_event_system.pipe(exit_on_error));
}
}
#[derive(Debug, Deref, Event, PartialEq, Eq, Clone, Hash)]
pub struct CrosstermEvent(pub event::Event);
#[derive(Debug, Deref, Event, PartialEq, Eq, Clone, Hash)]
pub struct KeyEvent(pub event::KeyEvent);
#[derive(Debug, Clone, Copy, Event, PartialEq, Eq, Deref)]
pub struct MouseEvent(pub event::MouseEvent);
#[derive(Debug, Clone, Copy, Event, PartialEq, Eq)]
pub enum FocusEvent {
Gained,
Lost,
}
#[derive(Debug, Clone, Copy, Event, PartialEq, Eq, Deref)]
pub struct ResizeEvent(pub Size);
#[derive(Debug, Clone, Event, PartialEq, Eq, Deref)]
pub struct PasteEvent(pub String);
pub fn crossterm_event_system(
mut events: EventWriter<CrosstermEvent>,
mut keys: EventWriter<KeyEvent>,
mut mouse: EventWriter<MouseEvent>,
mut focus: EventWriter<FocusEvent>,
mut paste: EventWriter<PasteEvent>,
mut resize: EventWriter<ResizeEvent>,
mut exit: EventWriter<AppExit>,
) -> Result<()> {
while event::poll(Duration::ZERO)? {
let event = event::read()?;
match event {
Key(event) => {
if event.kind == KeyEventKind::Press
&& event.modifiers == KeyModifiers::CONTROL
&& event.code == KeyCode::Char('c')
{
exit.send_default();
}
keys.send(KeyEvent(event));
}
event::Event::FocusLost => {
focus.send(FocusEvent::Lost);
}
event::Event::FocusGained => {
focus.send(FocusEvent::Gained);
}
event::Event::Mouse(event) => {
mouse.send(MouseEvent(event));
}
event::Event::Paste(ref s) => {
paste.send(PasteEvent(s.clone()));
}
event::Event::Resize(columns, rows) => {
resize.send(ResizeEvent(Size::new(columns, rows)));
}
}
events.send(CrosstermEvent(event));
}
Ok(())
}