Add filter button.

Piotr Osiewicz created

Move semantic & regex buttons to the right hand side.
Add default tab name for the new project search.

Change summary

crates/search/src/project_search.rs | 135 +++++++++++++++++++-----------
1 file changed, 86 insertions(+), 49 deletions(-)

Detailed changes

crates/search/src/project_search.rs 🔗

@@ -102,6 +102,7 @@ pub struct ProjectSearchView {
     query_editor_was_focused: bool,
     included_files_editor: ViewHandle<Editor>,
     excluded_files_editor: ViewHandle<Editor>,
+    filters_enabled: bool,
 }
 
 struct SemanticSearchState {
@@ -365,11 +366,19 @@ impl Item for ProjectSearchView {
                     .contained()
                     .with_margin_right(tab_theme.spacing),
             )
-            .with_children(self.model.read(cx).active_query.as_ref().map(|query| {
-                let query_text = util::truncate_and_trailoff(query.as_str(), MAX_TAB_TITLE_LEN);
-
-                Label::new(query_text, tab_theme.label.clone()).aligned()
-            }))
+            .with_child({
+                let tab_name: Option<Cow<_>> =
+                    self.model.read(cx).active_query.as_ref().map(|query| {
+                        let query_text =
+                            util::truncate_and_trailoff(query.as_str(), MAX_TAB_TITLE_LEN);
+                        query_text.into()
+                    });
+                Label::new(
+                    tab_name.unwrap_or("Project search".into()),
+                    tab_theme.label.clone(),
+                )
+                .aligned()
+            })
             .into_any()
     }
 
@@ -565,7 +574,7 @@ impl ProjectSearchView {
             cx.emit(ViewEvent::EditorEvent(event.clone()))
         })
         .detach();
-
+        let filters_enabled = false;
         let mut this = ProjectSearchView {
             search_id: model.read(cx).search_id,
             model,
@@ -578,6 +587,7 @@ impl ProjectSearchView {
             query_editor_was_focused: false,
             included_files_editor,
             excluded_files_editor,
+            filters_enabled,
         };
         this.model_changed(cx);
         this
@@ -1012,6 +1022,19 @@ impl ProjectSearchBar {
             false
         }
     }
+    fn toggle_filters(&mut self, cx: &mut ViewContext<Self>) -> bool {
+        if let Some(search_view) = self.active_project_search.as_ref() {
+            search_view.update(cx, |search_view, cx| {
+                search_view.filters_enabled = !search_view.filters_enabled;
+                search_view.semantic = None;
+                search_view.search(cx);
+            });
+            cx.notify();
+            true
+        } else {
+            false
+        }
+    }
 
     fn toggle_semantic_search(&mut self, cx: &mut ViewContext<Self>) -> bool {
         if let Some(search_view) = self.active_project_search.as_ref() {
@@ -1249,9 +1272,56 @@ impl View for ProjectSearchBar {
                 .aligned()
                 .left()
             });
+            let filters = search.filters_enabled.then(|| {
+                Flex::row()
+                    .with_child(
+                        Flex::row()
+                            .with_child(included_files_view)
+                            .contained()
+                            .with_style(include_container_style)
+                            .aligned()
+                            .constrained()
+                            .with_min_width(theme.search.include_exclude_editor.min_width)
+                            .with_max_width(theme.search.include_exclude_editor.max_width)
+                            .flex(1., false),
+                    )
+                    .with_child(
+                        Flex::row()
+                            .with_child(excluded_files_view)
+                            .contained()
+                            .with_style(exclude_container_style)
+                            .aligned()
+                            .constrained()
+                            .with_min_width(theme.search.include_exclude_editor.min_width)
+                            .with_max_width(theme.search.include_exclude_editor.max_width)
+                            .flex(1., false),
+                    )
+            });
+            let filter_button = {
+                let tooltip_style = theme::current(cx).tooltip.clone();
+                let is_active = search.filters_enabled;
+                MouseEventHandler::<Self, _>::new(0, cx, |state, cx| {
+                    let theme = theme::current(cx);
+                    let style = theme
+                        .search
+                        .option_button
+                        .in_state(is_active)
+                        .style_for(state);
+                    Label::new("Filter", style.text.clone())
+                        .contained()
+                        .with_style(style.container)
+                })
+                .on_click(MouseButton::Left, move |_, this, cx| {
+                    this.toggle_filters(cx);
+                })
+                .with_cursor_style(CursorStyle::PointingHand)
+                .with_tooltip::<Self>(0, "Toggle filters".into(), None, tooltip_style, cx)
+                .into_any()
+            };
             let case_button = self.render_option_button("Case", SearchOptions::CASE_SENSITIVE, cx);
             let word_button = self.render_option_button("Word", SearchOptions::WHOLE_WORD, cx);
             let regex_button = self.render_option_button("Regex", SearchOptions::REGEX, cx);
+
             let semantic_index =
                 SemanticIndex::enabled(cx).then(|| self.render_semantic_search_button(cx));
             Flex::row()
@@ -1288,10 +1358,9 @@ impl View for ProjectSearchBar {
                                 )
                                 .with_child(
                                     Flex::row()
-                                        .with_children(semantic_index)
                                         .with_child(case_button)
                                         .with_child(word_button)
-                                        .with_child(regex_button)
+                                        .with_child(filter_button)
                                         .contained()
                                         .with_style(theme.search.option_button_group)
                                         .aligned()
@@ -1300,52 +1369,20 @@ impl View for ProjectSearchBar {
                                 .contained()
                                 .with_margin_bottom(row_spacing),
                         )
-                        .with_child(
-                            Flex::row()
-                                .with_child(
-                                    Flex::row()
-                                        .with_child(included_files_view)
-                                        .contained()
-                                        .with_style(include_container_style)
-                                        .aligned()
-                                        .constrained()
-                                        .with_min_width(
-                                            theme.search.include_exclude_editor.min_width,
-                                        )
-                                        .with_max_width(
-                                            theme.search.include_exclude_editor.max_width,
-                                        )
-                                        .flex(1., false),
-                                )
-                                .with_child(
-                                    Flex::row()
-                                        .with_child(excluded_files_view)
-                                        .contained()
-                                        .with_style(exclude_container_style)
-                                        .aligned()
-                                        .constrained()
-                                        .with_min_width(
-                                            theme.search.include_exclude_editor.min_width,
-                                        )
-                                        .with_max_width(
-                                            theme.search.include_exclude_editor.max_width,
-                                        )
-                                        .flex(1., false),
-                                ),
-                        )
+                        .with_children(filters)
                         .contained()
                         .with_style(theme.search.container)
                         .flex(2., true),
                 )
                 .with_child(
-                    Flex::row()
-                        .with_child(Label::new(
-                            "Here be dragons",
-                            theme.search.match_index.text.clone(),
-                        ))
-                        .flex(1., true)
-                        .aligned()
-                        .right(),
+                    Flex::column().with_child(
+                        Flex::row()
+                            .with_children(semantic_index)
+                            .with_child(regex_button)
+                            .flex(1., true)
+                            .aligned()
+                            .right(),
+                    ),
                 )
                 .contained()
                 .flex_float()