use crate::model::{Cmd, Msg};
use std::fmt;
use std::time::{Duration, SystemTime};
pub struct BatchMsg(pub Vec<Cmd>);
impl fmt::Debug for BatchMsg {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "BatchMsg({} commands)", self.0.len())
}
}
pub struct SequenceMsg(pub Vec<Cmd>);
impl fmt::Debug for SequenceMsg {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "SequenceMsg({} commands)", self.0.len())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct QuitMsg;
pub fn quit() -> Cmd {
Some(Box::new(|| Some(Box::new(QuitMsg))))
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct SuspendMsg;
pub fn suspend() -> Cmd {
Some(Box::new(|| Some(Box::new(SuspendMsg))))
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ResumeMsg;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct InterruptMsg;
pub fn interrupt() -> Cmd {
Some(Box::new(|| Some(Box::new(InterruptMsg))))
}
pub fn batch(cmds: Vec<Cmd>) -> Cmd {
let mut valid_cmds = Vec::new();
for cmd in cmds {
if cmd.is_some() {
valid_cmds.push(cmd);
}
}
match valid_cmds.len() {
0 => None,
1 => valid_cmds.into_iter().next().unwrap(),
_ => Some(Box::new(move || Some(Box::new(BatchMsg(valid_cmds))))),
}
}
pub fn sequence(cmds: Vec<Cmd>) -> Cmd {
let mut valid_cmds = Vec::new();
for cmd in cmds {
if cmd.is_some() {
valid_cmds.push(cmd);
}
}
match valid_cmds.len() {
0 => None,
1 => valid_cmds.into_iter().next().unwrap(),
_ => Some(Box::new(move || Some(Box::new(SequenceMsg(valid_cmds))))),
}
}
pub fn every<F>(duration: Duration, fn_msg: F) -> Cmd
where
F: FnOnce(SystemTime) -> Option<Box<dyn Msg>> + Send + Sync + 'static,
{
Some(Box::new(move || {
let now = SystemTime::now();
if let Ok(elapsed) = now.duration_since(SystemTime::UNIX_EPOCH) {
let nanos = elapsed.as_nanos();
let dur_nanos = duration.as_nanos();
if dur_nanos > 0 {
let rem = nanos % dur_nanos;
let sleep_nanos = dur_nanos - rem;
std::thread::sleep(Duration::from_nanos(sleep_nanos as u64));
}
} else {
std::thread::sleep(duration);
}
fn_msg(SystemTime::now())
}))
}
pub fn tick<F>(duration: Duration, fn_msg: F) -> Cmd
where
F: FnOnce(SystemTime) -> Option<Box<dyn Msg>> + Send + Sync + 'static,
{
Some(Box::new(move || {
std::thread::sleep(duration);
fn_msg(SystemTime::now())
}))
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct RequestWindowSizeMsg;
pub fn request_window_size() -> Cmd {
Some(Box::new(|| Some(Box::new(RequestWindowSizeMsg))))
}