//! signal handling for UI events use std::any::{Any, TypeId}; use hashbrown::HashMap; use nohash_hasher::BuildNoHashHasher; pub mod trigger; /// A marker trait for UI Signals pub trait Signal: Any {} // #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Default)] // pub(crate) struct DummySignal; // impl UiSignal for DummySignal {} /// Internal storage for signals pub struct SignalStore { //TODO use a multithreaded queue instead, to allow easily offloading ui processing to a different thread ///XXX: is this truly the most efficient structure? sig: HashMap>, BuildNoHashHasher> } impl SignalStore { /// Create a new [`SigIntStore`] pub(crate) fn new() -> Self { Self { sig: Default::default(), } } /// Ensure that store for given signal type exists and return a mutable reference to it fn internal_store(&mut self) -> &mut Vec> { let type_id = TypeId::of::(); self.sig.entry(type_id).or_default() } /// Add a signal to the store /// /// Signals are stored in the order they are added pub fn add(&mut self, sig: T) { let type_id = TypeId::of::(); if let Some(v) = self.sig.get_mut(&type_id) { v.push(Box::new(sig)); } else { self.sig.insert(type_id, vec![Box::new(sig)]); } } /// Drain all signals of a given type pub(crate) fn drain(&mut self) -> impl Iterator + '_ { self.internal_store::() .drain(..) .map(|x| *x.downcast::().unwrap()) //unchecked? } /// Clear all signals pub(crate) fn clear(&mut self) { //XXX: should we clear the vecs instead? self.sig.clear(); } } // pub trait Signal { // type Arg; // type Output; // fn call(&self, arg: Self::Arg) -> Self::Output; // } // impl T, T> Signal for F { // type Arg = (); // type Output = T; // fn call(&self, _: Self::Arg) -> Self::Output { // self() // } // } // // impl T, A, T> Signal for F { // // type Arg = A; // // type Output = T; // // fn call(&self, a: Self::Arg) -> Self::Output { // // self(a) // // } // // } // pub struct SignalTrigger(pub(crate) Box R + 'static>); // impl SignalTrigger { // pub fn new R + 'static>(f: F) -> Self { // Self(Box::new(f)) // } // pub fn call(&self, a: A) -> R { // (self.0)(a) // } // } // impl R + 'static> From for SignalTrigger { // fn from(f: T) -> Self { // Self(Box::new(f)) // } // }