Deploy `FindBar` when hitting `cmd-f`

Antonio Scandurra , Nathan Sobo , and Max Brunsfeld created

Co-Authored-By: Nathan Sobo <nathan@zed.dev>
Co-Authored-By: Max Brunsfeld <max@zed.dev>

Change summary

Cargo.lock                   | 10 ++++++++
crates/find/Cargo.toml       | 12 ++++++++++
crates/find/src/find.rs      | 45 ++++++++++++++++++++++++++++++++++++++
crates/workspace/src/pane.rs | 32 +++++++++++++++++++++++++-
crates/zed/Cargo.toml        |  1 
crates/zed/src/main.rs       |  1 
6 files changed, 99 insertions(+), 2 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -1719,6 +1719,15 @@ dependencies = [
  "workspace",
 ]
 
+[[package]]
+name = "find"
+version = "0.1.0"
+dependencies = [
+ "editor",
+ "gpui",
+ "workspace",
+]
+
 [[package]]
 name = "fixedbitset"
 version = "0.2.0"
@@ -5725,6 +5734,7 @@ dependencies = [
  "editor",
  "env_logger",
  "file_finder",
+ "find",
  "fsevent",
  "futures",
  "fuzzy",

crates/find/Cargo.toml 🔗

@@ -0,0 +1,12 @@
+[package]
+name = "find"
+version = "0.1.0"
+edition = "2021"
+
+[lib]
+path = "src/find.rs"
+
+[dependencies]
+editor = { path = "../editor" }
+gpui = { path = "../gpui" }
+workspace = { path = "../workspace" }

crates/find/src/find.rs 🔗

@@ -0,0 +1,45 @@
+use gpui::{
+    action, color::Color, elements::*, keymap::Binding, Entity, MutableAppContext, RenderContext,
+    View, ViewContext,
+};
+use workspace::Workspace;
+
+action!(Deploy);
+
+pub fn init(cx: &mut MutableAppContext) {
+    cx.add_bindings([Binding::new(
+        "cmd-f",
+        Deploy,
+        Some("Editor && mode == full"),
+    )]);
+    cx.add_action(FindBar::deploy);
+}
+
+struct FindBar;
+
+impl Entity for FindBar {
+    type Event = ();
+}
+
+impl View for FindBar {
+    fn ui_name() -> &'static str {
+        "FindBar"
+    }
+
+    fn render(&mut self, _: &mut RenderContext<Self>) -> ElementBox {
+        Empty::new()
+            .contained()
+            .with_background_color(Color::red())
+            .constrained()
+            .with_height(30.)
+            .boxed()
+    }
+}
+
+impl FindBar {
+    fn deploy(workspace: &mut Workspace, _: &Deploy, cx: &mut ViewContext<Workspace>) {
+        workspace
+            .active_pane()
+            .update(cx, |pane, cx| pane.show_toolbar(cx, |_| FindBar));
+    }
+}

crates/workspace/src/pane.rs 🔗

@@ -7,11 +7,17 @@ use gpui::{
     geometry::{rect::RectF, vector::vec2f},
     keymap::Binding,
     platform::CursorStyle,
-    Entity, MutableAppContext, Quad, RenderContext, Task, View, ViewContext, ViewHandle,
+    AnyViewHandle, Entity, MutableAppContext, Quad, RenderContext, Task, View, ViewContext,
+    ViewHandle,
 };
 use postage::watch;
 use project::ProjectPath;
-use std::{any::Any, cell::RefCell, cmp, mem, rc::Rc};
+use std::{
+    any::{Any, TypeId},
+    cell::RefCell,
+    cmp, mem,
+    rc::Rc,
+};
 use util::ResultExt;
 
 action!(Split, SplitDirection);
@@ -75,6 +81,8 @@ pub struct Pane {
     active_item_index: usize,
     settings: watch::Receiver<Settings>,
     nav_history: Rc<RefCell<NavHistory>>,
+    toolbars: HashMap<TypeId, AnyViewHandle>,
+    active_toolbar: Option<AnyViewHandle>,
 }
 
 // #[derive(Debug, Eq, PartialEq)]
@@ -120,6 +128,8 @@ impl Pane {
             active_item_index: 0,
             settings,
             nav_history: Default::default(),
+            toolbars: Default::default(),
+            active_toolbar: Default::default(),
         }
     }
 
@@ -365,6 +375,19 @@ impl Pane {
         cx.emit(Event::Split(direction));
     }
 
+    pub fn show_toolbar<F, V>(&mut self, cx: &mut ViewContext<Self>, build_toolbar: F)
+    where
+        F: FnOnce(&mut ViewContext<V>) -> V,
+        V: View,
+    {
+        let handle = self
+            .toolbars
+            .entry(TypeId::of::<V>())
+            .or_insert_with(|| cx.add_view(build_toolbar).into());
+        self.active_toolbar = Some(handle.clone());
+        cx.notify();
+    }
+
     fn render_tabs(&self, cx: &mut RenderContext<Self>) -> ElementBox {
         let settings = self.settings.borrow();
         let theme = &settings.theme;
@@ -516,6 +539,11 @@ impl View for Pane {
         if let Some(active_item) = self.active_item() {
             Flex::column()
                 .with_child(self.render_tabs(cx))
+                .with_children(
+                    self.active_toolbar
+                        .as_ref()
+                        .map(|view| ChildView::new(view).boxed()),
+                )
                 .with_child(ChildView::new(active_item).flexible(1., true).boxed())
                 .named("pane")
         } else {

crates/zed/Cargo.toml 🔗

@@ -36,6 +36,7 @@ contacts_panel = { path = "../contacts_panel" }
 diagnostics = { path = "../diagnostics" }
 editor = { path = "../editor" }
 file_finder = { path = "../file_finder" }
+find = { path = "../find" }
 fsevent = { path = "../fsevent" }
 fuzzy = { path = "../fuzzy" }
 go_to_line = { path = "../go_to_line" }

crates/zed/src/main.rs 🔗

@@ -62,6 +62,7 @@ fn main() {
         outline::init(cx);
         project_panel::init(cx);
         diagnostics::init(cx);
+        find::init(cx);
         cx.spawn({
             let client = client.clone();
             |cx| async move {