From d40b4ce5dd30c981ce9d82632eafea0c35e10bd9 Mon Sep 17 00:00:00 2001 From: Anthony Date: Wed, 22 Oct 2025 21:52:14 -0400 Subject: [PATCH] Add new helper methods to Context> and rename views to entity I added two helper methods called `subscribe_new` and `subscribe_new_in`, both make it easier to create event handlers whenever a new Entity is created. Similar to `observe_new`. I also renamed some variable names from `view` to `entity` to be more inline with gpui3. The view name seems to be an artifact from gpui2. --- crates/gpui/src/app/context.rs | 94 +++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 8 deletions(-) diff --git a/crates/gpui/src/app/context.rs b/crates/gpui/src/app/context.rs index 41d6cac82b7c179040d61ddfd22b003c143a5fb9..8b10160ebb3b7838015c5c1983360441a5e3875b 100644 --- a/crates/gpui/src/app/context.rs +++ b/crates/gpui/src/app/context.rs @@ -10,6 +10,7 @@ use std::{ borrow::{Borrow, BorrowMut}, future::Future, ops, + rc::Rc, sync::Arc, }; use util::Deferred; @@ -94,6 +95,80 @@ impl<'a, T: 'static> Context<'a, T> { }) } + /// Subscribe to an event type of another entity whenever a new entity of that type is created + pub fn subscribe_in_new( + &mut self, + mut on_event: impl Fn(&mut T, &Entity, &Evt, &mut Window, &mut Context) + 'static, + ) -> Subscription + where + T: 'static, + T2: 'static + EventEmitter, + Evt: 'static, + { + let this = self.weak_entity(); + let on_event = Rc::new(on_event); + + self.app.observe_new::(move |_, window, cx| { + let handle = window.map(|window| window.handle); + + cx.app + .subscribe_internal(&cx.entity(), { + let this = this.clone(); + let on_event = on_event.clone(); + let handle = handle.clone(); + + move |e, event, cx| { + if let Some(this) = this.upgrade() + && let Some(window) = handle + { + window + .update(cx, |_, window, cx| { + this.update(cx, |this, cx| { + on_event(this, &e, event, window, cx) + }); + }) + .is_ok() + } else { + false + } + } + }) + .detach(); + }) + } + + /// Subscribe to an event type of another entity whenever a new entity of that type is created + pub fn subscribe_new( + &mut self, + mut on_event: impl Fn(&mut T, Entity, &Evt, &mut Context) + 'static, + ) -> Subscription + where + T: 'static, + T2: 'static + EventEmitter, + Evt: 'static, + { + let this = self.weak_entity(); + let on_event = Rc::new(on_event); + + self.app.observe_new::(move |_, _, cx| { + cx.app + .subscribe_internal(&cx.entity(), { + let this = this.clone(); + let on_event = on_event.clone(); + + move |e, event, cx| { + if let Some(this) = this.upgrade() { + this.update(cx, |this, cx| on_event(this, e, event, cx)); + true + } else { + false + } + } + }) + .detach(); + }) + } + /// Subscribe to an event type from another entity pub fn subscribe( &mut self, @@ -253,9 +328,11 @@ impl<'a, T: 'static> Context<'a, T> { &self, f: impl Fn(&mut T, &E, &mut Window, &mut Context) + 'static, ) -> impl Fn(&E, &mut Window, &mut App) + 'static { - let view = self.entity().downgrade(); + let entity = self.entity().downgrade(); move |e: &E, window: &mut Window, cx: &mut App| { - view.update(cx, |view, cx| f(view, e, window, cx)).ok(); + entity + .update(cx, |entity, cx| f(entity, e, window, cx)) + .ok(); } } @@ -265,9 +342,9 @@ impl<'a, T: 'static> Context<'a, T> { &self, f: impl Fn(&mut T, E, &mut Window, &mut Context) -> R + 'static, ) -> impl Fn(E, &mut Window, &mut App) -> R + 'static { - let view = self.entity(); + let entity = self.entity(); move |e: E, window: &mut Window, cx: &mut App| { - view.update(cx, |view, cx| f(view, e, window, cx)) + entity.update(cx, |entity, cx| f(entity, e, window, cx)) } } @@ -296,8 +373,9 @@ impl<'a, T: 'static> Context<'a, T> { ) where T: 'static, { - let view = self.entity(); - window.on_next_frame(move |window, cx| view.update(cx, |view, cx| f(view, window, cx))); + let entity = self.entity(); + window + .on_next_frame(move |window, cx| entity.update(cx, |entity, cx| f(entity, window, cx))); } /// Schedules the given function to be run at the end of the current effect cycle, allowing entities @@ -307,9 +385,9 @@ impl<'a, T: 'static> Context<'a, T> { window: &Window, f: impl FnOnce(&mut T, &mut Window, &mut Context) + 'static, ) { - let view = self.entity(); + let entity = self.entity(); window.defer(self, move |window, cx| { - view.update(cx, |view, cx| f(view, window, cx)) + entity.update(cx, |entity, cx| f(entity, window, cx)) }); }