Eliminate ElementStateContext trait

Nathan Sobo and Max Brunsfeld created

We now always have a RenderContext when rendering MouseEventHandlers or scrollable Flex columns/rows.

Co-Authored-By: Max Brunsfeld <maxbrunsfeld@gmail.com>

Change summary

crates/gpui/src/app.rs                          | 52 ++++++------------
crates/gpui/src/elements/flex.rs                | 10 +-
crates/gpui/src/elements/mouse_event_handler.rs | 10 +-
crates/gpui/src/presenter.rs                    | 14 +---
4 files changed, 32 insertions(+), 54 deletions(-)

Detailed changes

crates/gpui/src/app.rs 🔗

@@ -127,26 +127,6 @@ pub trait UpdateView {
         T: View;
 }
 
-pub trait ElementStateContext: DerefMut<Target = MutableAppContext> {
-    fn current_view_id(&self) -> usize;
-
-    fn element_state<Tag: 'static, T: 'static + Default>(
-        &mut self,
-        element_id: usize,
-    ) -> ElementStateHandle<T> {
-        let id = ElementStateId {
-            view_id: self.current_view_id(),
-            element_id,
-            tag: TypeId::of::<Tag>(),
-        };
-        self.cx
-            .element_states
-            .entry(id)
-            .or_insert_with(|| Box::new(T::default()));
-        ElementStateHandle::new(id, self.frame_count, &self.cx.ref_counts)
-    }
-}
-
 pub struct Menu<'a> {
     pub name: &'a str,
     pub items: Vec<MenuItem<'a>>,
@@ -3444,7 +3424,7 @@ pub struct MouseState {
     pub clicked: bool,
 }
 
-impl<'a, T: View> RenderContext<'a, T> {
+impl<'a, V: View> RenderContext<'a, V> {
     fn new(params: RenderParams, app: &'a mut MutableAppContext) -> Self {
         Self {
             app,
@@ -3458,7 +3438,7 @@ impl<'a, T: View> RenderContext<'a, T> {
         }
     }
 
-    pub fn handle(&self) -> WeakViewHandle<T> {
+    pub fn handle(&self) -> WeakViewHandle<V> {
         WeakViewHandle::new(self.window_id, self.view_id)
     }
 
@@ -3477,6 +3457,22 @@ impl<'a, T: View> RenderContext<'a, T> {
             clicked: self.clicked_region_id == region_id,
         }
     }
+
+    pub fn element_state<Tag: 'static, T: 'static + Default>(
+        &mut self,
+        element_id: usize,
+    ) -> ElementStateHandle<T> {
+        let id = ElementStateId {
+            view_id: self.view_id(),
+            element_id,
+            tag: TypeId::of::<Tag>(),
+        };
+        self.cx
+            .element_states
+            .entry(id)
+            .or_insert_with(|| Box::new(T::default()));
+        ElementStateHandle::new(id, self.frame_count, &self.cx.ref_counts)
+    }
 }
 
 impl AsRef<AppContext> for &AppContext {
@@ -3521,12 +3517,6 @@ impl<V: View> ReadView for RenderContext<'_, V> {
     }
 }
 
-impl<V: View> ElementStateContext for RenderContext<'_, V> {
-    fn current_view_id(&self) -> usize {
-        self.view_id
-    }
-}
-
 impl<M> AsRef<AppContext> for ViewContext<'_, M> {
     fn as_ref(&self) -> &AppContext {
         &self.app.cx
@@ -3625,12 +3615,6 @@ impl<V: View> UpdateView for ViewContext<'_, V> {
     }
 }
 
-impl<V: View> ElementStateContext for ViewContext<'_, V> {
-    fn current_view_id(&self) -> usize {
-        self.view_id
-    }
-}
-
 pub trait Handle<T> {
     type Weak: 'static;
     fn id(&self) -> usize;

crates/gpui/src/elements/flex.rs 🔗

@@ -2,8 +2,8 @@ use std::{any::Any, f32::INFINITY};
 
 use crate::{
     json::{self, ToJson, Value},
-    Axis, DebugContext, Element, ElementBox, ElementStateContext, ElementStateHandle, Event,
-    EventContext, LayoutContext, PaintContext, SizeConstraint, Vector2FExt,
+    Axis, DebugContext, Element, ElementBox, ElementStateHandle, Event, EventContext,
+    LayoutContext, PaintContext, RenderContext, SizeConstraint, Vector2FExt, View,
 };
 use pathfinder_geometry::{
     rect::RectF,
@@ -40,15 +40,15 @@ impl Flex {
         Self::new(Axis::Vertical)
     }
 
-    pub fn scrollable<Tag, C>(
+    pub fn scrollable<Tag, V>(
         mut self,
         element_id: usize,
         scroll_to: Option<usize>,
-        cx: &mut C,
+        cx: &mut RenderContext<V>,
     ) -> Self
     where
         Tag: 'static,
-        C: ElementStateContext,
+        V: View,
     {
         let scroll_state = cx.element_state::<Tag, ScrollState>(element_id);
         scroll_state.update(cx, |scroll_state, _| scroll_state.scroll_to = scroll_to);

crates/gpui/src/elements/mouse_event_handler.rs 🔗

@@ -6,8 +6,8 @@ use crate::{
     },
     platform::CursorStyle,
     scene::CursorRegion,
-    DebugContext, Element, ElementBox, ElementStateContext, ElementStateHandle, Event,
-    EventContext, LayoutContext, PaintContext, SizeConstraint,
+    DebugContext, Element, ElementBox, ElementStateHandle, Event, EventContext, LayoutContext,
+    PaintContext, RenderContext, SizeConstraint, View,
 };
 use serde_json::json;
 
@@ -29,11 +29,11 @@ pub struct MouseState {
 }
 
 impl MouseEventHandler {
-    pub fn new<Tag, C, F>(id: usize, cx: &mut C, render_child: F) -> Self
+    pub fn new<Tag, V, F>(id: usize, cx: &mut RenderContext<V>, render_child: F) -> Self
     where
         Tag: 'static,
-        C: ElementStateContext,
-        F: FnOnce(&MouseState, &mut C) -> ElementBox,
+        V: View,
+        F: FnOnce(&MouseState, &mut RenderContext<V>) -> ElementBox,
     {
         let state_handle = cx.element_state::<Tag, _>(id);
         let child = state_handle.update(cx, |state, cx| render_child(state, cx));

crates/gpui/src/presenter.rs 🔗

@@ -7,10 +7,10 @@ use crate::{
     platform::{CursorStyle, Event},
     scene::CursorRegion,
     text_layout::TextLayoutCache,
-    Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox,
-    ElementStateContext, Entity, FontSystem, ModelHandle, MouseRegion, MouseRegionId, ReadModel,
-    ReadView, RenderContext, RenderParams, Scene, UpgradeModelHandle, UpgradeViewHandle, View,
-    ViewHandle, WeakModelHandle, WeakViewHandle,
+    Action, AnyModelHandle, AnyViewHandle, AnyWeakModelHandle, AssetCache, ElementBox, Entity,
+    FontSystem, ModelHandle, MouseRegion, MouseRegionId, ReadModel, ReadView, RenderContext,
+    RenderParams, Scene, UpgradeModelHandle, UpgradeViewHandle, View, ViewHandle, WeakModelHandle,
+    WeakViewHandle,
 };
 use pathfinder_geometry::vector::{vec2f, Vector2F};
 use serde_json::json;
@@ -444,12 +444,6 @@ impl<'a> UpgradeViewHandle for LayoutContext<'a> {
     }
 }
 
-impl<'a> ElementStateContext for LayoutContext<'a> {
-    fn current_view_id(&self) -> usize {
-        *self.view_stack.last().unwrap()
-    }
-}
-
 pub struct PaintContext<'a> {
     rendered_views: &'a mut HashMap<usize, ElementBox>,
     pub scene: &'a mut Scene,