diff --git a/crates/diagnostics/src/diagnostics.rs b/crates/diagnostics/src/diagnostics.rs index 0ac282d1997760a5298113f688639af96898a9a9..75a95586bebc4043c62c2ee81a4c3fdd4b0d938d 100644 --- a/crates/diagnostics/src/diagnostics.rs +++ b/crates/diagnostics/src/diagnostics.rs @@ -24,6 +24,7 @@ use settings::Settings; use smallvec::SmallVec; use std::{ any::{Any, TypeId}, + borrow::Cow, cmp::Ordering, ops::Range, path::PathBuf, @@ -531,6 +532,10 @@ impl Item for ProjectDiagnosticsEditor { .update(cx, |editor, cx| editor.navigate(data, cx)) } + fn tab_tooltip_text(&self, _: &AppContext) -> Option> { + Some("Project Diagnostics".into()) + } + fn is_dirty(&self, cx: &AppContext) -> bool { self.excerpts.read(cx).is_dirty(cx) } diff --git a/crates/editor/src/items.rs b/crates/editor/src/items.rs index 0f2a98dfe94d49d135214c3500e6e02283186fc5..c5e0e8993e439391f5042ae6bf3e66d682267087 100644 --- a/crates/editor/src/items.rs +++ b/crates/editor/src/items.rs @@ -514,7 +514,24 @@ impl Item for Editor { } } - fn tab_description<'a>(&'a self, detail: usize, cx: &'a AppContext) -> Option> { + fn tab_tooltip_text(&self, cx: &AppContext) -> Option> { + let file_path = self + .buffer() + .read(cx) + .as_singleton()? + .read(cx) + .file() + .and_then(|f| f.as_local())? + .abs_path(cx); + + let file_path = util::paths::compact(&file_path) + .to_string_lossy() + .to_string(); + + Some(file_path.into()) + } + + fn tab_description<'a>(&'a self, detail: usize, cx: &'a AppContext) -> Option> { match path_for_buffer(&self.buffer, detail, true, cx)? { Cow::Borrowed(path) => Some(path.to_string_lossy()), Cow::Owned(path) => Some(path.to_string_lossy().to_string().into()), diff --git a/crates/feedback/src/feedback_editor.rs b/crates/feedback/src/feedback_editor.rs index 15334138db42bd2c76cef5feb60037ffd3edb048..f2d6c54aa74dc8ab37223ef6599a4346624fd4e0 100644 --- a/crates/feedback/src/feedback_editor.rs +++ b/crates/feedback/src/feedback_editor.rs @@ -1,5 +1,6 @@ use std::{ any::TypeId, + borrow::Cow, ops::{Range, RangeInclusive}, sync::Arc, }; @@ -248,6 +249,10 @@ impl Entity for FeedbackEditor { } impl Item for FeedbackEditor { + fn tab_tooltip_text(&self, _: &AppContext) -> Option> { + Some("Send Feedback".into()) + } + fn tab_content(&self, _: Option, style: &theme::Tab, _: &AppContext) -> ElementBox { Flex::row() .with_child( diff --git a/crates/gpui/src/elements/tooltip.rs b/crates/gpui/src/elements/tooltip.rs index 562f12295c4a3cd0dbbba28d46301de41f212ef7..2f26ee116dad86194796a807892de421e3dfaa5c 100644 --- a/crates/gpui/src/elements/tooltip.rs +++ b/crates/gpui/src/elements/tooltip.rs @@ -39,7 +39,7 @@ pub struct TooltipStyle { pub container: ContainerStyle, pub text: TextStyle, keystroke: KeystrokeStyle, - pub max_text_width: f32, + pub max_text_width: Option, } #[derive(Clone, Deserialize, Default)] @@ -140,9 +140,14 @@ impl Tooltip { ) -> impl Element { Flex::row() .with_child({ - let text = Text::new(text, style.text) - .constrained() - .with_max_width(style.max_text_width); + let text = if let Some(max_text_width) = style.max_text_width { + Text::new(text, style.text) + .constrained() + .with_max_width(max_text_width) + } else { + Text::new(text, style.text).constrained() + }; + if measure { text.flex(1., false).boxed() } else { diff --git a/crates/search/src/project_search.rs b/crates/search/src/project_search.rs index c7660aa33602ba83db950719c2110b28ebc9af6b..906a0becfdc41e209595f405521f999365d7d4a3 100644 --- a/crates/search/src/project_search.rs +++ b/crates/search/src/project_search.rs @@ -22,6 +22,7 @@ use settings::Settings; use smallvec::SmallVec; use std::{ any::{Any, TypeId}, + borrow::Cow, mem, ops::Range, path::PathBuf, @@ -225,6 +226,10 @@ impl View for ProjectSearchView { } impl Item for ProjectSearchView { + fn tab_tooltip_text(&self, cx: &AppContext) -> Option> { + Some(self.query_editor.read(cx).text(cx).into()) + } + fn act_as_type<'a>( &'a self, type_id: TypeId, diff --git a/crates/terminal_view/src/terminal_view.rs b/crates/terminal_view/src/terminal_view.rs index 3af147b9ff3e1e383ddb9d5045abb36e71cdddcf..e420a3d5e08dcf714847c11efc412364b00a4df9 100644 --- a/crates/terminal_view/src/terminal_view.rs +++ b/crates/terminal_view/src/terminal_view.rs @@ -3,6 +3,7 @@ pub mod terminal_button; pub mod terminal_element; use std::{ + borrow::Cow, ops::RangeInclusive, path::{Path, PathBuf}, time::Duration, @@ -543,6 +544,10 @@ impl View for TerminalView { } impl Item for TerminalView { + fn tab_tooltip_text(&self, cx: &AppContext) -> Option> { + Some(self.terminal().read(cx).title().into()) + } + fn tab_content( &self, _detail: Option, diff --git a/crates/welcome/src/welcome.rs b/crates/welcome/src/welcome.rs index 28b0e43c571fac33d7ee835933a584ef683d8da0..80e27666f581c000e169cef5cd0b14e64b313cb3 100644 --- a/crates/welcome/src/welcome.rs +++ b/crates/welcome/src/welcome.rs @@ -1,6 +1,6 @@ mod base_keymap_picker; -use std::sync::Arc; +use std::{borrow::Cow, sync::Arc}; use db::kvp::KEY_VALUE_STORE; use gpui::{ @@ -198,6 +198,10 @@ impl WelcomePage { } impl Item for WelcomePage { + fn tab_tooltip_text(&self, _: &AppContext) -> Option> { + Some("Welcome to Zed!".into()) + } + fn tab_content( &self, _detail: Option, diff --git a/crates/workspace/src/item.rs b/crates/workspace/src/item.rs index f7ffe64f972d99ccb9b172f3fc70a4a0203f91b4..6c41507478a5185a13c97984ed551aadb69ccdd7 100644 --- a/crates/workspace/src/item.rs +++ b/crates/workspace/src/item.rs @@ -44,7 +44,10 @@ pub trait Item: View { fn navigate(&mut self, _: Box, _: &mut ViewContext) -> bool { false } - fn tab_description<'a>(&'a self, _: usize, _: &'a AppContext) -> Option> { + fn tab_tooltip_text(&self, _: &AppContext) -> Option> { + None + } + fn tab_description<'a>(&'a self, _: usize, _: &'a AppContext) -> Option> { None } fn tab_content(&self, detail: Option, style: &theme::Tab, cx: &AppContext) @@ -162,7 +165,8 @@ pub trait ItemHandle: 'static + fmt::Debug { cx: &mut AppContext, handler: Box, ) -> gpui::Subscription; - fn tab_description<'a>(&self, detail: usize, cx: &'a AppContext) -> Option>; + fn tab_tooltip_text<'a>(&self, cx: &'a AppContext) -> Option>; + fn tab_description<'a>(&'a self, detail: usize, cx: &'a AppContext) -> Option>; fn tab_content(&self, detail: Option, style: &theme::Tab, cx: &AppContext) -> ElementBox; fn project_path(&self, cx: &AppContext) -> Option; @@ -248,7 +252,11 @@ impl ItemHandle for ViewHandle { }) } - fn tab_description<'a>(&self, detail: usize, cx: &'a AppContext) -> Option> { + fn tab_tooltip_text<'a>(&self, cx: &'a AppContext) -> Option> { + self.read(cx).tab_tooltip_text(cx) + } + + fn tab_description<'a>(&'a self, detail: usize, cx: &'a AppContext) -> Option> { self.read(cx).tab_description(detail, cx) } @@ -905,7 +913,7 @@ pub(crate) mod test { } impl Item for TestItem { - fn tab_description<'a>(&'a self, detail: usize, _: &'a AppContext) -> Option> { + fn tab_description(&self, detail: usize, _: &AppContext) -> Option> { self.tab_descriptions.as_ref().and_then(|descriptions| { let description = *descriptions.get(detail).or_else(|| descriptions.last())?; Some(description.into()) diff --git a/crates/workspace/src/pane.rs b/crates/workspace/src/pane.rs index a54aed96f464bdcfff03e526ecdb8cd9f5c37963..c394ae4631b57de99c3c8e2c229942c4cfe7481f 100644 --- a/crates/workspace/src/pane.rs +++ b/crates/workspace/src/pane.rs @@ -1386,6 +1386,9 @@ impl Pane { let detail = detail.clone(); let theme = cx.global::().theme.clone(); + let mut tooltip_theme = theme.tooltip.clone(); + tooltip_theme.max_text_width = None; + let tab_tooltip_text = item.tab_tooltip_text(cx).map(|a| a.to_string()); move |mouse_state, cx| { let tab_style = @@ -1393,39 +1396,56 @@ impl Pane { let hovered = mouse_state.hovered(); enum Tab {} - MouseEventHandler::::new(ix, cx, |_, cx| { - Self::render_tab( - &item, - pane.clone(), - ix == 0, - detail, - hovered, - tab_style, - cx, - ) - }) - .on_down(MouseButton::Left, move |_, cx| { - cx.dispatch_action(ActivateItem(ix)); - }) - .on_click(MouseButton::Middle, { - let item = item.clone(); - let pane = pane.clone(); - move |_, cx: &mut EventContext| { - cx.dispatch_action(CloseItemById { - item_id: item.id(), - pane: pane.clone(), - }) - } - }) - .on_down(MouseButton::Right, move |e, cx| { - let item = item.clone(); - cx.dispatch_action(DeployTabContextMenu { - position: e.position, - item_id: item.id(), - pane: pane.clone(), - }); - }) - .boxed() + let mouse_event_handler = + MouseEventHandler::::new(ix, cx, |_, cx| { + Self::render_tab( + &item, + pane.clone(), + ix == 0, + detail, + hovered, + tab_style, + cx, + ) + }) + .on_down(MouseButton::Left, move |_, cx| { + cx.dispatch_action(ActivateItem(ix)); + }) + .on_click(MouseButton::Middle, { + let item = item.clone(); + let pane = pane.clone(); + move |_, cx: &mut EventContext| { + cx.dispatch_action(CloseItemById { + item_id: item.id(), + pane: pane.clone(), + }) + } + }) + .on_down( + MouseButton::Right, + move |e, cx| { + let item = item.clone(); + cx.dispatch_action(DeployTabContextMenu { + position: e.position, + item_id: item.id(), + pane: pane.clone(), + }); + }, + ); + + if let Some(tab_tooltip_text) = tab_tooltip_text { + return mouse_event_handler + .with_tooltip::( + ix, + tab_tooltip_text, + None, + tooltip_theme, + cx, + ) + .boxed(); + } + + mouse_event_handler.boxed() } }); diff --git a/crates/workspace/src/shared_screen.rs b/crates/workspace/src/shared_screen.rs index 7f7bf3b25f418be46ff8e643d4a74ae54af2045f..a397c3a719fdd12b8b69c7612851a34290d34661 100644 --- a/crates/workspace/src/shared_screen.rs +++ b/crates/workspace/src/shared_screen.rs @@ -13,7 +13,10 @@ use gpui::{ }; use settings::Settings; use smallvec::SmallVec; -use std::sync::{Arc, Weak}; +use std::{ + borrow::Cow, + sync::{Arc, Weak}, +}; pub enum Event { Close, @@ -92,6 +95,9 @@ impl View for SharedScreen { } impl Item for SharedScreen { + fn tab_tooltip_text(&self, _: &AppContext) -> Option> { + Some(format!("{}'s screen", self.user.github_login).into()) + } fn deactivated(&mut self, cx: &mut ViewContext) { if let Some(nav_history) = self.nav_history.as_ref() { nav_history.push::<()>(None, cx);