Add missing shortcuts in tooltips (#18282)
Fixes some missing shortcuts from Tooltips like the project search, buffer search, quick action bar, .... https://github.com/user-attachments/assets/d3a0160a-8d6e-4ddc-bf82-1fabeca42d59 This should hopefully help new users learn and discover some nice keyboard shortcuts Release Notes: - Display keyboard shortcuts inside tooltips in the project search, buffer search etc.
This commit is contained in:
parent
a1d2e1106e
commit
1c5d9c221a
9 changed files with 199 additions and 43 deletions
|
@ -196,7 +196,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"context": "BufferSearchBar && in_replace",
|
"context": "BufferSearchBar && in_replace > Editor",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"enter": "search::ReplaceNext",
|
"enter": "search::ReplaceNext",
|
||||||
"ctrl-enter": "search::ReplaceAll"
|
"ctrl-enter": "search::ReplaceAll"
|
||||||
|
|
|
@ -232,7 +232,7 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"context": "BufferSearchBar && in_replace",
|
"context": "BufferSearchBar && in_replace > Editor",
|
||||||
"bindings": {
|
"bindings": {
|
||||||
"enter": "search::ReplaceNext",
|
"enter": "search::ReplaceNext",
|
||||||
"cmd-enter": "search::ReplaceAll"
|
"cmd-enter": "search::ReplaceAll"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use editor::Editor;
|
use editor::Editor;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
Element, EventEmitter, IntoElement, ParentElement, Render, StyledText, Subscription,
|
Element, EventEmitter, FocusableView, IntoElement, ParentElement, Render, StyledText,
|
||||||
ViewContext,
|
Subscription, ViewContext,
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
|
@ -90,17 +90,30 @@ impl Render for Breadcrumbs {
|
||||||
ButtonLike::new("toggle outline view")
|
ButtonLike::new("toggle outline view")
|
||||||
.child(breadcrumbs_stack)
|
.child(breadcrumbs_stack)
|
||||||
.style(ButtonStyle::Transparent)
|
.style(ButtonStyle::Transparent)
|
||||||
.on_click(move |_, cx| {
|
.on_click({
|
||||||
if let Some(editor) = editor.upgrade() {
|
let editor = editor.clone();
|
||||||
outline::toggle(editor, &editor::actions::ToggleOutline, cx)
|
move |_, cx| {
|
||||||
|
if let Some(editor) = editor.upgrade() {
|
||||||
|
outline::toggle(editor, &editor::actions::ToggleOutline, cx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.tooltip(|cx| {
|
.tooltip(move |cx| {
|
||||||
Tooltip::for_action(
|
if let Some(editor) = editor.upgrade() {
|
||||||
"Show symbol outline",
|
let focus_handle = editor.read(cx).focus_handle(cx);
|
||||||
&editor::actions::ToggleOutline,
|
Tooltip::for_action_in(
|
||||||
cx,
|
"Show symbol outline",
|
||||||
)
|
&editor::actions::ToggleOutline,
|
||||||
|
&focus_handle,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Tooltip::for_action(
|
||||||
|
"Show symbol outline",
|
||||||
|
&editor::actions::ToggleOutline,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
),
|
),
|
||||||
None => element
|
None => element
|
||||||
|
|
|
@ -8,8 +8,8 @@ use editor::actions::{
|
||||||
use editor::{Editor, EditorSettings};
|
use editor::{Editor, EditorSettings};
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
Action, AnchorCorner, ClickEvent, ElementId, EventEmitter, InteractiveElement, ParentElement,
|
Action, AnchorCorner, ClickEvent, ElementId, EventEmitter, FocusHandle, FocusableView,
|
||||||
Render, Styled, Subscription, View, ViewContext, WeakView,
|
InteractiveElement, ParentElement, Render, Styled, Subscription, View, ViewContext, WeakView,
|
||||||
};
|
};
|
||||||
use search::{buffer_search, BufferSearchBar};
|
use search::{buffer_search, BufferSearchBar};
|
||||||
use settings::{Settings, SettingsStore};
|
use settings::{Settings, SettingsStore};
|
||||||
|
@ -110,12 +110,15 @@ impl Render for QuickActionBar {
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let focus_handle = editor.read(cx).focus_handle(cx);
|
||||||
|
|
||||||
let search_button = editor.is_singleton(cx).then(|| {
|
let search_button = editor.is_singleton(cx).then(|| {
|
||||||
QuickActionBarButton::new(
|
QuickActionBarButton::new(
|
||||||
"toggle buffer search",
|
"toggle buffer search",
|
||||||
IconName::MagnifyingGlass,
|
IconName::MagnifyingGlass,
|
||||||
!self.buffer_search_bar.read(cx).is_dismissed(),
|
!self.buffer_search_bar.read(cx).is_dismissed(),
|
||||||
Box::new(buffer_search::Deploy::find()),
|
Box::new(buffer_search::Deploy::find()),
|
||||||
|
focus_handle.clone(),
|
||||||
"Buffer Search",
|
"Buffer Search",
|
||||||
{
|
{
|
||||||
let buffer_search_bar = self.buffer_search_bar.clone();
|
let buffer_search_bar = self.buffer_search_bar.clone();
|
||||||
|
@ -133,6 +136,7 @@ impl Render for QuickActionBar {
|
||||||
IconName::ZedAssistant,
|
IconName::ZedAssistant,
|
||||||
false,
|
false,
|
||||||
Box::new(InlineAssist::default()),
|
Box::new(InlineAssist::default()),
|
||||||
|
focus_handle.clone(),
|
||||||
"Inline Assist",
|
"Inline Assist",
|
||||||
{
|
{
|
||||||
let workspace = self.workspace.clone();
|
let workspace = self.workspace.clone();
|
||||||
|
@ -321,6 +325,7 @@ struct QuickActionBarButton {
|
||||||
icon: IconName,
|
icon: IconName,
|
||||||
toggled: bool,
|
toggled: bool,
|
||||||
action: Box<dyn Action>,
|
action: Box<dyn Action>,
|
||||||
|
focus_handle: FocusHandle,
|
||||||
tooltip: SharedString,
|
tooltip: SharedString,
|
||||||
on_click: Box<dyn Fn(&ClickEvent, &mut WindowContext)>,
|
on_click: Box<dyn Fn(&ClickEvent, &mut WindowContext)>,
|
||||||
}
|
}
|
||||||
|
@ -331,6 +336,7 @@ impl QuickActionBarButton {
|
||||||
icon: IconName,
|
icon: IconName,
|
||||||
toggled: bool,
|
toggled: bool,
|
||||||
action: Box<dyn Action>,
|
action: Box<dyn Action>,
|
||||||
|
focus_handle: FocusHandle,
|
||||||
tooltip: impl Into<SharedString>,
|
tooltip: impl Into<SharedString>,
|
||||||
on_click: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
|
on_click: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
|
@ -339,6 +345,7 @@ impl QuickActionBarButton {
|
||||||
icon,
|
icon,
|
||||||
toggled,
|
toggled,
|
||||||
action,
|
action,
|
||||||
|
focus_handle,
|
||||||
tooltip: tooltip.into(),
|
tooltip: tooltip.into(),
|
||||||
on_click: Box::new(on_click),
|
on_click: Box::new(on_click),
|
||||||
}
|
}
|
||||||
|
@ -355,7 +362,9 @@ impl RenderOnce for QuickActionBarButton {
|
||||||
.icon_size(IconSize::Small)
|
.icon_size(IconSize::Small)
|
||||||
.style(ButtonStyle::Subtle)
|
.style(ButtonStyle::Subtle)
|
||||||
.selected(self.toggled)
|
.selected(self.toggled)
|
||||||
.tooltip(move |cx| Tooltip::for_action(tooltip.clone(), &*action, cx))
|
.tooltip(move |cx| {
|
||||||
|
Tooltip::for_action_in(tooltip.clone(), &*action, &self.focus_handle, cx)
|
||||||
|
})
|
||||||
.on_click(move |event, cx| (self.on_click)(event, cx))
|
.on_click(move |event, cx| (self.on_click)(event, cx))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,10 @@ use editor::{
|
||||||
};
|
};
|
||||||
use futures::channel::oneshot;
|
use futures::channel::oneshot;
|
||||||
use gpui::{
|
use gpui::{
|
||||||
actions, div, impl_actions, Action, AppContext, ClickEvent, EventEmitter, FocusableView, Hsla,
|
actions, div, impl_actions, Action, AppContext, ClickEvent, EventEmitter, FocusHandle,
|
||||||
InteractiveElement as _, IntoElement, KeyContext, ParentElement as _, Render, ScrollHandle,
|
FocusableView, Hsla, InteractiveElement as _, IntoElement, KeyContext, ParentElement as _,
|
||||||
Styled, Subscription, Task, TextStyle, View, ViewContext, VisualContext as _, WindowContext,
|
Render, ScrollHandle, Styled, Subscription, Task, TextStyle, View, ViewContext,
|
||||||
|
VisualContext as _, WindowContext,
|
||||||
};
|
};
|
||||||
use project::{
|
use project::{
|
||||||
search::SearchQuery,
|
search::SearchQuery,
|
||||||
|
@ -142,6 +143,8 @@ impl Render for BufferSearchBar {
|
||||||
return div().id("search_bar");
|
return div().id("search_bar");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let focus_handle = self.focus_handle(cx);
|
||||||
|
|
||||||
let narrow_mode =
|
let narrow_mode =
|
||||||
self.scroll_handle.bounds().size.width / cx.rem_size() < 340. / BASE_REM_SIZE_IN_PX;
|
self.scroll_handle.bounds().size.width / cx.rem_size() < 340. / BASE_REM_SIZE_IN_PX;
|
||||||
let hide_inline_icons = self.editor_needed_width
|
let hide_inline_icons = self.editor_needed_width
|
||||||
|
@ -217,6 +220,7 @@ impl Render for BufferSearchBar {
|
||||||
div.children(supported_options.case.then(|| {
|
div.children(supported_options.case.then(|| {
|
||||||
self.render_search_option_button(
|
self.render_search_option_button(
|
||||||
SearchOptions::CASE_SENSITIVE,
|
SearchOptions::CASE_SENSITIVE,
|
||||||
|
focus_handle.clone(),
|
||||||
cx.listener(|this, _, cx| {
|
cx.listener(|this, _, cx| {
|
||||||
this.toggle_case_sensitive(&ToggleCaseSensitive, cx)
|
this.toggle_case_sensitive(&ToggleCaseSensitive, cx)
|
||||||
}),
|
}),
|
||||||
|
@ -225,6 +229,7 @@ impl Render for BufferSearchBar {
|
||||||
.children(supported_options.word.then(|| {
|
.children(supported_options.word.then(|| {
|
||||||
self.render_search_option_button(
|
self.render_search_option_button(
|
||||||
SearchOptions::WHOLE_WORD,
|
SearchOptions::WHOLE_WORD,
|
||||||
|
focus_handle.clone(),
|
||||||
cx.listener(|this, _, cx| {
|
cx.listener(|this, _, cx| {
|
||||||
this.toggle_whole_word(&ToggleWholeWord, cx)
|
this.toggle_whole_word(&ToggleWholeWord, cx)
|
||||||
}),
|
}),
|
||||||
|
@ -233,6 +238,7 @@ impl Render for BufferSearchBar {
|
||||||
.children(supported_options.regex.then(|| {
|
.children(supported_options.regex.then(|| {
|
||||||
self.render_search_option_button(
|
self.render_search_option_button(
|
||||||
SearchOptions::REGEX,
|
SearchOptions::REGEX,
|
||||||
|
focus_handle.clone(),
|
||||||
cx.listener(|this, _, cx| this.toggle_regex(&ToggleRegex, cx)),
|
cx.listener(|this, _, cx| this.toggle_regex(&ToggleRegex, cx)),
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
|
@ -250,7 +256,17 @@ impl Render for BufferSearchBar {
|
||||||
}))
|
}))
|
||||||
.selected(self.replace_enabled)
|
.selected(self.replace_enabled)
|
||||||
.size(ButtonSize::Compact)
|
.size(ButtonSize::Compact)
|
||||||
.tooltip(|cx| Tooltip::for_action("Toggle replace", &ToggleReplace, cx)),
|
.tooltip({
|
||||||
|
let focus_handle = focus_handle.clone();
|
||||||
|
move |cx| {
|
||||||
|
Tooltip::for_action_in(
|
||||||
|
"Toggle replace",
|
||||||
|
&ToggleReplace,
|
||||||
|
&focus_handle,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.when(supported_options.selection, |this| {
|
.when(supported_options.selection, |this| {
|
||||||
|
@ -268,8 +284,16 @@ impl Render for BufferSearchBar {
|
||||||
}))
|
}))
|
||||||
.selected(self.selection_search_enabled)
|
.selected(self.selection_search_enabled)
|
||||||
.size(ButtonSize::Compact)
|
.size(ButtonSize::Compact)
|
||||||
.tooltip(|cx| {
|
.tooltip({
|
||||||
Tooltip::for_action("Toggle search selection", &ToggleSelection, cx)
|
let focus_handle = focus_handle.clone();
|
||||||
|
move |cx| {
|
||||||
|
Tooltip::for_action_in(
|
||||||
|
"Toggle search selection",
|
||||||
|
&ToggleSelection,
|
||||||
|
&focus_handle,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -280,8 +304,16 @@ impl Render for BufferSearchBar {
|
||||||
IconButton::new("select-all", ui::IconName::SelectAll)
|
IconButton::new("select-all", ui::IconName::SelectAll)
|
||||||
.on_click(|_, cx| cx.dispatch_action(SelectAllMatches.boxed_clone()))
|
.on_click(|_, cx| cx.dispatch_action(SelectAllMatches.boxed_clone()))
|
||||||
.size(ButtonSize::Compact)
|
.size(ButtonSize::Compact)
|
||||||
.tooltip(|cx| {
|
.tooltip({
|
||||||
Tooltip::for_action("Select all matches", &SelectAllMatches, cx)
|
let focus_handle = focus_handle.clone();
|
||||||
|
move |cx| {
|
||||||
|
Tooltip::for_action_in(
|
||||||
|
"Select all matches",
|
||||||
|
&SelectAllMatches,
|
||||||
|
&focus_handle,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.child(render_nav_button(
|
.child(render_nav_button(
|
||||||
|
@ -289,12 +321,14 @@ impl Render for BufferSearchBar {
|
||||||
self.active_match_index.is_some(),
|
self.active_match_index.is_some(),
|
||||||
"Select previous match",
|
"Select previous match",
|
||||||
&SelectPrevMatch,
|
&SelectPrevMatch,
|
||||||
|
focus_handle.clone(),
|
||||||
))
|
))
|
||||||
.child(render_nav_button(
|
.child(render_nav_button(
|
||||||
ui::IconName::ChevronRight,
|
ui::IconName::ChevronRight,
|
||||||
self.active_match_index.is_some(),
|
self.active_match_index.is_some(),
|
||||||
"Select next match",
|
"Select next match",
|
||||||
&SelectNextMatch,
|
&SelectNextMatch,
|
||||||
|
focus_handle.clone(),
|
||||||
))
|
))
|
||||||
.when(!narrow_mode, |this| {
|
.when(!narrow_mode, |this| {
|
||||||
this.child(h_flex().ml_2().min_w(rems_from_px(40.)).child(
|
this.child(h_flex().ml_2().min_w(rems_from_px(40.)).child(
|
||||||
|
@ -335,8 +369,16 @@ impl Render for BufferSearchBar {
|
||||||
.flex_none()
|
.flex_none()
|
||||||
.child(
|
.child(
|
||||||
IconButton::new("search-replace-next", ui::IconName::ReplaceNext)
|
IconButton::new("search-replace-next", ui::IconName::ReplaceNext)
|
||||||
.tooltip(move |cx| {
|
.tooltip({
|
||||||
Tooltip::for_action("Replace next", &ReplaceNext, cx)
|
let focus_handle = focus_handle.clone();
|
||||||
|
move |cx| {
|
||||||
|
Tooltip::for_action_in(
|
||||||
|
"Replace next match",
|
||||||
|
&ReplaceNext,
|
||||||
|
&focus_handle,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.on_click(
|
.on_click(
|
||||||
cx.listener(|this, _, cx| this.replace_next(&ReplaceNext, cx)),
|
cx.listener(|this, _, cx| this.replace_next(&ReplaceNext, cx)),
|
||||||
|
@ -344,8 +386,16 @@ impl Render for BufferSearchBar {
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
IconButton::new("search-replace-all", ui::IconName::ReplaceAll)
|
IconButton::new("search-replace-all", ui::IconName::ReplaceAll)
|
||||||
.tooltip(move |cx| {
|
.tooltip({
|
||||||
Tooltip::for_action("Replace all", &ReplaceAll, cx)
|
let focus_handle = focus_handle.clone();
|
||||||
|
move |cx| {
|
||||||
|
Tooltip::for_action_in(
|
||||||
|
"Replace all matches",
|
||||||
|
&ReplaceAll,
|
||||||
|
&focus_handle,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.on_click(
|
.on_click(
|
||||||
cx.listener(|this, _, cx| this.replace_all(&ReplaceAll, cx)),
|
cx.listener(|this, _, cx| this.replace_all(&ReplaceAll, cx)),
|
||||||
|
@ -719,10 +769,11 @@ impl BufferSearchBar {
|
||||||
fn render_search_option_button(
|
fn render_search_option_button(
|
||||||
&self,
|
&self,
|
||||||
option: SearchOptions,
|
option: SearchOptions,
|
||||||
|
focus_handle: FocusHandle,
|
||||||
action: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
|
action: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
|
||||||
) -> impl IntoElement {
|
) -> impl IntoElement {
|
||||||
let is_active = self.search_options.contains(option);
|
let is_active = self.search_options.contains(option);
|
||||||
option.as_button(is_active, action)
|
option.as_button(is_active, focus_handle, action)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn focus_editor(&mut self, _: &FocusEditor, cx: &mut ViewContext<Self>) {
|
pub fn focus_editor(&mut self, _: &FocusEditor, cx: &mut ViewContext<Self>) {
|
||||||
|
@ -1122,6 +1173,7 @@ impl BufferSearchBar {
|
||||||
});
|
});
|
||||||
cx.focus(handle);
|
cx.focus(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toggle_replace(&mut self, _: &ToggleReplace, cx: &mut ViewContext<Self>) {
|
fn toggle_replace(&mut self, _: &ToggleReplace, cx: &mut ViewContext<Self>) {
|
||||||
if self.active_searchable_item.is_some() {
|
if self.active_searchable_item.is_some() {
|
||||||
self.replace_enabled = !self.replace_enabled;
|
self.replace_enabled = !self.replace_enabled;
|
||||||
|
@ -1134,6 +1186,7 @@ impl BufferSearchBar {
|
||||||
cx.notify();
|
cx.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn replace_next(&mut self, _: &ReplaceNext, cx: &mut ViewContext<Self>) {
|
fn replace_next(&mut self, _: &ReplaceNext, cx: &mut ViewContext<Self>) {
|
||||||
let mut should_propagate = true;
|
let mut should_propagate = true;
|
||||||
if !self.dismissed && self.active_search.is_some() {
|
if !self.dismissed && self.active_search.is_some() {
|
||||||
|
@ -1161,6 +1214,7 @@ impl BufferSearchBar {
|
||||||
cx.stop_propagation();
|
cx.stop_propagation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn replace_all(&mut self, _: &ReplaceAll, cx: &mut ViewContext<Self>) {
|
pub fn replace_all(&mut self, _: &ReplaceAll, cx: &mut ViewContext<Self>) {
|
||||||
if !self.dismissed && self.active_search.is_some() {
|
if !self.dismissed && self.active_search.is_some() {
|
||||||
if let Some(searchable_item) = self.active_searchable_item.as_ref() {
|
if let Some(searchable_item) = self.active_searchable_item.as_ref() {
|
||||||
|
|
|
@ -1551,6 +1551,7 @@ impl Render for ProjectSearchBar {
|
||||||
return div();
|
return div();
|
||||||
};
|
};
|
||||||
let search = search.read(cx);
|
let search = search.read(cx);
|
||||||
|
let focus_handle = search.focus_handle(cx);
|
||||||
|
|
||||||
let query_column = h_flex()
|
let query_column = h_flex()
|
||||||
.flex_1()
|
.flex_1()
|
||||||
|
@ -1571,18 +1572,21 @@ impl Render for ProjectSearchBar {
|
||||||
h_flex()
|
h_flex()
|
||||||
.child(SearchOptions::CASE_SENSITIVE.as_button(
|
.child(SearchOptions::CASE_SENSITIVE.as_button(
|
||||||
self.is_option_enabled(SearchOptions::CASE_SENSITIVE, cx),
|
self.is_option_enabled(SearchOptions::CASE_SENSITIVE, cx),
|
||||||
|
focus_handle.clone(),
|
||||||
cx.listener(|this, _, cx| {
|
cx.listener(|this, _, cx| {
|
||||||
this.toggle_search_option(SearchOptions::CASE_SENSITIVE, cx);
|
this.toggle_search_option(SearchOptions::CASE_SENSITIVE, cx);
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
.child(SearchOptions::WHOLE_WORD.as_button(
|
.child(SearchOptions::WHOLE_WORD.as_button(
|
||||||
self.is_option_enabled(SearchOptions::WHOLE_WORD, cx),
|
self.is_option_enabled(SearchOptions::WHOLE_WORD, cx),
|
||||||
|
focus_handle.clone(),
|
||||||
cx.listener(|this, _, cx| {
|
cx.listener(|this, _, cx| {
|
||||||
this.toggle_search_option(SearchOptions::WHOLE_WORD, cx);
|
this.toggle_search_option(SearchOptions::WHOLE_WORD, cx);
|
||||||
}),
|
}),
|
||||||
))
|
))
|
||||||
.child(SearchOptions::REGEX.as_button(
|
.child(SearchOptions::REGEX.as_button(
|
||||||
self.is_option_enabled(SearchOptions::REGEX, cx),
|
self.is_option_enabled(SearchOptions::REGEX, cx),
|
||||||
|
focus_handle.clone(),
|
||||||
cx.listener(|this, _, cx| {
|
cx.listener(|this, _, cx| {
|
||||||
this.toggle_search_option(SearchOptions::REGEX, cx);
|
this.toggle_search_option(SearchOptions::REGEX, cx);
|
||||||
}),
|
}),
|
||||||
|
@ -1603,7 +1607,17 @@ impl Render for ProjectSearchBar {
|
||||||
.map(|search| search.read(cx).filters_enabled)
|
.map(|search| search.read(cx).filters_enabled)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
)
|
)
|
||||||
.tooltip(|cx| Tooltip::for_action("Toggle filters", &ToggleFilters, cx)),
|
.tooltip({
|
||||||
|
let focus_handle = focus_handle.clone();
|
||||||
|
move |cx| {
|
||||||
|
Tooltip::for_action_in(
|
||||||
|
"Toggle filters",
|
||||||
|
&ToggleFilters,
|
||||||
|
&focus_handle,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
IconButton::new("project-search-toggle-replace", IconName::Replace)
|
IconButton::new("project-search-toggle-replace", IconName::Replace)
|
||||||
|
@ -1616,7 +1630,17 @@ impl Render for ProjectSearchBar {
|
||||||
.map(|search| search.read(cx).replace_enabled)
|
.map(|search| search.read(cx).replace_enabled)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
)
|
)
|
||||||
.tooltip(|cx| Tooltip::for_action("Toggle replace", &ToggleReplace, cx)),
|
.tooltip({
|
||||||
|
let focus_handle = focus_handle.clone();
|
||||||
|
move |cx| {
|
||||||
|
Tooltip::for_action_in(
|
||||||
|
"Toggle replace",
|
||||||
|
&ToggleReplace,
|
||||||
|
&focus_handle,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1650,8 +1674,16 @@ impl Render for ProjectSearchBar {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.tooltip(|cx| {
|
.tooltip({
|
||||||
Tooltip::for_action("Go to previous match", &SelectPrevMatch, cx)
|
let focus_handle = focus_handle.clone();
|
||||||
|
move |cx| {
|
||||||
|
Tooltip::for_action_in(
|
||||||
|
"Go to previous match",
|
||||||
|
&SelectPrevMatch,
|
||||||
|
&focus_handle,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
|
@ -1664,7 +1696,17 @@ impl Render for ProjectSearchBar {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.tooltip(|cx| Tooltip::for_action("Go to next match", &SelectNextMatch, cx)),
|
.tooltip({
|
||||||
|
let focus_handle = focus_handle.clone();
|
||||||
|
move |cx| {
|
||||||
|
Tooltip::for_action_in(
|
||||||
|
"Go to next match",
|
||||||
|
&SelectNextMatch,
|
||||||
|
&focus_handle,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
h_flex()
|
h_flex()
|
||||||
|
@ -1702,6 +1744,7 @@ impl Render for ProjectSearchBar {
|
||||||
.border_color(cx.theme().colors().border)
|
.border_color(cx.theme().colors().border)
|
||||||
.rounded_lg()
|
.rounded_lg()
|
||||||
.child(self.render_text_input(&search.replacement_editor, cx));
|
.child(self.render_text_input(&search.replacement_editor, cx));
|
||||||
|
let focus_handle = search.replacement_editor.read(cx).focus_handle(cx);
|
||||||
let replace_actions = h_flex().when(search.replace_enabled, |this| {
|
let replace_actions = h_flex().when(search.replace_enabled, |this| {
|
||||||
this.child(
|
this.child(
|
||||||
IconButton::new("project-search-replace-next", IconName::ReplaceNext)
|
IconButton::new("project-search-replace-next", IconName::ReplaceNext)
|
||||||
|
@ -1712,7 +1755,17 @@ impl Render for ProjectSearchBar {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.tooltip(|cx| Tooltip::for_action("Replace next match", &ReplaceNext, cx)),
|
.tooltip({
|
||||||
|
let focus_handle = focus_handle.clone();
|
||||||
|
move |cx| {
|
||||||
|
Tooltip::for_action_in(
|
||||||
|
"Replace next match",
|
||||||
|
&ReplaceNext,
|
||||||
|
&focus_handle,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
IconButton::new("project-search-replace-all", IconName::ReplaceAll)
|
IconButton::new("project-search-replace-all", IconName::ReplaceAll)
|
||||||
|
@ -1723,7 +1776,17 @@ impl Render for ProjectSearchBar {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
.tooltip(|cx| Tooltip::for_action("Replace all matches", &ReplaceAll, cx)),
|
.tooltip({
|
||||||
|
let focus_handle = focus_handle.clone();
|
||||||
|
move |cx| {
|
||||||
|
Tooltip::for_action_in(
|
||||||
|
"Replace all matches",
|
||||||
|
&ReplaceAll,
|
||||||
|
&focus_handle,
|
||||||
|
cx,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
h_flex()
|
h_flex()
|
||||||
|
@ -1790,6 +1853,7 @@ impl Render for ProjectSearchBar {
|
||||||
search
|
search
|
||||||
.search_options
|
.search_options
|
||||||
.contains(SearchOptions::INCLUDE_IGNORED),
|
.contains(SearchOptions::INCLUDE_IGNORED),
|
||||||
|
focus_handle.clone(),
|
||||||
cx.listener(|this, _, cx| {
|
cx.listener(|this, _, cx| {
|
||||||
this.toggle_search_option(SearchOptions::INCLUDE_IGNORED, cx);
|
this.toggle_search_option(SearchOptions::INCLUDE_IGNORED, cx);
|
||||||
}),
|
}),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
pub use buffer_search::BufferSearchBar;
|
pub use buffer_search::BufferSearchBar;
|
||||||
use editor::SearchSettings;
|
use editor::SearchSettings;
|
||||||
use gpui::{actions, Action, AppContext, IntoElement};
|
use gpui::{actions, Action, AppContext, FocusHandle, IntoElement};
|
||||||
use project::search::SearchQuery;
|
use project::search::SearchQuery;
|
||||||
pub use project_search::ProjectSearchView;
|
pub use project_search::ProjectSearchView;
|
||||||
use ui::{prelude::*, Tooltip};
|
use ui::{prelude::*, Tooltip};
|
||||||
|
@ -106,6 +106,7 @@ impl SearchOptions {
|
||||||
pub fn as_button(
|
pub fn as_button(
|
||||||
&self,
|
&self,
|
||||||
active: bool,
|
active: bool,
|
||||||
|
focus_handle: FocusHandle,
|
||||||
action: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static,
|
action: impl Fn(&gpui::ClickEvent, &mut WindowContext) + 'static,
|
||||||
) -> impl IntoElement {
|
) -> impl IntoElement {
|
||||||
IconButton::new(self.label(), self.icon())
|
IconButton::new(self.label(), self.icon())
|
||||||
|
@ -115,7 +116,7 @@ impl SearchOptions {
|
||||||
.tooltip({
|
.tooltip({
|
||||||
let action = self.to_toggle_action();
|
let action = self.to_toggle_action();
|
||||||
let label = self.label();
|
let label = self.label();
|
||||||
move |cx| Tooltip::for_action(label, &*action, cx)
|
move |cx| Tooltip::for_action_in(label, &*action, &focus_handle, cx)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use gpui::{Action, IntoElement};
|
use gpui::{Action, FocusHandle, IntoElement};
|
||||||
use ui::IconButton;
|
use ui::IconButton;
|
||||||
use ui::{prelude::*, Tooltip};
|
use ui::{prelude::*, Tooltip};
|
||||||
|
|
||||||
|
@ -7,12 +7,13 @@ pub(super) fn render_nav_button(
|
||||||
active: bool,
|
active: bool,
|
||||||
tooltip: &'static str,
|
tooltip: &'static str,
|
||||||
action: &'static dyn Action,
|
action: &'static dyn Action,
|
||||||
|
focus_handle: FocusHandle,
|
||||||
) -> impl IntoElement {
|
) -> impl IntoElement {
|
||||||
IconButton::new(
|
IconButton::new(
|
||||||
SharedString::from(format!("search-nav-button-{}", action.name())),
|
SharedString::from(format!("search-nav-button-{}", action.name())),
|
||||||
icon,
|
icon,
|
||||||
)
|
)
|
||||||
.on_click(|_, cx| cx.dispatch_action(action.boxed_clone()))
|
.on_click(|_, cx| cx.dispatch_action(action.boxed_clone()))
|
||||||
.tooltip(move |cx| Tooltip::for_action(tooltip, action, cx))
|
.tooltip(move |cx| Tooltip::for_action_in(tooltip, action, &focus_handle, cx))
|
||||||
.disabled(!active)
|
.disabled(!active)
|
||||||
}
|
}
|
||||||
|
|
|
@ -166,7 +166,16 @@ impl TerminalPanel {
|
||||||
pub fn asssistant_enabled(&mut self, enabled: bool, cx: &mut ViewContext<Self>) {
|
pub fn asssistant_enabled(&mut self, enabled: bool, cx: &mut ViewContext<Self>) {
|
||||||
self.assistant_enabled = enabled;
|
self.assistant_enabled = enabled;
|
||||||
if enabled {
|
if enabled {
|
||||||
self.assistant_tab_bar_button = Some(cx.new_view(|_| InlineAssistTabBarButton).into());
|
let focus_handle = self
|
||||||
|
.pane
|
||||||
|
.read(cx)
|
||||||
|
.active_item()
|
||||||
|
.map(|item| item.focus_handle(cx))
|
||||||
|
.unwrap_or(self.focus_handle(cx));
|
||||||
|
self.assistant_tab_bar_button = Some(
|
||||||
|
cx.new_view(move |_| InlineAssistTabBarButton { focus_handle })
|
||||||
|
.into(),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
self.assistant_tab_bar_button = None;
|
self.assistant_tab_bar_button = None;
|
||||||
}
|
}
|
||||||
|
@ -859,16 +868,21 @@ impl Panel for TerminalPanel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct InlineAssistTabBarButton;
|
struct InlineAssistTabBarButton {
|
||||||
|
focus_handle: FocusHandle,
|
||||||
|
}
|
||||||
|
|
||||||
impl Render for InlineAssistTabBarButton {
|
impl Render for InlineAssistTabBarButton {
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||||
|
let focus_handle = self.focus_handle.clone();
|
||||||
IconButton::new("terminal_inline_assistant", IconName::ZedAssistant)
|
IconButton::new("terminal_inline_assistant", IconName::ZedAssistant)
|
||||||
.icon_size(IconSize::Small)
|
.icon_size(IconSize::Small)
|
||||||
.on_click(cx.listener(|_, _, cx| {
|
.on_click(cx.listener(|_, _, cx| {
|
||||||
cx.dispatch_action(InlineAssist::default().boxed_clone());
|
cx.dispatch_action(InlineAssist::default().boxed_clone());
|
||||||
}))
|
}))
|
||||||
.tooltip(move |cx| Tooltip::for_action("Inline Assist", &InlineAssist::default(), cx))
|
.tooltip(move |cx| {
|
||||||
|
Tooltip::for_action_in("Inline Assist", &InlineAssist::default(), &focus_handle, cx)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue