From ce51196eaba0279f83604716a1d6e6927c11447b Mon Sep 17 00:00:00 2001 From: Antonio Scandurra Date: Fri, 14 Jan 2022 17:53:06 +0100 Subject: [PATCH] Center the selected item when updating outline query Co-Authored-By: Max Brunsfeld Co-Authored-By: Nathan Sobo --- crates/file_finder/src/file_finder.rs | 9 +++-- crates/gpui/src/elements/uniform_list.rs | 41 ++++++++++++++++----- crates/outline/src/outline.rs | 14 ++++--- crates/project_panel/src/project_panel.rs | 6 +-- crates/theme_selector/src/theme_selector.rs | 6 ++- 5 files changed, 54 insertions(+), 22 deletions(-) diff --git a/crates/file_finder/src/file_finder.rs b/crates/file_finder/src/file_finder.rs index 707a3bfb20..48fb562e7d 100644 --- a/crates/file_finder/src/file_finder.rs +++ b/crates/file_finder/src/file_finder.rs @@ -353,7 +353,8 @@ impl FileFinder { let mat = &self.matches[selected_index]; self.selected = Some((mat.worktree_id, mat.path.clone())); } - self.list_state.scroll_to(selected_index); + self.list_state + .scroll_to(ScrollTarget::Show(selected_index)); cx.notify(); } @@ -364,7 +365,8 @@ impl FileFinder { let mat = &self.matches[selected_index]; self.selected = Some((mat.worktree_id, mat.path.clone())); } - self.list_state.scroll_to(selected_index); + self.list_state + .scroll_to(ScrollTarget::Show(selected_index)); cx.notify(); } @@ -415,7 +417,8 @@ impl FileFinder { } self.latest_search_query = query; self.latest_search_did_cancel = did_cancel; - self.list_state.scroll_to(self.selected_index()); + self.list_state + .scroll_to(ScrollTarget::Show(self.selected_index())); cx.notify(); } } diff --git a/crates/gpui/src/elements/uniform_list.rs b/crates/gpui/src/elements/uniform_list.rs index f499801e63..889494c1bb 100644 --- a/crates/gpui/src/elements/uniform_list.rs +++ b/crates/gpui/src/elements/uniform_list.rs @@ -14,9 +14,14 @@ use std::{cmp, ops::Range, sync::Arc}; #[derive(Clone, Default)] pub struct UniformListState(Arc>); +pub enum ScrollTarget { + Show(usize), + Center(usize), +} + impl UniformListState { - pub fn scroll_to(&self, item_ix: usize) { - self.0.lock().scroll_to = Some(item_ix); + pub fn scroll_to(&self, scroll_to: ScrollTarget) { + self.0.lock().scroll_to = Some(scroll_to); } pub fn scroll_top(&self) -> f32 { @@ -27,7 +32,7 @@ impl UniformListState { #[derive(Default)] struct StateInner { scroll_top: f32, - scroll_to: Option, + scroll_to: Option, } pub struct LayoutState { @@ -97,14 +102,32 @@ where state.scroll_top = scroll_max; } - if let Some(item_ix) = state.scroll_to.take() { + if let Some(scroll_to) = state.scroll_to.take() { + let item_ix; + let center; + match scroll_to { + ScrollTarget::Show(ix) => { + item_ix = ix; + center = false; + } + ScrollTarget::Center(ix) => { + item_ix = ix; + center = true; + } + } + let item_top = self.padding_top + item_ix as f32 * item_height; let item_bottom = item_top + item_height; - - if item_top < state.scroll_top { - state.scroll_top = item_top; - } else if item_bottom > (state.scroll_top + list_height) { - state.scroll_top = item_bottom - list_height; + if center { + let item_center = item_top + item_height / 2.; + state.scroll_top = (item_center - list_height / 2.).max(0.); + } else { + let scroll_bottom = state.scroll_top + list_height; + if item_top < state.scroll_top { + state.scroll_top = item_top; + } else if item_bottom > scroll_bottom { + state.scroll_top = item_bottom - list_height; + } } } } diff --git a/crates/outline/src/outline.rs b/crates/outline/src/outline.rs index 1ddd3321e3..7e480aca87 100644 --- a/crates/outline/src/outline.rs +++ b/crates/outline/src/outline.rs @@ -187,19 +187,23 @@ impl OutlineView { fn select_prev(&mut self, _: &SelectPrev, cx: &mut ViewContext) { if self.selected_match_index > 0 { - self.select(self.selected_match_index - 1, true, cx); + self.select(self.selected_match_index - 1, true, false, cx); } } fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext) { if self.selected_match_index + 1 < self.matches.len() { - self.select(self.selected_match_index + 1, true, cx); + self.select(self.selected_match_index + 1, true, false, cx); } } - fn select(&mut self, index: usize, navigate: bool, cx: &mut ViewContext) { + fn select(&mut self, index: usize, navigate: bool, center: bool, cx: &mut ViewContext) { self.selected_match_index = index; - self.list_state.scroll_to(self.selected_match_index); + self.list_state.scroll_to(if center { + ScrollTarget::Center(index) + } else { + ScrollTarget::Show(index) + }); if navigate { let selected_match = &self.matches[self.selected_match_index]; let outline_item = &self.outline.items[selected_match.candidate_id]; @@ -319,7 +323,7 @@ impl OutlineView { .unwrap_or(0); navigate_to_selected_index = !self.matches.is_empty(); } - self.select(selected_index, navigate_to_selected_index, cx); + self.select(selected_index, navigate_to_selected_index, true, cx); } fn render_matches(&self) -> ElementBox { diff --git a/crates/project_panel/src/project_panel.rs b/crates/project_panel/src/project_panel.rs index 8c73f1be86..b28c526564 100644 --- a/crates/project_panel/src/project_panel.rs +++ b/crates/project_panel/src/project_panel.rs @@ -1,8 +1,8 @@ use gpui::{ action, elements::{ - Align, ConstrainedBox, Empty, Flex, Label, MouseEventHandler, ParentElement, Svg, - UniformList, UniformListState, + Align, ConstrainedBox, Empty, Flex, Label, MouseEventHandler, ParentElement, ScrollTarget, + Svg, UniformList, UniformListState, }, keymap::{ self, @@ -278,7 +278,7 @@ impl ProjectPanel { fn autoscroll(&mut self) { if let Some(selection) = self.selection { - self.list.scroll_to(selection.index); + self.list.scroll_to(ScrollTarget::Show(selection.index)); } } diff --git a/crates/theme_selector/src/theme_selector.rs b/crates/theme_selector/src/theme_selector.rs index d1cbafe7dc..af7e8527f0 100644 --- a/crates/theme_selector/src/theme_selector.rs +++ b/crates/theme_selector/src/theme_selector.rs @@ -140,7 +140,8 @@ impl ThemeSelector { if self.selected_index > 0 { self.selected_index -= 1; } - self.list_state.scroll_to(self.selected_index); + self.list_state + .scroll_to(ScrollTarget::Show(self.selected_index)); cx.notify(); } @@ -148,7 +149,8 @@ impl ThemeSelector { if self.selected_index + 1 < self.matches.len() { self.selected_index += 1; } - self.list_state.scroll_to(self.selected_index); + self.list_state + .scroll_to(ScrollTarget::Show(self.selected_index)); cx.notify(); }