-
Notifications
You must be signed in to change notification settings - Fork 9
Expand file tree
/
Copy pathevents.rs
More file actions
86 lines (74 loc) · 2.5 KB
/
events.rs
File metadata and controls
86 lines (74 loc) · 2.5 KB
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
use core::fmt;
use std::{pin::Pin, time::Duration};
use crossterm::event::{Event as CrosstermEvent, *};
use futures::{Stream, StreamExt};
use serde::{Deserialize, Serialize};
use tokio::time::interval;
use tokio_stream::{StreamMap, wrappers::IntervalStream};
use crate::config;
pub struct Events {
streams: StreamMap<StreamName, Pin<Box<dyn Stream<Item = Event>>>>,
}
impl fmt::Debug for Events {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Events").finish_non_exhaustive()
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
enum StreamName {
Ticks,
KeyRefresh,
Render,
Crossterm,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub enum Event {
Init,
Quit,
Error,
Closed,
Tick,
KeyRefresh,
Render,
Crossterm(CrosstermEvent),
}
impl Events {
pub fn new() -> Self {
Self {
streams: StreamMap::from_iter([
(StreamName::Ticks, tick_stream()),
(StreamName::KeyRefresh, key_refresh_stream()),
(StreamName::Render, render_stream()),
(StreamName::Crossterm, crossterm_stream()),
]),
}
}
pub async fn next(&mut self) -> Option<Event> {
self.streams.next().await.map(|(_name, event)| event)
}
}
fn tick_stream() -> Pin<Box<dyn Stream<Item = Event>>> {
let tick_delay = Duration::from_secs_f64(1.0 / config::get().tick_rate);
let tick_interval = interval(tick_delay);
Box::pin(IntervalStream::new(tick_interval).map(|_| Event::Tick))
}
fn key_refresh_stream() -> Pin<Box<dyn Stream<Item = Event>>> {
let key_refresh_delay = Duration::from_secs_f64(1.0 / config::get().key_refresh_rate);
let key_refresh_interval = interval(key_refresh_delay);
Box::pin(IntervalStream::new(key_refresh_interval).map(|_| Event::KeyRefresh))
}
fn render_stream() -> Pin<Box<dyn Stream<Item = Event>>> {
let render_delay = Duration::from_secs_f64(1.0 / config::get().frame_rate);
let render_interval = interval(render_delay);
Box::pin(IntervalStream::new(render_interval).map(|_| Event::Render))
}
fn crossterm_stream() -> Pin<Box<dyn Stream<Item = Event>>> {
Box::pin(EventStream::new().fuse().filter_map(|event| async move {
match event {
// Ignore key release / repeat events
Ok(CrosstermEvent::Key(key)) if key.kind == KeyEventKind::Release => None,
Ok(event) => Some(Event::Crossterm(event)),
Err(_) => Some(Event::Error),
}
}))
}