diff --git a/gpui/src/elements/list.rs b/gpui/src/elements/list.rs index de9b492797e92c9ccfba2b5183cef27396a20475..d0163468b1fd875f715c0367d58fafbe3ebb7e42 100644 --- a/gpui/src/elements/list.rs +++ b/gpui/src/elements/list.rs @@ -261,6 +261,15 @@ impl ListState { pub fn splice(&self, old_range: Range, count: usize) { let state = &mut *self.0.borrow_mut(); + if let Some((ix, offset)) = state.scroll_top.as_mut() { + if old_range.contains(ix) { + *ix = old_range.start; + *offset = 0.; + } else if old_range.end <= *ix { + *ix = *ix - (old_range.end - old_range.start) + count; + } + } + let mut old_heights = state.heights.cursor::(); let mut new_heights = old_heights.slice(&Count(old_range.start), Bias::Right, &()); old_heights.seek_forward(&Count(old_range.end), Bias::Right, &()); @@ -439,7 +448,7 @@ mod tests { fn test_layout(cx: &mut crate::MutableAppContext) { let mut presenter = cx.build_presenter(0, 0.); - let mut elements = vec![20., 30., 10.]; + let mut elements = vec![20., 30., 100.]; let state = ListState::new(elements.len(), Orientation::Top); let mut list = List::new( @@ -458,10 +467,20 @@ mod tests { ElementHeightSummary { count: 3, pending_count: 0, - height: 60. + height: 150. } ); + state.0.borrow_mut().scroll( + Default::default(), + vec2f(0., 54.), + true, + size.y(), + &mut presenter.build_event_context(cx), + ); + assert_eq!(state.0.borrow().scroll_top, Some((2, 4.))); + assert_eq!(state.0.borrow().scroll_top(size.y()), 54.); + elements.splice(1..2, vec![40., 50.]); elements.push(60.); state.splice(1..2, 2); @@ -471,7 +490,7 @@ mod tests { ElementHeightSummary { count: 5, pending_count: 3, - height: 30. + height: 120. } ); @@ -491,9 +510,11 @@ mod tests { ElementHeightSummary { count: 5, pending_count: 0, - height: 180. + height: 270. } ); + assert_eq!(state.0.borrow().scroll_top, Some((3, 4.))); + assert_eq!(state.0.borrow().scroll_top(size.y()), 114.); } fn item(height: f32) -> ElementBox { diff --git a/gpui/src/presenter.rs b/gpui/src/presenter.rs index 31c91688dbc4957299a5fcc5dbe41b3673d22d2d..0e8b63a5474eca08922906d2205968d0a2be450c 100644 --- a/gpui/src/presenter.rs +++ b/gpui/src/presenter.rs @@ -160,15 +160,7 @@ impl Presenter { _ => {} } - let mut event_cx = EventContext { - rendered_views: &mut self.rendered_views, - dispatched_actions: Default::default(), - font_cache: &self.font_cache, - text_layout_cache: &self.text_layout_cache, - view_stack: Default::default(), - invalidated_views: Default::default(), - app: cx, - }; + let mut event_cx = self.build_event_context(cx); event_cx.dispatch_event(root_view_id, &event); let invalidated_views = event_cx.invalidated_views; @@ -183,6 +175,21 @@ impl Presenter { } } + pub fn build_event_context<'a>( + &'a mut self, + cx: &'a mut MutableAppContext, + ) -> EventContext<'a> { + EventContext { + rendered_views: &mut self.rendered_views, + dispatched_actions: Default::default(), + font_cache: &self.font_cache, + text_layout_cache: &self.text_layout_cache, + view_stack: Default::default(), + invalidated_views: Default::default(), + app: cx, + } + } + pub fn debug_elements(&self, cx: &AppContext) -> Option { cx.root_view_id(self.window_id) .and_then(|root_view_id| self.rendered_views.get(&root_view_id)) @@ -274,8 +281,9 @@ impl<'a> EventContext<'a> { } pub fn notify(&mut self) { - self.invalidated_views - .insert(*self.view_stack.last().unwrap()); + if let Some(view_id) = self.view_stack.last() { + self.invalidated_views.insert(*view_id); + } } }