use std::collections::VecDeque;
use std::time::{Duration, Instant};
use glutin::event_loop::EventLoopProxy;
use glutin::window::WindowId;
use crate::event::Event;
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub struct TimerId {
topic: Topic,
window_id: WindowId,
}
impl TimerId {
pub fn new(topic: Topic, window_id: WindowId) -> Self {
Self { topic, window_id }
}
}
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Topic {
SelectionScrolling,
DelayedSearch,
BlinkCursor,
BlinkTimeout,
}
pub struct Timer {
pub deadline: Instant,
pub event: Event,
pub id: TimerId,
interval: Option<Duration>,
}
pub struct Scheduler {
timers: VecDeque<Timer>,
event_proxy: EventLoopProxy<Event>,
}
impl Scheduler {
pub fn new(event_proxy: EventLoopProxy<Event>) -> Self {
Self { timers: VecDeque::new(), event_proxy }
}
pub fn update(&mut self) -> Option<Instant> {
let now = Instant::now();
while !self.timers.is_empty() && self.timers[0].deadline <= now {
if let Some(timer) = self.timers.pop_front() {
if let Some(interval) = timer.interval {
self.schedule(timer.event.clone(), interval, true, timer.id);
}
let _ = self.event_proxy.send_event(timer.event);
}
}
self.timers.get(0).map(|timer| timer.deadline)
}
pub fn schedule(&mut self, event: Event, interval: Duration, repeat: bool, timer_id: TimerId) {
let deadline = Instant::now() + interval;
let index = self
.timers
.iter()
.position(|timer| timer.deadline > deadline)
.unwrap_or_else(|| self.timers.len());
let interval = if repeat { Some(interval) } else { None };
self.timers.insert(index, Timer { interval, deadline, event, id: timer_id });
}
pub fn unschedule(&mut self, id: TimerId) -> Option<Timer> {
let index = self.timers.iter().position(|timer| timer.id == id)?;
self.timers.remove(index)
}
pub fn scheduled(&mut self, id: TimerId) -> bool {
self.timers.iter().any(|timer| timer.id == id)
}
pub fn unschedule_window(&mut self, window_id: WindowId) {
self.timers.retain(|timer| timer.id.window_id != window_id);
}
}