First pass at allowing multiple event types to be emitted by an entity

This commit is contained in:
Mikayla 2023-11-08 16:34:38 -08:00
parent c81440424b
commit 26fc36ee0e
No known key found for this signature in database
6 changed files with 123 additions and 74 deletions

View file

@ -201,7 +201,8 @@ pub struct AppContext {
pub(crate) pending_notifications: HashSet<EntityId>,
pub(crate) pending_global_notifications: HashSet<TypeId>,
pub(crate) observers: SubscriberSet<EntityId, Handler>,
pub(crate) event_listeners: SubscriberSet<EntityId, Listener>,
// (Entity, Event Type)
pub(crate) event_listeners: SubscriberSet<EntityId, (TypeId, Listener)>,
pub(crate) release_listeners: SubscriberSet<EntityId, ReleaseListener>,
pub(crate) global_observers: SubscriberSet<TypeId, Handler>,
pub(crate) quit_observers: SubscriberSet<(), QuitHandler>,
@ -351,14 +352,15 @@ impl AppContext {
)
}
pub fn subscribe<T, E>(
pub fn subscribe<T, E, Evt>(
&mut self,
entity: &E,
mut on_event: impl FnMut(E, &T::Event, &mut AppContext) + 'static,
mut on_event: impl FnMut(E, &Evt, &mut AppContext) + 'static,
) -> Subscription
where
T: 'static + EventEmitter,
T: 'static + EventEmitter<Evt>,
E: Entity<T>,
Evt: 'static,
{
self.subscribe_internal(entity, move |entity, event, cx| {
on_event(entity, event, cx);
@ -366,27 +368,32 @@ impl AppContext {
})
}
pub(crate) fn subscribe_internal<T, E>(
pub(crate) fn subscribe_internal<T, E, Evt>(
&mut self,
entity: &E,
mut on_event: impl FnMut(E, &T::Event, &mut AppContext) -> bool + 'static,
mut on_event: impl FnMut(E, &Evt, &mut AppContext) -> bool + 'static,
) -> Subscription
where
T: 'static + EventEmitter,
T: 'static + EventEmitter<Evt>,
E: Entity<T>,
Evt: 'static,
{
let entity_id = entity.entity_id();
let entity = entity.downgrade();
self.event_listeners.insert(
entity_id,
Box::new(move |event, cx| {
let event: &T::Event = event.downcast_ref().expect("invalid event type");
if let Some(handle) = E::upgrade_from(&entity) {
on_event(handle, event, cx)
} else {
false
}
}),
(
TypeId::of::<Evt>(),
Box::new(move |event, cx| {
let event: &Evt = event.downcast_ref().expect("invalid event type");
if let Some(handle) = E::upgrade_from(&entity) {
on_event(handle, event, cx)
} else {
false
}
}),
),
)
}
@ -509,7 +516,11 @@ impl AppContext {
Effect::Notify { emitter } => {
self.apply_notify_effect(emitter);
}
Effect::Emit { emitter, event } => self.apply_emit_effect(emitter, event),
Effect::Emit {
emitter,
event_type,
event,
} => self.apply_emit_effect(emitter, event_type, event),
Effect::FocusChanged {
window_handle,
focused,
@ -604,10 +615,16 @@ impl AppContext {
.retain(&emitter, |handler| handler(self));
}
fn apply_emit_effect(&mut self, emitter: EntityId, event: Box<dyn Any>) {
fn apply_emit_effect(&mut self, emitter: EntityId, event_type: TypeId, event: Box<dyn Any>) {
self.event_listeners
.clone()
.retain(&emitter, |handler| handler(event.as_ref(), self));
.retain(&emitter, |(stored_type, handler)| {
if *stored_type == event_type {
handler(event.as_ref(), self)
} else {
true
}
});
}
fn apply_focus_changed_effect(
@ -978,6 +995,7 @@ pub(crate) enum Effect {
},
Emit {
emitter: EntityId,
event_type: TypeId,
event: Box<dyn Any>,
},
FocusChanged {