musichoard/src/tui/event.rs

163 lines
4.0 KiB
Rust
Raw Normal View History

use crossterm::event::{KeyEvent, MouseEvent};
use std::fmt;
use std::sync::mpsc;
use super::ui::UiError;
#[derive(Debug)]
pub enum EventError {
Send(Event),
Recv,
Io(std::io::Error),
Ui(String),
}
impl fmt::Display for EventError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Self::Send(ref e) => write!(f, "failed to send event: {e:?}"),
Self::Recv => write!(f, "receive event call failed"),
Self::Io(ref e) => {
write!(f, "an I/O error was triggered during event handling: {e}")
}
Self::Ui(ref s) => {
write!(f, "the UI returned an error during event handling: {s}")
}
}
}
}
impl From<mpsc::SendError<Event>> for EventError {
fn from(err: mpsc::SendError<Event>) -> EventError {
EventError::Send(err.0)
}
}
impl From<mpsc::RecvError> for EventError {
fn from(_: mpsc::RecvError) -> EventError {
EventError::Recv
}
}
impl From<UiError> for EventError {
fn from(err: UiError) -> EventError {
EventError::Ui(err.to_string())
}
}
#[derive(Clone, Copy, Debug)]
pub enum Event {
Key(KeyEvent),
Mouse(MouseEvent),
Resize(u16, u16),
}
pub struct EventChannel {
sender: mpsc::Sender<Event>,
receiver: mpsc::Receiver<Event>,
}
pub struct EventSender {
sender: mpsc::Sender<Event>,
}
pub struct EventReceiver {
receiver: mpsc::Receiver<Event>,
}
impl EventChannel {
pub fn new() -> Self {
let (sender, receiver) = mpsc::channel();
EventChannel { sender, receiver }
}
pub fn sender(&self) -> EventSender {
EventSender {
sender: self.sender.clone(),
}
}
pub fn receiver(self) -> EventReceiver {
EventReceiver {
receiver: self.receiver,
}
}
}
impl EventSender {
pub fn send(&self, event: Event) -> Result<(), EventError> {
Ok(self.sender.send(event)?)
}
}
impl EventReceiver {
pub fn recv(&self) -> Result<Event, EventError> {
Ok(self.receiver.recv()?)
}
}
#[cfg(test)]
mod tests {
use std::io;
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind, KeyEventState, KeyModifiers};
use crate::tui::ui::UiError;
use super::{Event, EventChannel, EventError};
#[test]
fn event_sender() {
let channel = EventChannel::new();
let sender = channel.sender();
let receiver = channel.receiver();
let event = Event::Key(KeyEvent::new(KeyCode::Up, KeyModifiers::empty()));
let result = sender.send(event);
assert!(result.is_ok());
drop(receiver);
let result = sender.send(event);
assert!(result.is_err());
}
#[test]
fn event_receiver() {
let channel = EventChannel::new();
let sender = channel.sender();
let receiver = channel.receiver();
let event = Event::Key(KeyEvent::new(KeyCode::Up, KeyModifiers::empty()));
sender.send(event).unwrap();
let result = receiver.recv();
assert!(result.is_ok());
drop(sender);
let result = receiver.recv();
assert!(result.is_err());
}
#[test]
fn errors() {
let send_err = EventError::Send(Event::Key(KeyEvent {
code: KeyCode::Up,
modifiers: KeyModifiers::empty(),
kind: KeyEventKind::Press,
state: KeyEventState::NONE,
}));
let recv_err = EventError::Recv;
let io_err = EventError::Io(io::Error::new(io::ErrorKind::Interrupted, "interrupted"));
let ui_err: EventError = UiError::Lib(String::from("lib error")).into();
assert!(!send_err.to_string().is_empty());
assert!(!recv_err.to_string().is_empty());
assert!(!io_err.to_string().is_empty());
assert!(!ui_err.to_string().is_empty());
assert!(!format!("{:?}", send_err).is_empty());
assert!(!format!("{:?}", recv_err).is_empty());
assert!(!format!("{:?}", io_err).is_empty());
assert!(!format!("{:?}", ui_err).is_empty());
}
}