Checkpoint

Nathan Sobo created

Change summary

crates/gpui/src/geometry.rs          |  9 ++++
crates/gpui2/src/elements/text.rs    | 14 ++++++-
crates/gpui2/src/gpui2.rs            |  1 
crates/gpui2/src/view_context.rs     | 37 ++++++++++++++++++
crates/gpui2/src/view_handle.rs      | 60 ++++++++++++++++++++++++++++++
crates/storybook/src/collab_panel.rs |  4 +-
6 files changed, 120 insertions(+), 5 deletions(-)

Detailed changes

crates/gpui/src/geometry.rs 🔗

@@ -167,6 +167,15 @@ pub struct Size<T: Clone + Default + Debug> {
     pub height: T,
 }
 
+impl Size<Length> {
+    pub fn full() -> Self {
+        Self {
+            width: relative(1.),
+            height: relative(1.),
+        }
+    }
+}
+
 impl<S, T: Clone + Default + Debug> From<taffy::geometry::Size<S>> for Size<T>
 where
     S: Into<T>,

crates/gpui2/src/elements/text.rs 🔗

@@ -12,11 +12,21 @@ use parking_lot::Mutex;
 use std::sync::Arc;
 use util::arc_cow::ArcCow;
 
-impl<V: 'static, S: Into<ArcCow<'static, str>>> IntoElement<V> for S {
+impl<V: 'static> IntoElement<V> for ArcCow<'static, str> {
     type Element = Text;
 
     fn into_element(self) -> Self::Element {
-        Text { text: self.into() }
+        Text { text: self }
+    }
+}
+
+impl<V: 'static> IntoElement<V> for &'static str {
+    type Element = Text;
+
+    fn into_element(self) -> Self::Element {
+        Text {
+            text: ArcCow::from(self),
+        }
     }
 }
 

crates/gpui2/src/gpui2.rs 🔗

@@ -6,6 +6,7 @@ pub mod interactive;
 pub mod style;
 pub mod view;
 pub mod view_context;
+pub mod view_handle;
 
 pub use color::*;
 pub use element::{AnyElement, Element, IntoElement, Layout, ParentElement};

crates/gpui2/src/view_context.rs 🔗

@@ -3,7 +3,10 @@ use std::{any::TypeId, rc::Rc};
 use crate::{element::LayoutId, style::Style};
 use anyhow::{anyhow, Result};
 use derive_more::{Deref, DerefMut};
-use gpui::{geometry::Size, scene::EventHandler, EventContext, Layout, MeasureParams};
+use gpui::{
+    geometry::Size, scene::EventHandler, AnyWindowHandle, BorrowWindowContext, EventContext,
+    Layout, MeasureParams, WindowContext,
+};
 pub use gpui::{taffy::tree::NodeId, ViewContext as LegacyViewContext};
 
 #[derive(Deref, DerefMut)]
@@ -77,3 +80,35 @@ impl<'a, 'b, 'c, V: 'static> ViewContext<'a, 'b, 'c, V> {
             .computed_layout(layout_id)
     }
 }
+
+impl<'a, 'b, 'c, V: 'static> BorrowWindowContext for ViewContext<'a, 'b, 'c, V> {
+    type Result<T> = T;
+
+    fn read_window<T, F>(&self, window: AnyWindowHandle, f: F) -> Self::Result<T>
+    where
+        F: FnOnce(&WindowContext) -> T,
+    {
+        self.legacy_cx.read_window(window, f)
+    }
+
+    fn read_window_optional<T, F>(&self, window: AnyWindowHandle, f: F) -> Option<T>
+    where
+        F: FnOnce(&WindowContext) -> Option<T>,
+    {
+        self.legacy_cx.read_window_optional(window, f)
+    }
+
+    fn update_window<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Self::Result<T>
+    where
+        F: FnOnce(&mut WindowContext) -> T,
+    {
+        self.legacy_cx.update_window(window, f)
+    }
+
+    fn update_window_optional<T, F>(&mut self, window: AnyWindowHandle, f: F) -> Option<T>
+    where
+        F: FnOnce(&mut WindowContext) -> Option<T>,
+    {
+        self.legacy_cx.update_window_optional(window, f)
+    }
+}

crates/gpui2/src/view_handle.rs 🔗

@@ -0,0 +1,60 @@
+use crate::{style::Style, Element, IntoElement, ViewContext};
+use gpui::{
+    geometry::{Point, Size},
+    taffy::style::Overflow,
+    AnyElement, View, ViewHandle,
+};
+
+impl<ParentView: 'static, ChildView: View> Element<ParentView> for ViewHandle<ChildView> {
+    type PaintState = AnyElement<ChildView>;
+
+    fn layout(
+        &mut self,
+        _: &mut ParentView,
+        cx: &mut ViewContext<ParentView>,
+    ) -> anyhow::Result<(gpui::LayoutId, Self::PaintState)>
+    where
+        Self: Sized,
+    {
+        let layout_id = cx.add_layout_node(
+            Style {
+                overflow: Point {
+                    x: Overflow::Hidden,
+                    y: Overflow::Hidden,
+                },
+                size: Size::full(),
+                ..Default::default()
+            },
+            None,
+        )?;
+        let element = self.update(cx, |view, cx| view.render(cx));
+        Ok((layout_id, element))
+    }
+
+    fn paint(
+        &mut self,
+        _: &mut ParentView,
+        parent_origin: gpui::geometry::vector::Vector2F,
+        layout: &gpui::Layout,
+        element: &mut AnyElement<ChildView>,
+        cx: &mut ViewContext<ParentView>,
+    ) where
+        Self: Sized,
+    {
+        self.update(cx, |view, cx| {
+            let bounds = layout.bounds + parent_origin;
+            element.layout(gpui::SizeConstraint::strict(bounds.size()), view, cx);
+            cx.paint_layer(Some(layout.bounds), |cx| {
+                element.paint(bounds.origin(), bounds, view, cx);
+            });
+        })
+    }
+}
+
+impl<ParentView: 'static, ChildView: View> IntoElement<ParentView> for ViewHandle<ChildView> {
+    type Element = Self;
+
+    fn into_element(self) -> Self::Element {
+        self
+    }
+}

crates/storybook/src/collab_panel.rs 🔗

@@ -117,7 +117,7 @@ impl<V: 'static> CollabPanelElement<V> {
 
     fn list_section_header(
         &self,
-        label: impl Into<ArcCow<'static, str>>,
+        label: impl IntoElement<V>,
         expanded: bool,
         theme: &Theme,
     ) -> impl Element<V> {
@@ -146,7 +146,7 @@ impl<V: 'static> CollabPanelElement<V> {
     fn list_item(
         &self,
         avatar_uri: impl Into<ArcCow<'static, str>>,
-        label: impl Into<ArcCow<'static, str>>,
+        label: impl IntoElement<V>,
         theme: &Theme,
     ) -> impl Element<V> {
         div()