Render the search UI on a separate row from the breadcrumbs

- In project search, render it above the breadcrumbs
- In buffer search, render it below

Co-Authored-By: Antonio Scandurra <me@as-cii.com>
Co-Authored-By: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
Nathan Sobo
2022-03-31 10:36:39 -06:00
co-authored by Antonio Scandurra Max Brunsfeld
parent 0453dd1101
commit 8bfac63e0d
9 changed files with 207 additions and 125 deletions
+75 -61
View File
@@ -8,13 +8,17 @@ use gpui::{
use language::OffsetRangeExt;
use project::search::SearchQuery;
use std::ops::Range;
use workspace::{ItemHandle, Pane, Settings, ToolbarItemView};
use workspace::{ItemHandle, Pane, Settings, ToolbarItemLocation, ToolbarItemView};
action!(Deploy, bool);
action!(Dismiss);
action!(FocusEditor);
action!(ToggleSearchOption, SearchOption);
pub enum Event {
UpdateLocation,
}
pub fn init(cx: &mut MutableAppContext) {
cx.add_bindings([
Binding::new("cmd-f", Deploy(true), Some("Editor && mode == full")),
@@ -57,7 +61,7 @@ pub struct BufferSearchBar {
}
impl Entity for BufferSearchBar {
type Event = ();
type Event = Event;
}
impl View for BufferSearchBar {
@@ -70,70 +74,66 @@ impl View for BufferSearchBar {
}
fn render(&mut self, cx: &mut RenderContext<Self>) -> ElementBox {
if self.dismissed || self.active_editor.is_none() {
Empty::new().boxed()
let theme = cx.global::<Settings>().theme.clone();
let editor_container = if self.query_contains_error {
theme.search.invalid_editor
} else {
let theme = cx.global::<Settings>().theme.clone();
let editor_container = if self.query_contains_error {
theme.search.invalid_editor
} else {
theme.search.editor.input.container
};
Flex::row()
.with_child(
Flex::row()
.with_child(ChildView::new(&self.query_editor).flex(1., true).boxed())
.with_children(self.active_editor.as_ref().and_then(|editor| {
let matches = self.editors_with_matches.get(&editor.downgrade())?;
let message = if let Some(match_ix) = self.active_match_index {
format!("{}/{}", match_ix + 1, matches.len())
} else {
"No matches".to_string()
};
theme.search.editor.input.container
};
Flex::row()
.with_child(
Flex::row()
.with_child(ChildView::new(&self.query_editor).flex(1., true).boxed())
.with_children(self.active_editor.as_ref().and_then(|editor| {
let matches = self.editors_with_matches.get(&editor.downgrade())?;
let message = if let Some(match_ix) = self.active_match_index {
format!("{}/{}", match_ix + 1, matches.len())
} else {
"No matches".to_string()
};
Some(
Label::new(message, theme.search.match_index.text.clone())
.contained()
.with_style(theme.search.match_index.container)
.aligned()
.boxed(),
)
}))
.contained()
.with_style(editor_container)
.aligned()
.constrained()
.with_max_width(theme.search.editor.max_width)
.boxed(),
)
.with_child(
Flex::row()
.with_child(self.render_nav_button("<", Direction::Prev, cx))
.with_child(self.render_nav_button(">", Direction::Next, cx))
.aligned()
.boxed(),
)
.with_child(
Flex::row()
.with_child(self.render_search_option(
"Case",
SearchOption::CaseSensitive,
cx,
))
.with_child(self.render_search_option("Word", SearchOption::WholeWord, cx))
.with_child(self.render_search_option("Regex", SearchOption::Regex, cx))
.contained()
.with_style(theme.search.option_button_group)
.aligned()
.boxed(),
)
.named("search bar")
}
Some(
Label::new(message, theme.search.match_index.text.clone())
.contained()
.with_style(theme.search.match_index.container)
.aligned()
.boxed(),
)
}))
.contained()
.with_style(editor_container)
.aligned()
.constrained()
.with_max_width(theme.search.editor.max_width)
.boxed(),
)
.with_child(
Flex::row()
.with_child(self.render_nav_button("<", Direction::Prev, cx))
.with_child(self.render_nav_button(">", Direction::Next, cx))
.aligned()
.boxed(),
)
.with_child(
Flex::row()
.with_child(self.render_search_option("Case", SearchOption::CaseSensitive, cx))
.with_child(self.render_search_option("Word", SearchOption::WholeWord, cx))
.with_child(self.render_search_option("Regex", SearchOption::Regex, cx))
.contained()
.with_style(theme.search.option_button_group)
.aligned()
.boxed(),
)
.named("search bar")
}
}
impl ToolbarItemView for BufferSearchBar {
fn set_active_pane_item(&mut self, item: Option<&dyn ItemHandle>, cx: &mut ViewContext<Self>) {
fn set_active_pane_item(
&mut self,
item: Option<&dyn ItemHandle>,
cx: &mut ViewContext<Self>,
) -> ToolbarItemLocation {
cx.notify();
self.active_editor_subscription.take();
self.active_editor.take();
@@ -145,9 +145,21 @@ impl ToolbarItemView for BufferSearchBar {
Some(cx.subscribe(&editor, Self::on_active_editor_event));
self.active_editor = Some(editor);
self.update_matches(false, cx);
return;
if !self.dismissed {
return ToolbarItemLocation::Secondary;
}
}
}
ToolbarItemLocation::Hidden
}
fn location_for_event(&self, _: &Self::Event, _: ToolbarItemLocation) -> ToolbarItemLocation {
if self.active_editor.is_some() && !self.dismissed {
ToolbarItemLocation::Secondary
} else {
ToolbarItemLocation::Hidden
}
}
}
@@ -186,6 +198,7 @@ impl BufferSearchBar {
if let Some(active_editor) = self.active_editor.as_ref() {
cx.focus(active_editor);
}
cx.emit(Event::UpdateLocation);
cx.notify();
}
@@ -234,6 +247,7 @@ impl BufferSearchBar {
self.dismissed = false;
cx.notify();
cx.emit(Event::UpdateLocation);
true
}
+10 -5
View File
@@ -16,7 +16,9 @@ use std::{
path::PathBuf,
};
use util::ResultExt as _;
use workspace::{Item, ItemNavHistory, Pane, Settings, ToolbarItemView, Workspace};
use workspace::{
Item, ItemNavHistory, Pane, Settings, ToolbarItemLocation, ToolbarItemView, Workspace,
};
action!(Deploy);
action!(Search);
@@ -56,7 +58,7 @@ struct ProjectSearch {
active_query: Option<SearchQuery>,
}
struct ProjectSearchView {
pub struct ProjectSearchView {
model: ModelHandle<ProjectSearch>,
query_editor: ViewHandle<Editor>,
results_editor: ViewHandle<Editor>,
@@ -136,7 +138,7 @@ impl ProjectSearch {
}
}
enum ViewEvent {
pub enum ViewEvent {
UpdateTab,
}
@@ -748,14 +750,17 @@ impl ToolbarItemView for ProjectSearchBar {
&mut self,
active_pane_item: Option<&dyn workspace::ItemHandle>,
cx: &mut ViewContext<Self>,
) {
) -> ToolbarItemLocation {
cx.notify();
self.subscription = None;
self.active_project_search = None;
if let Some(search) = active_pane_item.and_then(|i| i.downcast::<ProjectSearchView>()) {
self.subscription = Some(cx.observe(&search, |_, _, cx| cx.notify()));
self.active_project_search = Some(search);
ToolbarItemLocation::PrimaryLeft
} else {
ToolbarItemLocation::Hidden
}
cx.notify();
}
}
+1 -1
View File
@@ -1,7 +1,7 @@
pub use buffer_search::BufferSearchBar;
use editor::{Anchor, MultiBufferSnapshot};
use gpui::{action, MutableAppContext};
pub use project_search::ProjectSearchBar;
pub use project_search::{ProjectSearchBar, ProjectSearchView};
use std::{
cmp::{self, Ordering},
ops::Range,