Render a magnifier icon and the query in project search tab

Nathan Sobo created

Also: Wire up events so the modified status updates correctly.

Change summary

crates/find/src/project_find.rs       | 63 ++++++++++++++++++++++------
crates/theme/src/theme.rs             |  2 
crates/zed/assets/icons/magnifier.svg |  3 +
crates/zed/assets/themes/_base.toml   |  2 
4 files changed, 56 insertions(+), 14 deletions(-)

Detailed changes

crates/find/src/project_find.rs 🔗

@@ -39,6 +39,7 @@ struct ProjectFind {
     excerpts: ModelHandle<MultiBuffer>,
     pending_search: Option<Task<Option<()>>>,
     highlighted_ranges: Vec<Range<Anchor>>,
+    active_query: Option<SearchQuery>,
 }
 
 struct ProjectFindView {
@@ -64,6 +65,7 @@ impl ProjectFind {
             excerpts: cx.add_model(|_| MultiBuffer::new(replica_id)),
             pending_search: Default::default(),
             highlighted_ranges: Default::default(),
+            active_query: None,
         }
     }
 
@@ -75,6 +77,7 @@ impl ProjectFind {
                 .update(new_cx, |excerpts, cx| cx.add_model(|cx| excerpts.clone(cx))),
             pending_search: Default::default(),
             highlighted_ranges: self.highlighted_ranges.clone(),
+            active_query: self.active_query.clone(),
         }
     }
 
@@ -104,6 +107,7 @@ impl ProjectFind {
                         }
                     });
                     this.pending_search.take();
+                    this.active_query = Some(query);
                     cx.notify();
                 });
             }
@@ -124,8 +128,22 @@ impl Item for ProjectFind {
     ) -> Self::View {
         let settings = workspace.settings();
         let excerpts = model.read(cx).excerpts.clone();
+        let results_editor = cx.add_view(|cx| {
+            let mut editor = Editor::for_buffer(
+                excerpts,
+                Some(workspace.project().clone()),
+                settings.clone(),
+                cx,
+            );
+            editor.set_searchable(false);
+            editor.set_nav_history(Some(nav_history));
+            editor
+        });
+        cx.observe(&results_editor, |_, _, cx| cx.emit(ViewEvent::UpdateTab))
+            .detach();
         cx.observe(&model, |this, _, cx| this.model_changed(true, cx))
             .detach();
+
         ProjectFindView {
             model,
             query_editor: cx.add_view(|cx| {
@@ -135,17 +153,7 @@ impl Item for ProjectFind {
                     cx,
                 )
             }),
-            results_editor: cx.add_view(|cx| {
-                let mut editor = Editor::for_buffer(
-                    excerpts,
-                    Some(workspace.project().clone()),
-                    settings.clone(),
-                    cx,
-                );
-                editor.set_searchable(false);
-                editor.set_nav_history(Some(nav_history));
-                editor
-            }),
+            results_editor,
             case_sensitive: false,
             whole_word: false,
             regex: false,
@@ -159,8 +167,12 @@ impl Item for ProjectFind {
     }
 }
 
+enum ViewEvent {
+    UpdateTab,
+}
+
 impl Entity for ProjectFindView {
-    type Event = ();
+    type Event = ViewEvent;
 }
 
 impl View for ProjectFindView {
@@ -231,8 +243,26 @@ impl ItemView for ProjectFindView {
         Box::new(self.model.clone())
     }
 
-    fn tab_content(&self, style: &theme::Tab, _: &gpui::AppContext) -> ElementBox {
-        Label::new("Project Find".to_string(), style.label.clone()).boxed()
+    fn tab_content(&self, style: &theme::Tab, cx: &gpui::AppContext) -> ElementBox {
+        let settings = self.settings.borrow();
+        let find_theme = &settings.theme.find;
+        Flex::row()
+            .with_child(
+                Svg::new("icons/magnifier.svg")
+                    .with_color(style.label.text.color)
+                    .constrained()
+                    .with_width(find_theme.tab_icon_width)
+                    .aligned()
+                    .boxed(),
+            )
+            .with_children(self.model.read(cx).active_query.as_ref().map(|query| {
+                Label::new(query.as_str().to_string(), style.label.clone())
+                    .aligned()
+                    .contained()
+                    .with_margin_left(find_theme.tab_icon_spacing)
+                    .boxed()
+            }))
+            .boxed()
     }
 
     fn project_path(&self, _: &gpui::AppContext) -> Option<project::ProjectPath> {
@@ -331,6 +361,10 @@ impl ItemView for ProjectFindView {
         self.results_editor
             .update(cx, |editor, cx| editor.navigate(data, cx));
     }
+
+    fn should_update_tab_on_event(event: &ViewEvent) -> bool {
+        matches!(event, ViewEvent::UpdateTab)
+    }
 }
 
 impl ProjectFindView {
@@ -407,6 +441,7 @@ impl ProjectFindView {
             }
         }
 
+        cx.emit(ViewEvent::UpdateTab);
         cx.notify();
     }
 

crates/theme/src/theme.rs 🔗

@@ -108,6 +108,8 @@ pub struct Find {
     pub match_background: Color,
     pub match_index: ContainedText,
     pub results_status: TextStyle,
+    pub tab_icon_width: f32,
+    pub tab_icon_spacing: f32,
 }
 
 #[derive(Clone, Deserialize, Default)]

crates/zed/assets/icons/magnifier.svg 🔗

@@ -0,0 +1,3 @@
+<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path d="M11.0893 10.4092L8.34129 7.66113C8.93602 6.93311 9.26414 6.01641 9.26414 5.01562C9.26414 2.65928 7.35425 0.75 4.99851 0.75C2.64278 0.75 0.751343 2.65989 0.751343 5.01562C0.751343 7.37136 2.66103 9.28125 4.99851 9.28125C5.99909 9.28125 6.91702 8.93446 7.64402 8.35758L10.3921 11.1056C10.5069 11.2028 10.6341 11.25 10.7592 11.25C10.8843 11.25 11.011 11.2019 11.1072 11.1058C11.2985 10.9137 11.2985 10.602 11.0893 10.4092ZM1.73572 5.01562C1.73572 3.20643 3.20777 1.73438 5.01697 1.73438C6.82617 1.73438 8.29822 3.20643 8.29822 5.01562C8.29822 6.82482 6.82617 8.29688 5.01697 8.29688C3.20777 8.29688 1.73572 6.82441 1.73572 5.01562Z" fill="white" fill-opacity="0.5"/>
+</svg>

crates/zed/assets/themes/_base.toml 🔗

@@ -352,6 +352,8 @@ tab_summary_spacing = 10
 match_background = "$state.highlighted_line"
 background = "$surface.1"
 results_status = { extends = "$text.0", size = 18 }
+tab_icon_width = 14
+tab_icon_spacing = 4
 
 [find.option_button]
 extends = "$text.1"