use crate::entity::Entity;
use std::{any::Any, cmp::Ordering, fmt::Debug};
use vizia_id::GenerationalId;
use web_time::Instant;
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum Propagation {
Up,
Subtree,
Direct,
}
pub struct Event {
pub(crate) meta: EventMeta,
pub(crate) message: Option<Box<dyn Any + Send>>,
}
impl Debug for Event {
fn fmt(&self, _: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Ok(())
}
}
impl Event {
pub fn new<M>(message: M) -> Self
where
M: Any + Send,
{
Event { meta: Default::default(), message: Some(Box::new(message)) }
}
pub fn target(mut self, entity: Entity) -> Self {
self.meta.target = entity;
self
}
pub fn origin(mut self, entity: Entity) -> Self {
self.meta.origin = entity;
self
}
pub fn propagate(mut self, propagation: Propagation) -> Self {
self.meta.propagation = propagation;
self
}
pub fn direct(mut self, entity: Entity) -> Self {
self.meta.propagation = Propagation::Direct;
self.meta.target = entity;
self
}
pub fn consume(&mut self) {
self.meta.consume();
}
pub fn map<M, F>(&mut self, f: F)
where
M: Any + Send,
F: FnOnce(&M, &mut EventMeta),
{
if let Some(message) = &self.message {
if let Some(message) = message.as_ref().downcast_ref() {
(f)(message, &mut self.meta);
}
}
}
pub fn take<M: Any + Send, F>(&mut self, f: F)
where
F: FnOnce(M, &mut EventMeta),
{
if let Some(message) = &self.message {
if message.as_ref().is::<M>() {
let m = self.message.take().unwrap();
let v = m.downcast().unwrap();
self.meta.consume();
(f)(*v, &mut self.meta);
}
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct EventMeta {
pub origin: Entity,
pub target: Entity,
pub propagation: Propagation,
pub(crate) consumed: bool,
}
impl EventMeta {
pub fn consume(&mut self) {
self.consumed = true;
}
}
impl Default for EventMeta {
fn default() -> Self {
Self {
origin: Entity::null(),
target: Entity::root(),
propagation: Propagation::Up,
consumed: false,
}
}
}
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub struct TimedEventHandle(pub usize);
#[derive(Debug)]
pub(crate) struct TimedEvent {
pub ident: TimedEventHandle,
pub event: Event,
pub time: Instant,
}
impl PartialEq<Self> for TimedEvent {
fn eq(&self, other: &Self) -> bool {
self.time.eq(&other.time)
}
}
impl Eq for TimedEvent {}
impl PartialOrd for TimedEvent {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for TimedEvent {
fn cmp(&self, other: &Self) -> Ordering {
self.time.cmp(&other.time).reverse()
}
}