:art:

Max Brunsfeld and Mikayla created

Co-authored-by: Mikayla <mikayla@zed.dev>

Change summary

crates/picker2/src/picker2.rs | 183 +++++++++++++++++++-----------------
1 file changed, 98 insertions(+), 85 deletions(-)

Detailed changes

crates/picker2/src/picker2.rs 🔗

@@ -41,96 +41,109 @@ impl<V: PickerDelegate> Picker<V> {
             phantom: std::marker::PhantomData,
         }
     }
+
+    fn bind_actions<T: StatelessInteractive<V>>(
+        div: T,
+        id: ElementId,
+        scroll_handle: &UniformListScrollHandle,
+    ) -> T {
+        div.on_action({
+            let id = id.clone();
+            let scroll_handle = scroll_handle.clone();
+            move |view: &mut V, _: &menu::SelectNext, cx| {
+                let count = view.match_count(id.clone());
+                if count > 0 {
+                    let index = view.selected_index(id.clone());
+                    let ix = cmp::min(index + 1, count - 1);
+                    view.set_selected_index(ix, id.clone(), cx);
+                    scroll_handle.scroll_to_item(ix);
+                }
+            }
+        })
+        .on_action({
+            let id = id.clone();
+            let scroll_handle = scroll_handle.clone();
+            move |view, _: &menu::SelectPrev, cx| {
+                let count = view.match_count(id.clone());
+                if count > 0 {
+                    let index = view.selected_index(id.clone());
+                    let ix = index.saturating_sub(1);
+                    view.set_selected_index(ix, id.clone(), cx);
+                    scroll_handle.scroll_to_item(ix);
+                }
+            }
+        })
+        .on_action({
+            let id = id.clone();
+            let scroll_handle = scroll_handle.clone();
+            move |view: &mut V, _: &menu::SelectFirst, cx| {
+                let count = view.match_count(id.clone());
+                if count > 0 {
+                    view.set_selected_index(0, id.clone(), cx);
+                    scroll_handle.scroll_to_item(0);
+                }
+            }
+        })
+        .on_action({
+            let id = id.clone();
+            let scroll_handle = scroll_handle.clone();
+            move |view: &mut V, _: &menu::SelectLast, cx| {
+                let count = view.match_count(id.clone());
+                if count > 0 {
+                    view.set_selected_index(count - 1, id.clone(), cx);
+                    scroll_handle.scroll_to_item(count - 1);
+                }
+            }
+        })
+        .on_action({
+            let id = id.clone();
+            move |view: &mut V, _: &menu::Cancel, cx| {
+                view.dismissed(id.clone(), cx);
+            }
+        })
+        .on_action({
+            let id = id.clone();
+            move |view: &mut V, _: &menu::Confirm, cx| {
+                view.confirm(false, id.clone(), cx);
+            }
+        })
+        .on_action({
+            let id = id.clone();
+            move |view: &mut V, _: &menu::SecondaryConfirm, cx| {
+                view.confirm(true, id.clone(), cx);
+            }
+        })
+    }
 }
 
 impl<V: 'static + PickerDelegate> Picker<V> {
     pub fn render(self, view: &mut V, _cx: &mut ViewContext<V>) -> impl Component<V> {
         let id = self.id.clone();
         let scroll_handle = UniformListScrollHandle::new();
-        div()
-            .size_full()
-            .id(self.id.clone())
-            .track_focus(&self.focus_handle)
-            .context("picker")
-            .on_action({
-                let id = id.clone();
-                let scroll_handle = scroll_handle.clone();
-                move |view: &mut V, _: &menu::SelectNext, cx| {
-                    let count = view.match_count(id.clone());
-                    if count > 0 {
-                        let index = view.selected_index(id.clone());
-                        let ix = cmp::min(index + 1, count - 1);
-                        view.set_selected_index(ix, id.clone(), cx);
-                        scroll_handle.scroll_to_item(ix);
-                    }
-                }
-            })
-            .on_action({
-                let id = id.clone();
-                let scroll_handle = scroll_handle.clone();
-                move |view, _: &menu::SelectPrev, cx| {
-                    let count = view.match_count(id.clone());
-                    if count > 0 {
-                        let index = view.selected_index(id.clone());
-                        let ix = index.saturating_sub(1);
-                        view.set_selected_index(ix, id.clone(), cx);
-                        scroll_handle.scroll_to_item(ix);
-                    }
-                }
-            })
-            .on_action({
-                let id = id.clone();
-                let scroll_handle = scroll_handle.clone();
-                move |view: &mut V, _: &menu::SelectFirst, cx| {
-                    let count = view.match_count(id.clone());
-                    if count > 0 {
-                        view.set_selected_index(0, id.clone(), cx);
-                        scroll_handle.scroll_to_item(0);
-                    }
-                }
-            })
-            .on_action({
-                let id = id.clone();
-                let scroll_handle = scroll_handle.clone();
-                move |view: &mut V, _: &menu::SelectLast, cx| {
-                    let count = view.match_count(id.clone());
-                    if count > 0 {
-                        view.set_selected_index(count - 1, id.clone(), cx);
-                        scroll_handle.scroll_to_item(count - 1);
-                    }
-                }
-            })
-            .on_action({
-                let id = id.clone();
-                move |view: &mut V, _: &menu::Cancel, cx| {
-                    view.dismissed(id.clone(), cx);
-                }
-            })
-            .on_action({
-                let id = id.clone();
-                move |view: &mut V, _: &menu::Confirm, cx| {
-                    view.confirm(false, id.clone(), cx);
-                }
-            })
-            .on_action({
-                let id = id.clone();
-                move |view: &mut V, _: &menu::SecondaryConfirm, cx| {
-                    view.confirm(true, id.clone(), cx);
-                }
-            })
-            .child(
-                uniform_list(
-                    "candidates",
-                    view.match_count(self.id.clone()),
-                    move |view: &mut V, visible_range, cx| {
-                        let selected_ix = view.selected_index(self.id.clone());
-                        visible_range
-                            .map(|ix| view.render_match(ix, ix == selected_ix, self.id.clone(), cx))
-                            .collect()
-                    },
-                )
-                .track_scroll(scroll_handle.clone())
-                .size_full(),
-            )
+        Self::bind_actions(
+            div()
+                .id(self.id.clone())
+                .size_full()
+                .track_focus(&self.focus_handle)
+                .context("picker")
+                .child(
+                    uniform_list(
+                        "candidates",
+                        view.match_count(self.id.clone()),
+                        move |view: &mut V, visible_range, cx| {
+                            let selected_ix = view.selected_index(self.id.clone());
+                            visible_range
+                                .map(|ix| {
+                                    view.render_match(ix, ix == selected_ix, self.id.clone(), cx)
+                                })
+                                .collect()
+                        },
+                    )
+                    .track_scroll(scroll_handle.clone())
+                    .size_full(),
+                ),
+            id,
+            &scroll_handle,
+        )
     }
 }