diff --git a/crates/gpui/src/elements/div.rs b/crates/gpui/src/elements/div.rs index e3ca5c7cd95ce55f7b523399d6cecbe7be3ad3a2..06fe5902bf6eca527f5f16d84e88c9c847e3e08a 100644 --- a/crates/gpui/src/elements/div.rs +++ b/crates/gpui/src/elements/div.rs @@ -3097,6 +3097,25 @@ impl ScrollHandle { } } + /// Get the bottom child that's scrolled into view. + pub fn bottom_item(&self) -> usize { + let state = self.0.borrow(); + let bottom = state.bounds.bottom() - state.offset.borrow().y; + + match state.child_bounds.binary_search_by(|bounds| { + if bottom < bounds.top() { + Ordering::Greater + } else if bottom > bounds.bottom() { + Ordering::Less + } else { + Ordering::Equal + } + }) { + Ok(ix) => ix, + Err(ix) => ix.min(state.child_bounds.len().saturating_sub(1)), + } + } + /// Return the bounds into which this child is painted pub fn bounds(&self) -> Bounds { self.0.borrow().bounds @@ -3198,6 +3217,21 @@ impl ScrollHandle { } } + /// Get the logical scroll bottom, based on a child index and a pixel offset. + pub fn logical_scroll_bottom(&self) -> (usize, Pixels) { + let ix = self.bottom_item(); + let state = self.0.borrow(); + + if let Some(child_bounds) = state.child_bounds.get(ix) { + ( + ix, + child_bounds.bottom() + state.offset.borrow().y - state.bounds.bottom(), + ) + } else { + (ix, px(0.)) + } + } + /// Get the count of children for scrollable item. pub fn children_count(&self) -> usize { self.0.borrow().child_bounds.len() diff --git a/crates/settings_ui/src/settings_ui.rs b/crates/settings_ui/src/settings_ui.rs index 5ba51882307f4281219b134136908f45a611a124..70cfadd87a90141461089bd09b5fbde9036bb42b 100644 --- a/crates/settings_ui/src/settings_ui.rs +++ b/crates/settings_ui/src/settings_ui.rs @@ -944,7 +944,11 @@ impl SettingsWindow { } fn calculate_navbar_entry_from_scroll_position(&mut self) { - let scroll_index = self.scroll_handle.logical_scroll_top().0; + let top = self.scroll_handle.top_item(); + let bottom = self.scroll_handle.bottom_item(); + + let scroll_index = (top + bottom) / 2; + let scroll_index = scroll_index.clamp(top, bottom); let mut page_index = self.navbar_entry; while !self.navbar_entries[page_index].is_root {