Differentiate among tabs with the same name

This commit introduces a new, optional `Item::tab_description` method
that lets implementers define a description for the tab with a certain
`detail`. When two or more tabs match the same description, we will
increase the `detail` until tabs don't match anymore or increasing the
`detail` doesn't disambiguate tabs any further.

As soon as we find a valid `detail` that disambiguates tabs enough, we
will pass it to `Item::tab_content`. In `Editor`, this is implemented by
showing more and more of the path's suffix as `detail` is increased.
This commit is contained in:
Antonio Scandurra 2022-07-14 11:49:10 +02:00
parent 4a5b8fd2e6
commit 07d269234f
12 changed files with 171 additions and 25 deletions

View file

@ -840,8 +840,10 @@ impl Pane {
} else {
None
};
let mut row = Flex::row().scrollable::<Tabs, _>(1, autoscroll, cx);
for (ix, item) in self.items.iter().enumerate() {
for (ix, (item, detail)) in self.items.iter().zip(self.tab_details(cx)).enumerate() {
let detail = if detail == 0 { None } else { Some(detail) };
let is_active = ix == self.active_item_index;
row.add_child({
@ -850,7 +852,7 @@ impl Pane {
} else {
theme.workspace.tab.clone()
};
let title = item.tab_content(&tab_style, cx);
let title = item.tab_content(detail, &tab_style, cx);
let mut style = if is_active {
theme.workspace.active_tab.clone()
@ -971,6 +973,43 @@ impl Pane {
row.boxed()
})
}
fn tab_details(&self, cx: &AppContext) -> Vec<usize> {
let mut tab_details = (0..self.items.len()).map(|_| 0).collect::<Vec<_>>();
let mut tab_descriptions = HashMap::default();
let mut done = false;
while !done {
done = true;
// Store item indices by their tab description.
for (ix, (item, detail)) in self.items.iter().zip(&tab_details).enumerate() {
if let Some(description) = item.tab_description(*detail, cx) {
if *detail == 0
|| Some(&description) != item.tab_description(detail - 1, cx).as_ref()
{
tab_descriptions
.entry(description)
.or_insert(Vec::new())
.push(ix);
}
}
}
// If two or more items have the same tab description, increase their level
// of detail and try again.
for (_, item_ixs) in tab_descriptions.drain() {
if item_ixs.len() > 1 {
done = false;
for ix in item_ixs {
tab_details[ix] += 1;
}
}
}
}
tab_details
}
}
impl Entity for Pane {