Introduce gpui::render_view

Antonio Scandurra created

Change summary

crates/editor2/src/editor.rs | 13 +++--
crates/gpui2/src/style.rs    |  4 
crates/gpui2/src/view.rs     | 82 +++++++++++++++++++++++++++++++++++++
3 files changed, 89 insertions(+), 10 deletions(-)

Detailed changes

crates/editor2/src/editor.rs 🔗

@@ -39,9 +39,9 @@ use futures::FutureExt;
 use fuzzy::{StringMatch, StringMatchCandidate};
 use git::diff_hunk_to_display;
 use gpui::{
-    action, actions, div, point, px, relative, rems, size, uniform_list, AnyElement, AppContext,
-    AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Component, Context, Entity,
-    EventEmitter, FocusHandle, FontFeatures, FontStyle, FontWeight, HighlightStyle, Hsla,
+    action, actions, div, point, px, relative, rems, render_view, size, uniform_list, AnyElement,
+    AppContext, AsyncWindowContext, BackgroundExecutor, Bounds, ClipboardItem, Component, Context,
+    Entity, EventEmitter, FocusHandle, FontFeatures, FontStyle, FontWeight, HighlightStyle, Hsla,
     InputHandler, KeyContext, Model, MouseButton, ParentElement, Pixels, Render,
     StatefulInteractive, StatelessInteractive, Styled, Subscription, Task, TextStyle,
     UniformListScrollHandle, View, ViewContext, VisualContext, WeakView, WindowContext,
@@ -7806,7 +7806,8 @@ impl Editor {
                                     }
                                     div()
                                         .pl(cx.anchor_x)
-                                        .child(with_view(&rename_editor, |_, _| {
+                                        .child(render_view(
+                                            &rename_editor,
                                             EditorElement::new(EditorStyle {
                                                 background: cx.theme().system().transparent,
                                                 local_player: cx.editor_style.local_player,
@@ -7817,8 +7818,8 @@ impl Editor {
                                                     .editor_style
                                                     .diagnostic_style
                                                     .clone(),
-                                            })
-                                        }))
+                                            }),
+                                        ))
                                         .render()
                                 }
                             }),

crates/gpui2/src/style.rs 🔗

@@ -1,8 +1,8 @@
 use crate::{
     black, phi, point, rems, AbsoluteLength, BorrowAppContext, BorrowWindow, Bounds, ContentMask,
     Corners, CornersRefinement, CursorStyle, DefiniteLength, Edges, EdgesRefinement, Font,
-    FontFeatures, FontStyle, FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Result,
-    Rgba, SharedString, Size, SizeRefinement, Styled, TextRun, ViewContext, WindowContext,
+    FontFeatures, FontStyle, FontWeight, Hsla, Length, Pixels, Point, PointRefinement, Rgba,
+    SharedString, Size, SizeRefinement, Styled, TextRun, ViewContext, WindowContext,
 };
 use refineable::{Cascade, Refineable};
 use smallvec::SmallVec;

crates/gpui2/src/view.rs 🔗

@@ -1,7 +1,7 @@
 use crate::{
     private::Sealed, AnyBox, AnyElement, AnyModel, AnyWeakModel, AppContext, AvailableSpace,
-    Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, LayoutId, Model, Pixels,
-    Size, ViewContext, VisualContext, WeakModel, WindowContext,
+    BorrowWindow, Bounds, Component, Element, ElementId, Entity, EntityId, Flatten, LayoutId,
+    Model, Pixels, Size, ViewContext, VisualContext, WeakModel, WindowContext,
 };
 use anyhow::{Context, Result};
 use std::{
@@ -281,6 +281,84 @@ where
     }
 }
 
+pub struct RenderView<C, V> {
+    view: View<V>,
+    component: Option<C>,
+}
+
+impl<C, ParentViewState, ViewState> Component<ParentViewState> for RenderView<C, ViewState>
+where
+    C: 'static + Component<ViewState>,
+    ParentViewState: 'static,
+    ViewState: 'static,
+{
+    fn render(self) -> AnyElement<ParentViewState> {
+        AnyElement::new(self)
+    }
+}
+
+impl<C, ParentViewState, ViewState> Element<ParentViewState> for RenderView<C, ViewState>
+where
+    C: 'static + Component<ViewState>,
+    ParentViewState: 'static,
+    ViewState: 'static,
+{
+    type ElementState = AnyElement<ViewState>;
+
+    fn id(&self) -> Option<ElementId> {
+        Some(self.view.entity_id().into())
+    }
+
+    fn initialize(
+        &mut self,
+        _: &mut ParentViewState,
+        _: Option<Self::ElementState>,
+        cx: &mut ViewContext<ParentViewState>,
+    ) -> Self::ElementState {
+        cx.with_element_id(self.view.entity_id(), |_, cx| {
+            self.view.update(cx, |view, cx| {
+                let mut element = self.component.take().unwrap().render();
+                element.initialize(view, cx);
+                element
+            })
+        })
+    }
+
+    fn layout(
+        &mut self,
+        _: &mut ParentViewState,
+        element: &mut Self::ElementState,
+        cx: &mut ViewContext<ParentViewState>,
+    ) -> LayoutId {
+        cx.with_element_id(self.view.entity_id(), |_, cx| {
+            self.view.update(cx, |view, cx| element.layout(view, cx))
+        })
+    }
+
+    fn paint(
+        &mut self,
+        _: Bounds<Pixels>,
+        _: &mut ParentViewState,
+        element: &mut Self::ElementState,
+        cx: &mut ViewContext<ParentViewState>,
+    ) {
+        cx.with_element_id(self.view.entity_id(), |_, cx| {
+            self.view.update(cx, |view, cx| element.paint(view, cx))
+        })
+    }
+}
+
+pub fn render_view<C, V>(view: &View<V>, component: C) -> RenderView<C, V>
+where
+    C: 'static + Component<V>,
+    V: 'static,
+{
+    RenderView {
+        view: view.clone(),
+        component: Some(component),
+    }
+}
+
 mod any_view {
     use crate::{AnyElement, AnyView, BorrowWindow, LayoutId, Render, WindowContext};
     use std::any::Any;