Add refreshing field to LayoutContext

Max Brunsfeld and Nathan Sobo created

Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

gpui/src/app.rs           |  5 +++--
gpui/src/elements/list.rs | 10 +++++-----
gpui/src/presenter.rs     | 10 +++++++---
3 files changed, 15 insertions(+), 10 deletions(-)

Detailed changes

gpui/src/app.rs 🔗

@@ -1431,7 +1431,8 @@ impl MutableAppContext {
                 {
                     let mut presenter = presenter.borrow_mut();
                     presenter.invalidate(invalidation, self);
-                    let scene = presenter.build_scene(window.size(), window.scale_factor(), self);
+                    let scene =
+                        presenter.build_scene(window.size(), window.scale_factor(), false, self);
                     window.present_scene(scene);
                 }
                 self.presenters_and_platform_windows
@@ -1461,7 +1462,7 @@ impl MutableAppContext {
                 .take();
             let mut presenter = presenter.borrow_mut();
             presenter.refresh(invalidation, self);
-            let scene = presenter.build_scene(window.size(), window.scale_factor(), self);
+            let scene = presenter.build_scene(window.size(), window.scale_factor(), true, self);
             window.present_scene(scene);
         }
         self.presenters_and_platform_windows = presenters;

gpui/src/elements/list.rs 🔗

@@ -98,7 +98,7 @@ impl Element for List {
         item_constraint.min.set_y(0.);
         item_constraint.max.set_y(f32::INFINITY);
 
-        if state.last_layout_width != Some(size.x()) {
+        if cx.refreshing || state.last_layout_width != Some(size.x()) {
             state.rendered_range = 0..0;
             state.items = SumTree::from_iter(
                 (0..state.items.summary().count).map(|_| ListItem::Unrendered),
@@ -578,7 +578,7 @@ mod tests {
         });
 
         let mut list = List::new(state.clone());
-        let (size, _) = list.layout(constraint, &mut presenter.build_layout_context(cx));
+        let (size, _) = list.layout(constraint, &mut presenter.build_layout_context(false, cx));
         assert_eq!(size, vec2f(100., 40.));
         assert_eq!(
             state.0.borrow().items.summary(),
@@ -601,7 +601,7 @@ mod tests {
             &mut presenter.build_event_context(cx),
         );
         let (_, logical_scroll_top) =
-            list.layout(constraint, &mut presenter.build_layout_context(cx));
+            list.layout(constraint, &mut presenter.build_layout_context(false, cx));
         assert_eq!(
             logical_scroll_top,
             ListOffset {
@@ -626,7 +626,7 @@ mod tests {
         );
 
         let (size, logical_scroll_top) =
-            list.layout(constraint, &mut presenter.build_layout_context(cx));
+            list.layout(constraint, &mut presenter.build_layout_context(false, cx));
         assert_eq!(size, vec2f(100., 40.));
         assert_eq!(
             state.0.borrow().items.summary(),
@@ -738,7 +738,7 @@ mod tests {
             let mut list = List::new(state.clone());
             let (size, logical_scroll_top) = list.layout(
                 SizeConstraint::new(vec2f(0., 0.), vec2f(width, height)),
-                &mut presenter.build_layout_context(cx),
+                &mut presenter.build_layout_context(false, cx),
             );
             assert_eq!(size, vec2f(width, height));
             last_logical_scroll_top = Some(logical_scroll_top);

gpui/src/presenter.rs 🔗

@@ -97,12 +97,13 @@ impl Presenter {
         &mut self,
         window_size: Vector2F,
         scale_factor: f32,
+        refreshing: bool,
         cx: &mut MutableAppContext,
     ) -> Scene {
         let mut scene = Scene::new(scale_factor);
 
         if let Some(root_view_id) = cx.root_view_id(self.window_id) {
-            self.layout(window_size, cx);
+            self.layout(window_size, refreshing, cx);
             let mut paint_cx = PaintContext {
                 scene: &mut scene,
                 font_cache: &self.font_cache,
@@ -123,20 +124,22 @@ impl Presenter {
         scene
     }
 
-    fn layout(&mut self, size: Vector2F, cx: &mut MutableAppContext) {
+    fn layout(&mut self, size: Vector2F, refreshing: bool, cx: &mut MutableAppContext) {
         if let Some(root_view_id) = cx.root_view_id(self.window_id) {
-            self.build_layout_context(cx)
+            self.build_layout_context(refreshing, cx)
                 .layout(root_view_id, SizeConstraint::strict(size));
         }
     }
 
     pub fn build_layout_context<'a>(
         &'a mut self,
+        refreshing: bool,
         cx: &'a mut MutableAppContext,
     ) -> LayoutContext<'a> {
         LayoutContext {
             rendered_views: &mut self.rendered_views,
             parents: &mut self.parents,
+            refreshing,
             font_cache: &self.font_cache,
             font_system: cx.platform().fonts(),
             text_layout_cache: &self.text_layout_cache,
@@ -213,6 +216,7 @@ pub struct LayoutContext<'a> {
     rendered_views: &'a mut HashMap<usize, ElementBox>,
     parents: &'a mut HashMap<usize, usize>,
     view_stack: Vec<usize>,
+    pub refreshing: bool,
     pub font_cache: &'a Arc<FontCache>,
     pub font_system: Arc<dyn FontSystem>,
     pub text_layout_cache: &'a TextLayoutCache,