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:
Antonio Scandurra 2023-12-06 19:12:01 +01:00
parent e4884f1d76
commit cc9eff89f5
5 changed files with 48 additions and 40 deletions

View file

@ -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(

View file

@ -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())
})
} }
} }

View file

@ -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>) {

View file

@ -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 {

View file

@ -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)
}), }),