Make all pickers respect mouse clicks

Max Brunsfeld created

Change summary

crates/file_finder/src/file_finder.rs | 50 +++++++++-------------------
crates/picker/src/picker.rs           | 26 +++++++++++++-
crates/workspace/src/menu.rs          |  5 ++
3 files changed, 45 insertions(+), 36 deletions(-)

Detailed changes

crates/file_finder/src/file_finder.rs 🔗

@@ -1,7 +1,7 @@
 use fuzzy::PathMatch;
 use gpui::{
-    actions, elements::*, impl_internal_actions, AppContext, Entity, ModelHandle,
-    MutableAppContext, RenderContext, Task, View, ViewContext, ViewHandle,
+    actions, elements::*, AppContext, Entity, ModelHandle, MutableAppContext, RenderContext, Task,
+    View, ViewContext, ViewHandle,
 };
 use picker::{Picker, PickerDelegate};
 use project::{Project, ProjectPath, WorktreeId};
@@ -28,11 +28,7 @@ pub struct FileFinder {
     cancel_flag: Arc<AtomicBool>,
 }
 
-#[derive(Clone)]
-pub struct Select(pub ProjectPath);
-
 actions!(file_finder, [Toggle]);
-impl_internal_actions!(file_finder, [Select]);
 
 pub fn init(cx: &mut MutableAppContext) {
     cx.add_action(FileFinder::toggle);
@@ -240,33 +236,21 @@ impl PickerDelegate for FileFinder {
         };
         let (file_name, file_name_positions, full_path, full_path_positions) =
             self.labels_for_match(path_match);
-        let action = Select(ProjectPath {
-            worktree_id: WorktreeId::from_usize(path_match.worktree_id),
-            path: path_match.path.clone(),
-        });
-
-        EventHandler::new(
-            Flex::column()
-                .with_child(
-                    Label::new(file_name.to_string(), style.label.clone())
-                        .with_highlights(file_name_positions)
-                        .boxed(),
-                )
-                .with_child(
-                    Label::new(full_path, style.label.clone())
-                        .with_highlights(full_path_positions)
-                        .boxed(),
-                )
-                .flex(1., false)
-                .contained()
-                .with_style(style.container)
-                .boxed(),
-        )
-        .on_mouse_down(move |cx| {
-            cx.dispatch_action(action.clone());
-            true
-        })
-        .named("match")
+        Flex::column()
+            .with_child(
+                Label::new(file_name.to_string(), style.label.clone())
+                    .with_highlights(file_name_positions)
+                    .boxed(),
+            )
+            .with_child(
+                Label::new(full_path, style.label.clone())
+                    .with_highlights(full_path_positions)
+                    .boxed(),
+            )
+            .flex(1., false)
+            .contained()
+            .with_style(style.container)
+            .named("match")
     }
 }
 

crates/picker/src/picker.rs 🔗

@@ -1,7 +1,7 @@
 use editor::Editor;
 use gpui::{
     elements::{
-        ChildView, Flex, FlexItem, Label, ParentElement, ScrollTarget, UniformList,
+        ChildView, EventHandler, Flex, FlexItem, Label, ParentElement, ScrollTarget, UniformList,
         UniformListState,
     },
     keymap, AppContext, Axis, Element, ElementBox, Entity, MutableAppContext, RenderContext, Task,
@@ -9,7 +9,9 @@ use gpui::{
 };
 use settings::Settings;
 use std::cmp;
-use workspace::menu::{Cancel, Confirm, SelectFirst, SelectLast, SelectNext, SelectPrev};
+use workspace::menu::{
+    Cancel, Confirm, SelectFirst, SelectIndex, SelectLast, SelectNext, SelectPrev,
+};
 
 pub struct Picker<D: PickerDelegate> {
     delegate: WeakViewHandle<D>,
@@ -78,6 +80,7 @@ impl<D: PickerDelegate> Picker<D> {
         cx.add_action(Self::select_last);
         cx.add_action(Self::select_next);
         cx.add_action(Self::select_prev);
+        cx.add_action(Self::select_index);
         cx.add_action(Self::confirm);
         cx.add_action(Self::cancel);
     }
@@ -126,7 +129,14 @@ impl<D: PickerDelegate> Picker<D> {
                 let delegate = delegate.read(cx);
                 let selected_ix = delegate.selected_index();
                 range.end = cmp::min(range.end, delegate.match_count());
-                items.extend(range.map(move |ix| delegate.render_match(ix, ix == selected_ix, cx)));
+                items.extend(range.map(move |ix| {
+                    EventHandler::new(delegate.render_match(ix, ix == selected_ix, cx))
+                        .on_mouse_down(move |cx| {
+                            cx.dispatch_action(SelectIndex(ix));
+                            true
+                        })
+                        .boxed()
+                }));
             },
         )
         .contained()
@@ -181,6 +191,16 @@ impl<D: PickerDelegate> Picker<D> {
         }
     }
 
+    pub fn select_index(&mut self, action: &SelectIndex, cx: &mut ViewContext<Self>) {
+        if let Some(delegate) = self.delegate.upgrade(cx) {
+            let index = action.0;
+            delegate.update(cx, |delegate, cx| {
+                delegate.set_selected_index(index, cx);
+                delegate.confirm(cx);
+            });
+        }
+    }
+
     pub fn select_last(&mut self, _: &SelectLast, cx: &mut ViewContext<Self>) {
         if let Some(delegate) = self.delegate.upgrade(cx) {
             let index = delegate.update(cx, |delegate, cx| {

crates/workspace/src/menu.rs 🔗

@@ -1,3 +1,6 @@
+#[derive(Clone)]
+pub struct SelectIndex(pub usize);
+
 gpui::actions!(
     menu,
     [
@@ -9,3 +12,5 @@ gpui::actions!(
         SelectLast
     ]
 );
+
+gpui::impl_internal_actions!(menu, [SelectIndex]);