Merge branch 'main' into channel-guests
This commit is contained in:
@@ -223,6 +223,7 @@ impl Render for BufferSearchBar {
|
||||
.gap_2()
|
||||
.border_1()
|
||||
.border_color(editor_border)
|
||||
.min_w(rems(384. / 16.))
|
||||
.rounded_lg()
|
||||
.child(IconElement::new(Icon::MagnifyingGlass))
|
||||
.child(self.render_text_input(&self.query_editor, cx))
|
||||
@@ -422,89 +423,134 @@ impl ToolbarItemView for BufferSearchBar {
|
||||
}
|
||||
}
|
||||
|
||||
impl BufferSearchBar {
|
||||
fn register(workspace: &mut Workspace) {
|
||||
workspace.register_action(move |workspace, deploy: &Deploy, cx| {
|
||||
let pane = workspace.active_pane();
|
||||
/// Registrar inverts the dependency between search and it's downstream user, allowing said downstream user to register search action without knowing exactly what those actions are.
|
||||
pub trait SearchActionsRegistrar {
|
||||
fn register_handler<A: Action>(
|
||||
&mut self,
|
||||
callback: fn(&mut BufferSearchBar, &A, &mut ViewContext<BufferSearchBar>),
|
||||
);
|
||||
}
|
||||
|
||||
pane.update(cx, |this, cx| {
|
||||
this.toolbar().update(cx, |this, cx| {
|
||||
type GetSearchBar<T> =
|
||||
for<'a, 'b> fn(&'a T, &'a mut ViewContext<'b, T>) -> Option<View<BufferSearchBar>>;
|
||||
|
||||
/// Registers search actions on a div that can be taken out.
|
||||
pub struct DivRegistrar<'a, 'b, T: 'static> {
|
||||
div: Option<Div>,
|
||||
cx: &'a mut ViewContext<'b, T>,
|
||||
search_getter: GetSearchBar<T>,
|
||||
}
|
||||
|
||||
impl<'a, 'b, T: 'static> DivRegistrar<'a, 'b, T> {
|
||||
pub fn new(search_getter: GetSearchBar<T>, cx: &'a mut ViewContext<'b, T>) -> Self {
|
||||
Self {
|
||||
div: Some(div()),
|
||||
cx,
|
||||
search_getter,
|
||||
}
|
||||
}
|
||||
pub fn into_div(self) -> Div {
|
||||
// This option is always Some; it's an option in the first place because we want to call methods
|
||||
// on div that require ownership.
|
||||
self.div.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: 'static> SearchActionsRegistrar for DivRegistrar<'_, '_, T> {
|
||||
fn register_handler<A: gpui::Action>(
|
||||
&mut self,
|
||||
callback: fn(&mut BufferSearchBar, &A, &mut ViewContext<BufferSearchBar>),
|
||||
) {
|
||||
let getter = self.search_getter;
|
||||
self.div = self.div.take().map(|div| {
|
||||
div.on_action(self.cx.listener(move |this, action, cx| {
|
||||
(getter)(this, cx)
|
||||
.clone()
|
||||
.map(|search_bar| search_bar.update(cx, |this, cx| callback(this, action, cx)));
|
||||
}))
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Register actions for an active pane.
|
||||
impl SearchActionsRegistrar for Workspace {
|
||||
fn register_handler<A: Action>(
|
||||
&mut self,
|
||||
callback: fn(&mut BufferSearchBar, &A, &mut ViewContext<BufferSearchBar>),
|
||||
) {
|
||||
self.register_action(move |workspace, action: &A, cx| {
|
||||
let pane = workspace.active_pane();
|
||||
pane.update(cx, move |this, cx| {
|
||||
this.toolbar().update(cx, move |this, cx| {
|
||||
if let Some(search_bar) = this.item_of_type::<BufferSearchBar>() {
|
||||
search_bar.update(cx, |this, cx| {
|
||||
this.deploy(deploy, cx);
|
||||
});
|
||||
return;
|
||||
search_bar.update(cx, move |this, cx| callback(this, action, cx));
|
||||
cx.notify();
|
||||
}
|
||||
let view = cx.new_view(|cx| BufferSearchBar::new(cx));
|
||||
this.add_item(view.clone(), cx);
|
||||
view.update(cx, |this, cx| this.deploy(deploy, cx));
|
||||
cx.notify();
|
||||
})
|
||||
});
|
||||
});
|
||||
fn register_action<A: Action>(
|
||||
workspace: &mut Workspace,
|
||||
update: fn(&mut BufferSearchBar, &A, &mut ViewContext<BufferSearchBar>),
|
||||
) {
|
||||
workspace.register_action(move |workspace, action: &A, cx| {
|
||||
let pane = workspace.active_pane();
|
||||
pane.update(cx, move |this, cx| {
|
||||
this.toolbar().update(cx, move |this, cx| {
|
||||
if let Some(search_bar) = this.item_of_type::<BufferSearchBar>() {
|
||||
search_bar.update(cx, move |this, cx| update(this, action, cx));
|
||||
cx.notify();
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
register_action(workspace, |this, action: &ToggleCaseSensitive, cx| {
|
||||
}
|
||||
}
|
||||
impl BufferSearchBar {
|
||||
pub fn register_inner(registrar: &mut impl SearchActionsRegistrar) {
|
||||
registrar.register_handler(|this, action: &ToggleCaseSensitive, cx| {
|
||||
if this.supported_options().case {
|
||||
this.toggle_case_sensitive(action, cx);
|
||||
}
|
||||
});
|
||||
register_action(workspace, |this, action: &ToggleWholeWord, cx| {
|
||||
|
||||
registrar.register_handler(|this, action: &ToggleWholeWord, cx| {
|
||||
if this.supported_options().word {
|
||||
this.toggle_whole_word(action, cx);
|
||||
}
|
||||
});
|
||||
register_action(workspace, |this, action: &ToggleReplace, cx| {
|
||||
|
||||
registrar.register_handler(|this, action: &ToggleReplace, cx| {
|
||||
if this.supported_options().replacement {
|
||||
this.toggle_replace(action, cx);
|
||||
}
|
||||
});
|
||||
register_action(workspace, |this, _: &ActivateRegexMode, cx| {
|
||||
|
||||
registrar.register_handler(|this, _: &ActivateRegexMode, cx| {
|
||||
if this.supported_options().regex {
|
||||
this.activate_search_mode(SearchMode::Regex, cx);
|
||||
}
|
||||
});
|
||||
register_action(workspace, |this, _: &ActivateTextMode, cx| {
|
||||
|
||||
registrar.register_handler(|this, _: &ActivateTextMode, cx| {
|
||||
this.activate_search_mode(SearchMode::Text, cx);
|
||||
});
|
||||
register_action(workspace, |this, action: &CycleMode, cx| {
|
||||
|
||||
registrar.register_handler(|this, action: &CycleMode, cx| {
|
||||
if this.supported_options().regex {
|
||||
// If regex is not supported then search has just one mode (text) - in that case there's no point in supporting
|
||||
// cycling.
|
||||
this.cycle_mode(action, cx)
|
||||
}
|
||||
});
|
||||
register_action(workspace, |this, action: &SelectNextMatch, cx| {
|
||||
|
||||
registrar.register_handler(|this, action: &SelectNextMatch, cx| {
|
||||
this.select_next_match(action, cx);
|
||||
});
|
||||
register_action(workspace, |this, action: &SelectPrevMatch, cx| {
|
||||
registrar.register_handler(|this, action: &SelectPrevMatch, cx| {
|
||||
this.select_prev_match(action, cx);
|
||||
});
|
||||
register_action(workspace, |this, action: &SelectAllMatches, cx| {
|
||||
registrar.register_handler(|this, action: &SelectAllMatches, cx| {
|
||||
this.select_all_matches(action, cx);
|
||||
});
|
||||
register_action(workspace, |this, _: &editor::Cancel, cx| {
|
||||
registrar.register_handler(|this, _: &editor::Cancel, cx| {
|
||||
if !this.dismissed {
|
||||
this.dismiss(&Dismiss, cx);
|
||||
return;
|
||||
}
|
||||
cx.propagate();
|
||||
});
|
||||
registrar.register_handler(|this, deploy, cx| {
|
||||
this.deploy(deploy, cx);
|
||||
})
|
||||
}
|
||||
fn register(workspace: &mut Workspace) {
|
||||
Self::register_inner(workspace);
|
||||
}
|
||||
pub fn new(cx: &mut ViewContext<Self>) -> Self {
|
||||
let query_editor = cx.new_view(|cx| Editor::single_line(cx));
|
||||
|
||||
Reference in New Issue
Block a user