Checkpoint

Nathan Sobo created

Change summary

crates/gpui3/src/elements/div.rs | 82 +++++++++++++++++----------------
crates/gpui3/src/window.rs       | 57 ++++++++++------------
2 files changed, 69 insertions(+), 70 deletions(-)

Detailed changes

crates/gpui3/src/elements/div.rs 🔗

@@ -23,7 +23,7 @@ pub fn div<S>() -> Div<S> {
     }
 }
 
-impl<S: 'static> Element for Div<S> {
+impl<S: 'static + Send + Sync> Element for Div<S> {
     type State = S;
     type FrameState = Vec<LayoutId>;
 
@@ -33,22 +33,16 @@ impl<S: 'static> Element for Div<S> {
         cx: &mut ViewContext<S>,
     ) -> Result<(LayoutId, Self::FrameState)> {
         let style = self.computed_style();
-        let pop_text_style = style
-            .text_style(cx)
-            .map(|style| cx.push_text_style(style.clone()))
-            .is_some();
-
-        let children = self
-            .children
-            .iter_mut()
-            .map(|child| child.layout(view, cx))
-            .collect::<Result<Vec<LayoutId>>>()?;
-
-        if pop_text_style {
-            cx.pop_text_style();
-        }
-
-        Ok((cx.request_layout(style.into(), children.clone())?, children))
+        let child_layout_ids = if let Some(text_style) = style.text_style(cx) {
+            cx.with_text_style(text_style.clone(), |cx| self.layout_children(view, cx))?
+        } else {
+            self.layout_children(view, cx)?
+        };
+
+        Ok((
+            cx.request_layout(style.into(), child_layout_ids.clone())?,
+            child_layout_ids,
+        ))
     }
 
     fn paint(
@@ -61,36 +55,25 @@ impl<S: 'static> Element for Div<S> {
         let Layout { order, bounds } = layout;
 
         let style = self.computed_style();
-        let pop_text_style = style
-            .text_style(cx)
-            .map(|style| cx.push_text_style(style.clone()))
-            .is_some();
         style.paint_background(bounds, cx);
-        // self.interaction_handlers().paint(order, bounds, cx);
-
-        // // TODO: Support only one dimension being hidden
-        // let mut pop_layer = false;
+        let overflow = &style.overflow;
+        // // todo!("support only one dimension being hidden")
         // if style.overflow.y != Overflow::Visible || style.overflow.x != Overflow::Visible {
         //     cx.scene().push_layer(Some(bounds));
         //     pop_layer = true;
         // }
-
-        let scroll_offset = self.scroll_offset(&style.overflow);
-        for child in &mut self.children {
-            child.paint(state, Some(scroll_offset), cx)?;
+        if let Some(text_style) = style.text_style(cx) {
+            cx.with_text_style(text_style.clone(), |cx| {
+                self.paint_children(overflow, state, cx)
+            })?;
+        } else {
+            self.paint_children(overflow, state, cx)?;
         }
-
-        // if pop_layer {
-        //     cx.scene().pop_layer();
-        // }
-
         style.paint_foreground(bounds, cx);
-        if pop_text_style {
-            cx.pop_text_style();
-        }
 
         self.handle_scroll(order, bounds, style.overflow.clone(), child_layouts, cx);
 
+        // todo!("enable inspector")
         // if cx.is_inspector_enabled() {
         //     self.paint_inspector(parent_origin, layout, cx);
         // }
@@ -99,7 +82,7 @@ impl<S: 'static> Element for Div<S> {
     }
 }
 
-impl<V: 'static> Div<V> {
+impl<S: 'static> Div<S> {
     pub fn overflow_hidden(mut self) -> Self {
         self.declared_style().overflow.x = Some(Overflow::Hidden);
         self.declared_style().overflow.y = Some(Overflow::Hidden);
@@ -147,13 +130,33 @@ impl<V: 'static> Div<V> {
         offset
     }
 
+    fn layout_children(&mut self, view: &mut S, cx: &mut ViewContext<S>) -> Result<Vec<LayoutId>> {
+        self.children
+            .iter_mut()
+            .map(|child| child.layout(view, cx))
+            .collect::<Result<Vec<LayoutId>>>()
+    }
+
+    fn paint_children(
+        &mut self,
+        overflow: &Point<Overflow>,
+        state: &mut S,
+        cx: &mut ViewContext<S>,
+    ) -> Result<()> {
+        let scroll_offset = self.scroll_offset(overflow);
+        for child in &mut self.children {
+            child.paint(state, Some(scroll_offset), cx)?;
+        }
+        Ok(())
+    }
+
     fn handle_scroll(
         &mut self,
         _order: u32,
         bounds: Bounds<Pixels>,
         overflow: Point<Overflow>,
         child_layout_ids: &[LayoutId],
-        cx: &mut ViewContext<V>,
+        cx: &mut ViewContext<S>,
     ) {
         if overflow.y == Overflow::Scroll || overflow.x == Overflow::Scroll {
             let mut scroll_max = Point::default();
@@ -244,6 +247,7 @@ impl<V: 'static> Div<V> {
     //     //     }
     //     // });
     // }
+    //
 }
 
 impl<V> Styled for Div<V> {

crates/gpui3/src/window.rs 🔗

@@ -158,14 +158,6 @@ impl<'a, 'w> WindowContext<'a, 'w> {
         self.window.rem_size
     }
 
-    pub fn push_text_style(&mut self, text_style: TextStyleRefinement) {
-        self.window.text_style_stack.push(text_style);
-    }
-
-    pub fn pop_text_style(&mut self) {
-        self.window.text_style_stack.pop();
-    }
-
     pub fn push_cascading_state<T: Send + Sync + 'static>(&mut self, theme: T) {
         self.window
             .state_stacks_by_type
@@ -239,15 +231,15 @@ impl Context for WindowContext<'_, '_> {
 }
 
 #[derive(Deref, DerefMut)]
-pub struct ViewContext<'a, 'w, T> {
+pub struct ViewContext<'a, 'w, S> {
     #[deref]
     #[deref_mut]
     window_cx: WindowContext<'a, 'w>,
-    entity_type: PhantomData<T>,
+    entity_type: PhantomData<S>,
     entity_id: EntityId,
 }
 
-impl<'a, 'w, T: Send + Sync + 'static> ViewContext<'a, 'w, T> {
+impl<'a, 'w, S: Send + Sync + 'static> ViewContext<'a, 'w, S> {
     fn mutable(app: &'a mut AppContext, window: &'w mut Window, entity_id: EntityId) -> Self {
         Self {
             window_cx: WindowContext::mutable(app, window),
@@ -256,32 +248,25 @@ impl<'a, 'w, T: Send + Sync + 'static> ViewContext<'a, 'w, T> {
         }
     }
 
-    // fn immutable(app: &'a AppContext, window: &'w Window, entity_id: EntityId) -> Self {
-    //     Self {
-    //         window_cx: WindowContext::immutable(app, window),
-    //         entity_id,
-    //         entity_type: PhantomData,
-    //     }
-    // }
-
-    pub fn erase_state<R>(&mut self, f: impl FnOnce(&mut ViewContext<()>) -> R) -> R {
-        let entity_id = self.unit_entity.id;
-        let mut cx = ViewContext::mutable(
-            &mut *self.window_cx.app,
-            &mut *self.window_cx.window,
-            entity_id,
-        );
-        f(&mut cx)
+    pub fn handle(&self) -> WeakHandle<S> {
+        self.entities.weak_handle(self.entity_id)
     }
 
-    pub fn handle(&self) -> WeakHandle<T> {
-        self.entities.weak_handle(self.entity_id)
+    pub fn with_text_style<R>(
+        &mut self,
+        style: TextStyleRefinement,
+        f: impl FnOnce(&mut Self) -> R,
+    ) -> R {
+        self.window.text_style_stack.push(style);
+        let result = f(self);
+        self.window.text_style_stack.pop();
+        result
     }
 
     pub fn observe<E: Send + Sync + 'static>(
         &mut self,
         handle: &Handle<E>,
-        on_notify: impl Fn(&mut T, Handle<E>, &mut ViewContext<'_, '_, T>) + Send + Sync + 'static,
+        on_notify: impl Fn(&mut S, Handle<E>, &mut ViewContext<'_, '_, S>) + Send + Sync + 'static,
     ) {
         let this = self.handle();
         let handle = handle.downgrade();
@@ -310,9 +295,19 @@ impl<'a, 'w, T: Send + Sync + 'static> ViewContext<'a, 'w, T> {
             .push_back(Effect::Notify(entity_id));
         self.window.dirty = true;
     }
+
+    pub(crate) fn erase_state<R>(&mut self, f: impl FnOnce(&mut ViewContext<()>) -> R) -> R {
+        let entity_id = self.unit_entity.id;
+        let mut cx = ViewContext::mutable(
+            &mut *self.window_cx.app,
+            &mut *self.window_cx.window,
+            entity_id,
+        );
+        f(&mut cx)
+    }
 }
 
-impl<'a, 'w, T: 'static> Context for ViewContext<'a, 'w, T> {
+impl<'a, 'w, S: 'static> Context for ViewContext<'a, 'w, S> {
     type EntityContext<'b, 'c, U: Send + Sync + 'static> = ViewContext<'b, 'c, U>;
     type Result<U> = U;