Add new helper methods to Context<Entity<T>> and rename views to entity

Anthony created

I added two helper methods called `subscribe_new` and
`subscribe_new_in`, both make it easier to create event handlers
whenever a new Entity<T> 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.

Change summary

crates/gpui/src/app/context.rs | 94 ++++++++++++++++++++++++++++++++---
1 file changed, 86 insertions(+), 8 deletions(-)

Detailed changes

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<T2, Evt>(
+        &mut self,
+        mut on_event: impl Fn(&mut T, &Entity<T2>, &Evt, &mut Window, &mut Context<T>) + 'static,
+    ) -> Subscription
+    where
+        T: 'static,
+        T2: 'static + EventEmitter<Evt>,
+        Evt: 'static,
+    {
+        let this = self.weak_entity();
+        let on_event = Rc::new(on_event);
+
+        self.app.observe_new::<T2>(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<T2, Evt>(
+        &mut self,
+        mut on_event: impl Fn(&mut T, Entity<T2>, &Evt, &mut Context<T>) + 'static,
+    ) -> Subscription
+    where
+        T: 'static,
+        T2: 'static + EventEmitter<Evt>,
+        Evt: 'static,
+    {
+        let this = self.weak_entity();
+        let on_event = Rc::new(on_event);
+
+        self.app.observe_new::<T2>(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<T2, Evt>(
         &mut self,
@@ -253,9 +328,11 @@ impl<'a, T: 'static> Context<'a, T> {
         &self,
         f: impl Fn(&mut T, &E, &mut Window, &mut Context<T>) + '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<T>) -> 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<T>) + '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))
         });
     }