Fix picker_story to display selected value.

This commit is contained in:
Jason Lee 2024-06-26 19:01:52 +08:00
parent 085b8e578b
commit 672240d750
3 changed files with 51 additions and 15 deletions

View file

@ -1,7 +1,7 @@
use gpui::{
div, prelude::FluentBuilder as _, px, Div, Empty, Entity, InteractiveElement as _, IntoElement,
ParentElement, Render, SharedString, Styled, Task, View, ViewContext, VisualContext as _,
WindowContext,
actions, div, prelude::FluentBuilder as _, px, Div, Empty, Entity, InteractiveElement as _,
IntoElement, ParentElement, Render, SharedString, Styled, Task, View, ViewContext,
VisualContext as _, WeakView, WindowContext,
};
use ui::{
@ -17,7 +17,10 @@ use ui::{
use super::story_case;
actions!(picker_story, [DismissPicker]);
pub struct ListItemDeletegate {
story: WeakView<PickerStory>,
selected_index: usize,
items: Vec<String>,
matches: Vec<String>,
@ -42,12 +45,12 @@ impl PickerDelegate for ListItemDeletegate {
&self,
ix: usize,
selected: bool,
cx: &mut ViewContext<Picker<Self>>,
_cx: &mut ViewContext<Picker<Self>>,
) -> Option<Self::ListItem> {
let is_selected = ix == self.selected_index;
if let Some(item) = self.matches.get(ix) {
let list_item = ListItem::new(format!("item-{}", ix))
.selected(is_selected)
.check_icon(ui::IconName::Check)
.selected(selected)
.py_1()
.px_3()
.child(item.clone());
@ -73,6 +76,27 @@ impl PickerDelegate for ListItemDeletegate {
Task::ready(())
}
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {
if let Some(story) = self.story.upgrade() {
cx.update_view(&story, |story, cx| {
story.open = false;
cx.notify();
});
}
}
fn confirm(&mut self, _secondary: bool, cx: &mut ViewContext<Picker<Self>>) {
if let Some(story) = self.story.upgrade() {
cx.update_view(&story, |story, cx| {
if let Some(item) = self.matches.get(self.selected_index) {
story.selected_value = Some(item.clone());
}
story.open = false;
cx.notify();
});
}
}
}
pub struct PickerStory {
@ -82,7 +106,7 @@ pub struct PickerStory {
}
impl PickerStory {
pub(crate) fn new(cx: &mut WindowContext) -> Self {
pub(crate) fn new(cx: &mut ViewContext<Self>) -> Self {
let items = [
"Baguette (France)",
"Baklava (Turkey)",
@ -135,11 +159,13 @@ impl PickerStory {
"Wiener Schnitzel (Austria)",
];
let story = cx.view().downgrade();
let picker = cx.new_view(|cx| {
let items: Vec<String> = items.iter().map(|s| s.to_string()).collect();
let mut picker = Picker::uniform_list(
ListItemDeletegate {
story,
selected_index: 0,
matches: items.clone(),
items,

View file

@ -4,13 +4,14 @@ use gpui::{
StatefulInteractiveElement as _, Style, Styled, WindowContext,
};
use crate::{h_flex, theme::ActiveTheme, Disableable, IconName, Selectable};
use crate::{h_flex, theme::ActiveTheme, Disableable, Icon, IconName, Selectable};
#[derive(IntoElement)]
pub struct ListItem {
base: Stateful<Div>,
disabled: bool,
selected: bool,
check_icon: Option<IconName>,
on_click: Option<Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
on_secondary_mouse_down: Option<Box<dyn Fn(&MouseDownEvent, &mut WindowContext) + 'static>>,
}
@ -23,9 +24,15 @@ impl ListItem {
selected: false,
on_click: None,
on_secondary_mouse_down: None,
check_icon: None,
}
}
pub fn check_icon(mut self, icon: IconName) -> Self {
self.check_icon = Some(icon);
self
}
pub fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
self.on_click = Some(Box::new(handler));
self
@ -68,7 +75,10 @@ impl ParentElement for ListItem {
impl RenderOnce for ListItem {
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
self.base
h_flex()
.id("item-group")
.items_center()
.gap_2()
.w_full()
.relative()
.gap_x_2()
@ -85,12 +95,12 @@ impl RenderOnce for ListItem {
this.hover(|this| this.bg(cx.theme().accent))
})
.when(self.selected, |this| this.bg(cx.theme().accent))
.map(|this| {
if self.selected {
this.child(IconName::Check)
.child(self.base.when(self.selected, |this| {
if let Some(icon) = self.check_icon {
this.child(icon)
} else {
this.child(div())
this
}
})
}))
}
}

View file

@ -56,7 +56,7 @@ pub trait PickerDelegate: Sized + 'static {
fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<Picker<Self>>) {}
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {}
fn should_dismiss(&self) -> bool {
return true;
true
}
fn render_query(&self, input: &View<TextField>, _cx: &mut ViewContext<Picker<Self>>) -> Div {
v_flex()