Make tab switcher show preview of selected tab (#36718)
Similar to nvim's telescope this makes it easier to find the right tab in the list. The preview takes place in the pane where the tab resides. - on dismiss: We restore all panes. - on confirm: We restore all panes except the one where the selected tab resides. For this reason we collect the active item for each pane before the tabswither starts. Release Notes: - Improved tab switcher, it now shows a preview of the selected tab Co-authored-by: Julia Ryan <juliaryan3.14@gmail.com>
This commit is contained in:
parent
0beb919bbb
commit
06c0e59379
1 changed files with 46 additions and 9 deletions
|
@ -113,7 +113,13 @@ impl TabSwitcher {
|
||||||
}
|
}
|
||||||
|
|
||||||
let weak_workspace = workspace.weak_handle();
|
let weak_workspace = workspace.weak_handle();
|
||||||
|
|
||||||
let project = workspace.project().clone();
|
let project = workspace.project().clone();
|
||||||
|
let original_items: Vec<_> = workspace
|
||||||
|
.panes()
|
||||||
|
.iter()
|
||||||
|
.map(|p| (p.clone(), p.read(cx).active_item_index()))
|
||||||
|
.collect();
|
||||||
workspace.toggle_modal(window, cx, |window, cx| {
|
workspace.toggle_modal(window, cx, |window, cx| {
|
||||||
let delegate = TabSwitcherDelegate::new(
|
let delegate = TabSwitcherDelegate::new(
|
||||||
project,
|
project,
|
||||||
|
@ -124,6 +130,7 @@ impl TabSwitcher {
|
||||||
is_global,
|
is_global,
|
||||||
window,
|
window,
|
||||||
cx,
|
cx,
|
||||||
|
original_items,
|
||||||
);
|
);
|
||||||
TabSwitcher::new(delegate, window, is_global, cx)
|
TabSwitcher::new(delegate, window, is_global, cx)
|
||||||
});
|
});
|
||||||
|
@ -221,7 +228,9 @@ pub struct TabSwitcherDelegate {
|
||||||
workspace: WeakEntity<Workspace>,
|
workspace: WeakEntity<Workspace>,
|
||||||
project: Entity<Project>,
|
project: Entity<Project>,
|
||||||
matches: Vec<TabMatch>,
|
matches: Vec<TabMatch>,
|
||||||
|
original_items: Vec<(Entity<Pane>, usize)>,
|
||||||
is_all_panes: bool,
|
is_all_panes: bool,
|
||||||
|
restored_items: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TabSwitcherDelegate {
|
impl TabSwitcherDelegate {
|
||||||
|
@ -235,6 +244,7 @@ impl TabSwitcherDelegate {
|
||||||
is_all_panes: bool,
|
is_all_panes: bool,
|
||||||
window: &mut Window,
|
window: &mut Window,
|
||||||
cx: &mut Context<TabSwitcher>,
|
cx: &mut Context<TabSwitcher>,
|
||||||
|
original_items: Vec<(Entity<Pane>, usize)>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self::subscribe_to_updates(&pane, window, cx);
|
Self::subscribe_to_updates(&pane, window, cx);
|
||||||
Self {
|
Self {
|
||||||
|
@ -246,6 +256,8 @@ impl TabSwitcherDelegate {
|
||||||
project,
|
project,
|
||||||
matches: Vec::new(),
|
matches: Vec::new(),
|
||||||
is_all_panes,
|
is_all_panes,
|
||||||
|
original_items,
|
||||||
|
restored_items: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,13 +312,6 @@ impl TabSwitcherDelegate {
|
||||||
|
|
||||||
let matches = if query.is_empty() {
|
let matches = if query.is_empty() {
|
||||||
let history = workspace.read(cx).recently_activated_items(cx);
|
let history = workspace.read(cx).recently_activated_items(cx);
|
||||||
for item in &all_items {
|
|
||||||
eprintln!(
|
|
||||||
"{:?} {:?}",
|
|
||||||
item.item.tab_content_text(0, cx),
|
|
||||||
(Reverse(history.get(&item.item.item_id())), item.item_index)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
all_items
|
all_items
|
||||||
.sort_by_key(|tab| (Reverse(history.get(&tab.item.item_id())), tab.item_index));
|
.sort_by_key(|tab| (Reverse(history.get(&tab.item.item_id())), tab.item_index));
|
||||||
all_items
|
all_items
|
||||||
|
@ -473,8 +478,25 @@ impl PickerDelegate for TabSwitcherDelegate {
|
||||||
self.selected_index
|
self.selected_index
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_selected_index(&mut self, ix: usize, _: &mut Window, cx: &mut Context<Picker<Self>>) {
|
fn set_selected_index(
|
||||||
|
&mut self,
|
||||||
|
ix: usize,
|
||||||
|
window: &mut Window,
|
||||||
|
cx: &mut Context<Picker<Self>>,
|
||||||
|
) {
|
||||||
self.selected_index = ix;
|
self.selected_index = ix;
|
||||||
|
|
||||||
|
let Some(selected_match) = self.matches.get(self.selected_index()) else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
selected_match
|
||||||
|
.pane
|
||||||
|
.update(cx, |pane, cx| {
|
||||||
|
if let Some(index) = pane.index_for_item(selected_match.item.as_ref()) {
|
||||||
|
pane.activate_item(index, false, false, window, cx);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.ok();
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,6 +523,13 @@ impl PickerDelegate for TabSwitcherDelegate {
|
||||||
let Some(selected_match) = self.matches.get(self.selected_index()) else {
|
let Some(selected_match) = self.matches.get(self.selected_index()) else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
self.restored_items = true;
|
||||||
|
for (pane, index) in self.original_items.iter() {
|
||||||
|
pane.update(cx, |this, cx| {
|
||||||
|
this.activate_item(*index, false, false, window, cx);
|
||||||
|
})
|
||||||
|
}
|
||||||
selected_match
|
selected_match
|
||||||
.pane
|
.pane
|
||||||
.update(cx, |pane, cx| {
|
.update(cx, |pane, cx| {
|
||||||
|
@ -511,7 +540,15 @@ impl PickerDelegate for TabSwitcherDelegate {
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn dismissed(&mut self, _: &mut Window, cx: &mut Context<Picker<TabSwitcherDelegate>>) {
|
fn dismissed(&mut self, window: &mut Window, cx: &mut Context<Picker<TabSwitcherDelegate>>) {
|
||||||
|
if !self.restored_items {
|
||||||
|
for (pane, index) in self.original_items.iter() {
|
||||||
|
pane.update(cx, |this, cx| {
|
||||||
|
this.activate_item(*index, false, false, window, cx);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
self.tab_switcher
|
self.tab_switcher
|
||||||
.update(cx, |_, cx| cx.emit(DismissEvent))
|
.update(cx, |_, cx| cx.emit(DismissEvent))
|
||||||
.log_err();
|
.log_err();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue