@@ -261,6 +261,15 @@ impl ListState {
pub fn splice(&self, old_range: Range<usize>, 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::<Count, ()>();
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 {
@@ -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<json::Value> {
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);
+ }
}
}