use crate::priority_queue::Priority;
use hojicha_core::core::Message;
use hojicha_core::event::Event;
pub fn detect_priority<M: Message>(event: &Event<M>) -> Priority {
if event.is_quit() || event.is_key() || event.is_suspend() || event.is_resume() {
Priority::High
} else if event.is_resize() || event.is_tick() {
Priority::Low
} else {
Priority::Normal
}
}
#[derive(Debug, Clone)]
pub enum EventKind {
Quit,
Key,
Mouse,
User,
Resize,
Tick,
Paste,
Focus,
Blur,
Suspend,
Resume,
ExecProcess,
}
impl EventKind {
pub fn priority(&self) -> Priority {
match self {
EventKind::Quit => Priority::High,
EventKind::Key => Priority::High,
EventKind::Suspend => Priority::High,
EventKind::Resume => Priority::High,
EventKind::Mouse => Priority::Normal,
EventKind::User => Priority::Normal,
EventKind::Paste => Priority::Normal,
EventKind::Focus => Priority::Normal,
EventKind::Blur => Priority::Normal,
EventKind::ExecProcess => Priority::Normal,
EventKind::Resize => Priority::Low,
EventKind::Tick => Priority::Low,
}
}
pub fn from_event<M: Message>(event: &Event<M>) -> Self {
if event.is_quit() {
EventKind::Quit
} else if event.is_key() {
EventKind::Key
} else if event.is_mouse() {
EventKind::Mouse
} else if event.is_user() {
EventKind::User
} else if event.is_resize() {
EventKind::Resize
} else if event.is_tick() {
EventKind::Tick
} else if event.is_paste() {
EventKind::Paste
} else if event.is_focus() {
EventKind::Focus
} else if event.is_blur() {
EventKind::Blur
} else if event.is_suspend() {
EventKind::Suspend
} else if event.is_resume() {
EventKind::Resume
} else {
EventKind::ExecProcess
}
}
}
pub trait SafePriorityMapper<M: Message>: Send + Sync {
fn map_priority(&self, event: &Event<M>) -> Priority;
}
pub struct DefaultPriorityMapper;
impl<M: Message> SafePriorityMapper<M> for DefaultPriorityMapper {
fn map_priority(&self, event: &Event<M>) -> Priority {
detect_priority(event)
}
}
type PriorityMapperFn<M> = Box<dyn Fn(&Event<M>) -> Option<Priority> + Send + Sync>;
pub struct CustomPriorityMapper<M: Message> {
mapper: PriorityMapperFn<M>,
}
impl<M: Message> CustomPriorityMapper<M> {
pub fn new<F>(mapper: F) -> Self
where
F: Fn(&Event<M>) -> Option<Priority> + Send + Sync + 'static,
{
Self {
mapper: Box::new(mapper),
}
}
}
impl<M: Message> SafePriorityMapper<M> for CustomPriorityMapper<M> {
fn map_priority(&self, event: &Event<M>) -> Priority {
(self.mapper)(event).unwrap_or_else(|| detect_priority(event))
}
}
#[cfg(test)]
mod tests {
use super::*;
use hojicha_core::event::{Event, Key, KeyEvent, KeyModifiers};
#[test]
fn test_priority_detection() {
assert_eq!(detect_priority::<()>(&Event::Quit), Priority::High);
assert_eq!(
detect_priority::<()>(&Event::Key(KeyEvent::new(
Key::Char('a'),
KeyModifiers::empty()
))),
Priority::High
);
assert_eq!(
detect_priority::<String>(&Event::User("test".to_string())),
Priority::Normal
);
assert_eq!(detect_priority::<()>(&Event::Tick), Priority::Low);
assert_eq!(
detect_priority::<()>(&Event::Resize {
width: 80,
height: 24
}),
Priority::Low
);
}
#[test]
fn test_event_kind() {
let quit_event: Event<()> = Event::Quit;
assert_eq!(
EventKind::from_event(&quit_event).priority(),
Priority::High
);
let tick_event: Event<()> = Event::Tick;
assert_eq!(EventKind::from_event(&tick_event).priority(), Priority::Low);
}
#[test]
fn test_custom_mapper() {
let mapper = CustomPriorityMapper::new(|event| {
if event.is_user() {
Some(Priority::High)
} else {
None
}
});
let user_event = Event::User("important".to_string());
assert_eq!(mapper.map_priority(&user_event), Priority::High);
let tick_event: Event<String> = Event::Tick;
assert_eq!(mapper.map_priority(&tick_event), Priority::Low);
}
}