Use a handler instead of an action for clicks
This prevents dispatching actions on buttons that were not the target of the click. Co-Authored-By: Marshall <marshall@zed.dev>
This commit is contained in:
parent
e4884f1d76
commit
cc9eff89f5
5 changed files with 48 additions and 40 deletions
|
@ -2574,7 +2574,9 @@ impl Render for InlineAssistant {
|
||||||
.w(measurements.gutter_width)
|
.w(measurements.gutter_width)
|
||||||
.child(
|
.child(
|
||||||
IconButton::new("include_conversation", Icon::Ai)
|
IconButton::new("include_conversation", Icon::Ai)
|
||||||
.action(Box::new(ToggleIncludeConversation))
|
.on_click(cx.listener(|this, _, cx| {
|
||||||
|
this.toggle_include_conversation(&ToggleIncludeConversation, cx)
|
||||||
|
}))
|
||||||
.selected(self.include_conversation)
|
.selected(self.include_conversation)
|
||||||
.tooltip(|cx| {
|
.tooltip(|cx| {
|
||||||
Tooltip::for_action(
|
Tooltip::for_action(
|
||||||
|
@ -2587,7 +2589,9 @@ impl Render for InlineAssistant {
|
||||||
.children(if SemanticIndex::enabled(cx) {
|
.children(if SemanticIndex::enabled(cx) {
|
||||||
Some(
|
Some(
|
||||||
IconButton::new("retrieve_context", Icon::MagnifyingGlass)
|
IconButton::new("retrieve_context", Icon::MagnifyingGlass)
|
||||||
.action(Box::new(ToggleRetrieveContext))
|
.on_click(cx.listener(|this, _, cx| {
|
||||||
|
this.toggle_retrieve_context(&ToggleRetrieveContext, cx)
|
||||||
|
}))
|
||||||
.selected(self.retrieve_context)
|
.selected(self.retrieve_context)
|
||||||
.tooltip(|cx| {
|
.tooltip(|cx| {
|
||||||
Tooltip::for_action(
|
Tooltip::for_action(
|
||||||
|
|
|
@ -2,8 +2,8 @@
|
||||||
use editor::Editor;
|
use editor::Editor;
|
||||||
|
|
||||||
use gpui::{
|
use gpui::{
|
||||||
Action, Div, ElementId, EventEmitter, InteractiveElement, ParentElement, Render, Stateful,
|
Action, ClickEvent, Div, ElementId, EventEmitter, InteractiveElement, ParentElement, Render,
|
||||||
Styled, Subscription, View, ViewContext, WeakView,
|
Stateful, Styled, Subscription, View, ViewContext, WeakView,
|
||||||
};
|
};
|
||||||
use search::BufferSearchBar;
|
use search::BufferSearchBar;
|
||||||
use ui::{prelude::*, ButtonSize, ButtonStyle, Icon, IconButton, IconSize, Tooltip};
|
use ui::{prelude::*, ButtonSize, ButtonStyle, Icon, IconButton, IconSize, Tooltip};
|
||||||
|
@ -41,19 +41,24 @@ impl Render for QuickActionBar {
|
||||||
type Element = Stateful<Div>;
|
type Element = Stateful<Div>;
|
||||||
|
|
||||||
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
fn render(&mut self, cx: &mut ViewContext<Self>) -> Self::Element {
|
||||||
|
let buffer_search_bar = self.buffer_search_bar.clone();
|
||||||
let search_button = QuickActionBarButton::new(
|
let search_button = QuickActionBarButton::new(
|
||||||
"toggle buffer search",
|
"toggle buffer search",
|
||||||
Icon::MagnifyingGlass,
|
Icon::MagnifyingGlass,
|
||||||
!self.buffer_search_bar.read(cx).is_dismissed(),
|
!self.buffer_search_bar.read(cx).is_dismissed(),
|
||||||
Box::new(search::buffer_search::Deploy { focus: false }),
|
Box::new(search::buffer_search::Deploy { focus: false }),
|
||||||
"Buffer Search",
|
"Buffer Search",
|
||||||
|
move |_, cx| {
|
||||||
|
buffer_search_bar.update(cx, |search_bar, cx| search_bar.toggle(cx));
|
||||||
|
},
|
||||||
);
|
);
|
||||||
let assistant_button = QuickActionBarButton::new(
|
let assistant_button = QuickActionBarButton::new(
|
||||||
"toggle inline assitant",
|
"toggle inline assistant",
|
||||||
Icon::MagicWand,
|
Icon::MagicWand,
|
||||||
false,
|
false,
|
||||||
Box::new(gpui::NoAction),
|
Box::new(gpui::NoAction),
|
||||||
"Inline assistant",
|
"Inline assistant",
|
||||||
|
|_, _cx| todo!(),
|
||||||
);
|
);
|
||||||
h_stack()
|
h_stack()
|
||||||
.id("quick action bar")
|
.id("quick action bar")
|
||||||
|
@ -154,6 +159,7 @@ struct QuickActionBarButton {
|
||||||
action: Box<dyn Action>,
|
action: Box<dyn Action>,
|
||||||
tooltip: SharedString,
|
tooltip: SharedString,
|
||||||
tooltip_meta: Option<SharedString>,
|
tooltip_meta: Option<SharedString>,
|
||||||
|
on_click: Box<dyn Fn(&ClickEvent, &mut WindowContext)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl QuickActionBarButton {
|
impl QuickActionBarButton {
|
||||||
|
@ -163,6 +169,7 @@ impl QuickActionBarButton {
|
||||||
toggled: bool,
|
toggled: bool,
|
||||||
action: Box<dyn Action>,
|
action: Box<dyn Action>,
|
||||||
tooltip: impl Into<SharedString>,
|
tooltip: impl Into<SharedString>,
|
||||||
|
on_click: impl Fn(&ClickEvent, &mut WindowContext) + 'static,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
id: id.into(),
|
id: id.into(),
|
||||||
|
@ -171,6 +178,7 @@ impl QuickActionBarButton {
|
||||||
action,
|
action,
|
||||||
tooltip: tooltip.into(),
|
tooltip: tooltip.into(),
|
||||||
tooltip_meta: None,
|
tooltip_meta: None,
|
||||||
|
on_click: Box::new(on_click),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,10 +209,7 @@ impl RenderOnce for QuickActionBarButton {
|
||||||
Tooltip::for_action(tooltip.clone(), &*action, cx)
|
Tooltip::for_action(tooltip.clone(), &*action, cx)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.on_click({
|
.on_click(move |event, cx| (self.on_click)(event, cx))
|
||||||
let action = self.action.boxed_clone();
|
|
||||||
move |_, cx| cx.dispatch_action(action.boxed_clone())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ use project::search::SearchQuery;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::{any::Any, sync::Arc};
|
use std::{any::Any, sync::Arc};
|
||||||
|
|
||||||
use ui::{h_stack, Icon, IconButton, IconElement};
|
use ui::{h_stack, Clickable, Icon, IconButton, IconElement};
|
||||||
use util::ResultExt;
|
use util::ResultExt;
|
||||||
use workspace::{
|
use workspace::{
|
||||||
item::ItemHandle,
|
item::ItemHandle,
|
||||||
|
@ -161,16 +161,6 @@ impl Render for BufferSearchBar {
|
||||||
|
|
||||||
Some(ui::Label::new(message))
|
Some(ui::Label::new(message))
|
||||||
});
|
});
|
||||||
let nav_button_for_direction = |icon, direction| {
|
|
||||||
render_nav_button(
|
|
||||||
icon,
|
|
||||||
self.active_match_index.is_some(),
|
|
||||||
cx.listener(move |this, _, cx| match direction {
|
|
||||||
Direction::Prev => this.select_prev_match(&Default::default(), cx),
|
|
||||||
Direction::Next => this.select_next_match(&Default::default(), cx),
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
let should_show_replace_input = self.replace_enabled && supported_options.replacement;
|
let should_show_replace_input = self.replace_enabled && supported_options.replacement;
|
||||||
let replace_all = should_show_replace_input
|
let replace_all = should_show_replace_input
|
||||||
.then(|| super::render_replace_button(ReplaceAll, ui::Icon::ReplaceAll));
|
.then(|| super::render_replace_button(ReplaceAll, ui::Icon::ReplaceAll));
|
||||||
|
@ -237,15 +227,21 @@ impl Render for BufferSearchBar {
|
||||||
h_stack()
|
h_stack()
|
||||||
.gap_0p5()
|
.gap_0p5()
|
||||||
.flex_none()
|
.flex_none()
|
||||||
.child(self.render_action_button())
|
.child(self.render_action_button(cx))
|
||||||
.children(match_count)
|
.children(match_count)
|
||||||
.child(nav_button_for_direction(
|
.child(render_nav_button(
|
||||||
ui::Icon::ChevronLeft,
|
ui::Icon::ChevronLeft,
|
||||||
Direction::Prev,
|
self.active_match_index.is_some(),
|
||||||
|
cx.listener(move |this, _, cx| {
|
||||||
|
this.select_prev_match(&Default::default(), cx);
|
||||||
|
}),
|
||||||
))
|
))
|
||||||
.child(nav_button_for_direction(
|
.child(render_nav_button(
|
||||||
ui::Icon::ChevronRight,
|
ui::Icon::ChevronRight,
|
||||||
Direction::Next,
|
self.active_match_index.is_some(),
|
||||||
|
cx.listener(move |this, _, cx| {
|
||||||
|
this.select_next_match(&Default::default(), cx);
|
||||||
|
}),
|
||||||
)),
|
)),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -317,13 +313,7 @@ impl BufferSearchBar {
|
||||||
pane.update(cx, |this, cx| {
|
pane.update(cx, |this, cx| {
|
||||||
this.toolbar().update(cx, |this, cx| {
|
this.toolbar().update(cx, |this, cx| {
|
||||||
if let Some(search_bar) = this.item_of_type::<BufferSearchBar>() {
|
if let Some(search_bar) = this.item_of_type::<BufferSearchBar>() {
|
||||||
search_bar.update(cx, |this, cx| {
|
search_bar.update(cx, |this, cx| this.toggle(cx));
|
||||||
if this.is_dismissed() {
|
|
||||||
this.show(cx);
|
|
||||||
} else {
|
|
||||||
this.dismiss(&Dismiss, cx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let view = cx.build_view(|cx| BufferSearchBar::new(cx));
|
let view = cx.build_view(|cx| BufferSearchBar::new(cx));
|
||||||
|
@ -487,6 +477,14 @@ impl BufferSearchBar {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn toggle(&mut self, cx: &mut ViewContext<Self>) {
|
||||||
|
if self.is_dismissed() {
|
||||||
|
self.show(cx);
|
||||||
|
} else {
|
||||||
|
self.dismiss(&Dismiss, cx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn show(&mut self, cx: &mut ViewContext<Self>) -> bool {
|
pub fn show(&mut self, cx: &mut ViewContext<Self>) -> bool {
|
||||||
if self.active_searchable_item.is_none() {
|
if self.active_searchable_item.is_none() {
|
||||||
return false;
|
return false;
|
||||||
|
@ -588,12 +586,14 @@ impl BufferSearchBar {
|
||||||
self.update_matches(cx)
|
self.update_matches(cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_action_button(&self) -> impl IntoElement {
|
fn render_action_button(&self, cx: &mut ViewContext<Self>) -> impl IntoElement {
|
||||||
// let tooltip_style = theme.tooltip.clone();
|
// let tooltip_style = theme.tooltip.clone();
|
||||||
|
|
||||||
// let style = theme.search.action_button.clone();
|
// let style = theme.search.action_button.clone();
|
||||||
|
|
||||||
IconButton::new(0, ui::Icon::SelectAll).action(Box::new(SelectAllMatches))
|
IconButton::new("select-all", ui::Icon::SelectAll).on_click(cx.listener(|this, _, cx| {
|
||||||
|
this.select_all_matches(&SelectAllMatches, cx);
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn activate_search_mode(&mut self, mode: SearchMode, cx: &mut ViewContext<Self>) {
|
pub fn activate_search_mode(&mut self, mode: SearchMode, cx: &mut ViewContext<Self>) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use gpui::{Action, AnyView, DefiniteLength};
|
use gpui::{AnyView, DefiniteLength};
|
||||||
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, Icon, IconSize};
|
use crate::{ButtonCommon, ButtonLike, ButtonSize, ButtonStyle, Icon, IconSize};
|
||||||
|
@ -39,10 +39,6 @@ impl IconButton {
|
||||||
self.selected_icon = icon.into();
|
self.selected_icon = icon.into();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn action(self, action: Box<dyn Action>) -> Self {
|
|
||||||
self.on_click(move |_event, cx| cx.dispatch_action(action.boxed_clone()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Disableable for IconButton {
|
impl Disableable for IconButton {
|
||||||
|
|
|
@ -724,7 +724,10 @@ impl Render for PanelButtons {
|
||||||
.trigger(
|
.trigger(
|
||||||
IconButton::new(name, icon)
|
IconButton::new(name, icon)
|
||||||
.selected(is_active_button)
|
.selected(is_active_button)
|
||||||
.action(action.boxed_clone())
|
.on_click({
|
||||||
|
let action = action.boxed_clone();
|
||||||
|
move |_, cx| cx.dispatch_action(action.boxed_clone())
|
||||||
|
})
|
||||||
.tooltip(move |cx| {
|
.tooltip(move |cx| {
|
||||||
Tooltip::for_action(tooltip.clone(), &*action, cx)
|
Tooltip::for_action(tooltip.clone(), &*action, cx)
|
||||||
}),
|
}),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue