diff --git a/crates/picker2/src/picker2.rs b/crates/picker2/src/picker2.rs index dafe45e4e973e05d074a6970ffadfc210f1d16e2..8161c0d0a2546d94b82ac6f640e3185074744df6 100644 --- a/crates/picker2/src/picker2.rs +++ b/crates/picker2/src/picker2.rs @@ -1,31 +1,26 @@ -use std::cmp; - use gpui::{ - div, list, Component, ElementId, FocusHandle, Focusable, ListScrollHandle, ParentElement, + div, list, Component, ElementId, FocusHandle, ListScrollHandle, ParentElement, StatelessInteractive, Styled, ViewContext, }; +use std::cmp; -// pub struct Picker { -// delegate: D, -// query_editor: ViewHandle, -// list_state: UniformListState, -// max_size: Vector2F, -// theme: Arc theme::Picker>>>, -// confirmed: bool, -// pending_update_matches: Option>>, -// confirm_on_update: Option, -// has_focus: bool, -// } +#[derive(Component)] +pub struct Picker { + id: ElementId, + focus_handle: FocusHandle, + phantom: std::marker::PhantomData, +} pub trait PickerDelegate: Sized + 'static { type ListItem: Component; - // fn placeholder_text(&self) -> Arc; fn match_count(&self, picker_id: ElementId) -> usize; fn selected_index(&self, picker_id: ElementId) -> usize; fn set_selected_index(&mut self, ix: usize, picker_id: ElementId, cx: &mut ViewContext); - // fn update_matches(&mut self, query: String, cx: &mut ViewContext>) -> Task<()>; + // fn placeholder_text(&self) -> Arc; + // fn update_matches(&mut self, query: String, cx: &mut ViewContext>) -> Task<()>; + fn confirm(&mut self, secondary: bool, picker_id: ElementId, cx: &mut ViewContext); fn dismissed(&mut self, picker_id: ElementId, cx: &mut ViewContext); @@ -37,33 +32,6 @@ pub trait PickerDelegate: Sized + 'static { picker_id: ElementId, cx: &mut ViewContext, ) -> Self::ListItem; - - // fn center_selection_after_match_updates(&self) -> bool { - // false - // } - // fn render_header( - // &self, - // _cx: &mut ViewContext>, - // ) -> Option>> { - // None - // } - // fn render_footer( - // &self, - // _cx: &mut ViewContext>, - // ) -> Option>> { - // None - // } -} - -// impl Entity for Picker { -// type Event = PickerEvent; -// } - -#[derive(Component)] -pub struct Picker { - id: ElementId, - focus_handle: FocusHandle, - phantom: std::marker::PhantomData, } impl Picker { @@ -85,12 +53,6 @@ impl Picker { .id(self.id.clone()) .track_focus(&self.focus_handle) .context("picker") - .on_focus(|_, _, _cx| { - eprintln!("picker focused"); - }) - .on_blur(|_, _, _cx| { - eprintln!("picker blurred"); - }) .on_action({ let id = id.clone(); let scroll_handle = scroll_handle.clone(); @@ -173,305 +135,3 @@ impl Picker { ) } } - -// impl View for Picker { -// fn ui_name() -> &'static str { -// "Picker" -// } - -// fn render(&mut self, cx: &mut ViewContext) -> AnyElement { -// let theme = (self.theme.lock())(theme::current(cx).as_ref()); -// let query = self.query(cx); -// let match_count = self.delegate.match_count(); - -// let container_style; -// let editor_style; -// if query.is_empty() && match_count == 0 { -// container_style = theme.empty_container; -// editor_style = theme.empty_input_editor.container; -// } else { -// container_style = theme.container; -// editor_style = theme.input_editor.container; -// }; - -// Flex::new(Axis::Vertical) -// .with_child( -// ChildView::new(&self.query_editor, cx) -// .contained() -// .with_style(editor_style), -// ) -// .with_children(self.delegate.render_header(cx)) -// .with_children(if match_count == 0 { -// if query.is_empty() { -// None -// } else { -// Some( -// Label::new("No matches", theme.no_matches.label.clone()) -// .contained() -// .with_style(theme.no_matches.container) -// .into_any(), -// ) -// } -// } else { -// Some( -// UniformList::new( -// self.list_state.clone(), -// match_count, -// cx, -// move |this, mut range, items, cx| { -// let selected_ix = this.delegate.selected_index(); -// range.end = cmp::min(range.end, this.delegate.match_count()); -// items.extend(range.map(move |ix| { -// MouseEventHandler::new::(ix, cx, |state, cx| { -// this.delegate.render_match(ix, state, ix == selected_ix, cx) -// }) -// // Capture mouse events -// .on_down(MouseButton::Left, |_, _, _| {}) -// .on_up(MouseButton::Left, |_, _, _| {}) -// .on_click(MouseButton::Left, move |click, picker, cx| { -// picker.select_index(ix, click.cmd, cx); -// }) -// .with_cursor_style(CursorStyle::PointingHand) -// .into_any() -// })); -// }, -// ) -// .contained() -// .with_margin_top(6.0) -// .flex(1., false) -// .into_any(), -// ) -// }) -// .with_children(self.delegate.render_footer(cx)) -// .contained() -// .with_style(container_style) -// .constrained() -// .with_max_width(self.max_size.x()) -// .with_max_height(self.max_size.y()) -// .into_any_named("picker") -// } - -// fn update_keymap_context(&self, keymap: &mut KeymapContext, _: &AppContext) { -// Self::reset_to_default_keymap_context(keymap); -// keymap.add_identifier("menu"); -// } - -// fn focus_in(&mut self, _: AnyViewHandle, cx: &mut ViewContext) { -// self.has_focus = true; -// if cx.is_self_focused() { -// cx.focus(&self.query_editor); -// } -// } - -// fn focus_out(&mut self, _: AnyViewHandle, _: &mut ViewContext) { -// self.has_focus = false; -// } -// } - -// impl Modal for Picker { -// fn has_focus(&self) -> bool { -// self.has_focus -// } - -// fn dismiss_on_event(event: &Self::Event) -> bool { -// matches!(event, PickerEvent::Dismiss) -// } -// } - -// impl Picker { -// pub fn init(cx: &mut AppContext) { -// cx.add_action(Self::select_first); -// cx.add_action(Self::select_last); -// cx.add_action(Self::select_next); -// cx.add_action(Self::select_prev); -// cx.add_action(Self::confirm); -// cx.add_action(Self::secondary_confirm); -// cx.add_action(Self::cancel); -// } - -// pub fn new(delegate: D, cx: &mut ViewContext) -> Self { -// let theme = Arc::new(Mutex::new( -// Box::new(|theme: &theme::Theme| theme.picker.clone()) -// as Box theme::Picker>, -// )); -// let placeholder_text = delegate.placeholder_text(); -// let query_editor = cx.add_view({ -// let picker_theme = theme.clone(); -// |cx| { -// let mut editor = Editor::single_line( -// Some(Arc::new(move |theme| { -// (picker_theme.lock())(theme).input_editor.clone() -// })), -// cx, -// ); -// editor.set_placeholder_text(placeholder_text, cx); -// editor -// } -// }); -// cx.subscribe(&query_editor, Self::on_query_editor_event) -// .detach(); -// let mut this = Self { -// query_editor, -// list_state: Default::default(), -// delegate, -// max_size: vec2f(540., 420.), -// theme, -// confirmed: false, -// pending_update_matches: None, -// confirm_on_update: None, -// has_focus: false, -// }; -// this.update_matches(String::new(), cx); -// this -// Self { delegate } -// } - -// pub fn with_max_size(mut self, width: f32, height: f32) -> Self { -// self.max_size = vec2f(width, height); -// self -// } - -// pub fn with_theme(self, theme: F) -> Self -// where -// F: 'static + Fn(&theme::Theme) -> theme::Picker, -// { -// *self.theme.lock() = Box::new(theme); -// self -// } - -// pub fn delegate(&self) -> &D { -// &self.delegate -// } - -// pub fn delegate_mut(&mut self) -> &mut D { -// &mut self.delegate -// } - -// pub fn query(&self, cx: &AppContext) -> String { -// self.query_editor.read(cx).text(cx) -// } - -// pub fn set_query(&self, query: impl Into>, cx: &mut ViewContext) { -// self.query_editor -// .update(cx, |editor, cx| editor.set_text(query, cx)); -// } - -// fn on_query_editor_event( -// &mut self, -// _: ViewHandle, -// event: &editor::Event, -// cx: &mut ViewContext, -// ) { -// match event { -// editor::Event::BufferEdited { .. } => self.update_matches(self.query(cx), cx), -// editor::Event::Blurred if !self.confirmed => { -// self.dismiss(cx); -// } -// _ => {} -// } -// } - -// pub fn update_matches(&mut self, query: String, cx: &mut ViewContext) { -// let update = self.delegate.update_matches(query, cx); -// self.matches_updated(cx); -// self.pending_update_matches = Some(cx.spawn(|this, mut cx| async move { -// update.await; -// this.update(&mut cx, |this, cx| { -// this.matches_updated(cx); -// }) -// .log_err() -// })); -// } - -// fn matches_updated(&mut self, cx: &mut ViewContext) { -// let index = self.delegate.selected_index(); -// let target = if self.delegate.center_selection_after_match_updates() { -// ScrollTarget::Center(index) -// } else { -// ScrollTarget::Show(index) -// }; -// self.list_state.scroll_to(target); -// self.pending_update_matches = None; -// if let Some(secondary) = self.confirm_on_update.take() { -// self.confirmed = true; -// self.delegate.confirm(secondary, cx) -// } -// cx.notify(); -// } - -// pub fn select_first(&mut self, _: &SelectFirst, cx: &mut ViewContext) { -// if self.delegate.match_count() > 0 { -// self.delegate.set_selected_index(0, cx); -// self.list_state.scroll_to(ScrollTarget::Show(0)); -// } - -// cx.notify(); -// } - -// pub fn select_index(&mut self, index: usize, cmd: bool, cx: &mut ViewContext) { -// if self.delegate.match_count() > 0 { -// self.confirmed = true; -// self.delegate.set_selected_index(index, cx); -// self.delegate.confirm(cmd, cx); -// } -// } - -// pub fn select_last(&mut self, _: &SelectLast, cx: &mut ViewContext) { -// let match_count = self.delegate.match_count(); -// if match_count > 0 { -// let index = match_count - 1; -// self.delegate.set_selected_index(index, cx); -// self.list_state.scroll_to(ScrollTarget::Show(index)); -// } -// cx.notify(); -// } - -// pub fn select_next(&mut self, _: &SelectNext, cx: &mut ViewContext) { -// let next_index = self.delegate.selected_index() + 1; -// if next_index < self.delegate.match_count() { -// self.delegate.set_selected_index(next_index, cx); -// self.list_state.scroll_to(ScrollTarget::Show(next_index)); -// } - -// cx.notify(); -// } - -// pub fn select_prev(&mut self, _: &SelectPrev, cx: &mut ViewContext) { -// let mut selected_index = self.delegate.selected_index(); -// if selected_index > 0 { -// selected_index -= 1; -// self.delegate.set_selected_index(selected_index, cx); -// self.list_state -// .scroll_to(ScrollTarget::Show(selected_index)); -// } - -// cx.notify(); -// } - -// pub fn confirm(&mut self, _: &Confirm, cx: &mut ViewContext) { -// if self.pending_update_matches.is_some() { -// self.confirm_on_update = Some(false) -// } else { -// self.confirmed = true; -// self.delegate.confirm(false, cx); -// } -// } - -// pub fn secondary_confirm(&mut self, _: &SecondaryConfirm, cx: &mut ViewContext) { -// if self.pending_update_matches.is_some() { -// self.confirm_on_update = Some(true) -// } else { -// self.confirmed = true; -// self.delegate.confirm(true, cx); -// } -// } - -// fn cancel(&mut self, _: &Cancel, cx: &mut ViewContext) { -// self.dismiss(cx); -// } - -// fn dismiss(&mut self, cx: &mut ViewContext) { -// cx.emit(PickerEvent::Dismiss); -// self.delegate.dismissed(cx); -// } -// } diff --git a/crates/storybook2/src/stories/picker.rs b/crates/storybook2/src/stories/picker.rs index f5f2456d42bd2137081a6c6f8df262dee5e6f22a..061490779bb2fbb3b8c5a50d14efd532f2009c7c 100644 --- a/crates/storybook2/src/stories/picker.rs +++ b/crates/storybook2/src/stories/picker.rs @@ -93,11 +93,11 @@ impl PickerStory { KeyBinding::new("ctrl-c", menu::Cancel, Some("picker")), ]); - let fh = cx.focus_handle(); - cx.focus(&fh); + let focus_handle = cx.focus_handle(); + cx.focus(&focus_handle); PickerStory { - focus_handle: fh, + focus_handle, candidates: vec![ "Baguette (France)".into(), "Baklava (Turkey)".into(),