Fix picker_story to display selected value.
This commit is contained in:
parent
085b8e578b
commit
672240d750
3 changed files with 51 additions and 15 deletions
|
|
@ -1,7 +1,7 @@
|
||||||
use gpui::{
|
use gpui::{
|
||||||
div, prelude::FluentBuilder as _, px, Div, Empty, Entity, InteractiveElement as _, IntoElement,
|
actions, div, prelude::FluentBuilder as _, px, Div, Empty, Entity, InteractiveElement as _,
|
||||||
ParentElement, Render, SharedString, Styled, Task, View, ViewContext, VisualContext as _,
|
IntoElement, ParentElement, Render, SharedString, Styled, Task, View, ViewContext,
|
||||||
WindowContext,
|
VisualContext as _, WeakView, WindowContext,
|
||||||
};
|
};
|
||||||
|
|
||||||
use ui::{
|
use ui::{
|
||||||
|
|
@ -17,7 +17,10 @@ use ui::{
|
||||||
|
|
||||||
use super::story_case;
|
use super::story_case;
|
||||||
|
|
||||||
|
actions!(picker_story, [DismissPicker]);
|
||||||
|
|
||||||
pub struct ListItemDeletegate {
|
pub struct ListItemDeletegate {
|
||||||
|
story: WeakView<PickerStory>,
|
||||||
selected_index: usize,
|
selected_index: usize,
|
||||||
items: Vec<String>,
|
items: Vec<String>,
|
||||||
matches: Vec<String>,
|
matches: Vec<String>,
|
||||||
|
|
@ -42,12 +45,12 @@ impl PickerDelegate for ListItemDeletegate {
|
||||||
&self,
|
&self,
|
||||||
ix: usize,
|
ix: usize,
|
||||||
selected: bool,
|
selected: bool,
|
||||||
cx: &mut ViewContext<Picker<Self>>,
|
_cx: &mut ViewContext<Picker<Self>>,
|
||||||
) -> Option<Self::ListItem> {
|
) -> Option<Self::ListItem> {
|
||||||
let is_selected = ix == self.selected_index;
|
|
||||||
if let Some(item) = self.matches.get(ix) {
|
if let Some(item) = self.matches.get(ix) {
|
||||||
let list_item = ListItem::new(format!("item-{}", ix))
|
let list_item = ListItem::new(format!("item-{}", ix))
|
||||||
.selected(is_selected)
|
.check_icon(ui::IconName::Check)
|
||||||
|
.selected(selected)
|
||||||
.py_1()
|
.py_1()
|
||||||
.px_3()
|
.px_3()
|
||||||
.child(item.clone());
|
.child(item.clone());
|
||||||
|
|
@ -73,6 +76,27 @@ impl PickerDelegate for ListItemDeletegate {
|
||||||
|
|
||||||
Task::ready(())
|
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 {
|
pub struct PickerStory {
|
||||||
|
|
@ -82,7 +106,7 @@ pub struct PickerStory {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PickerStory {
|
impl PickerStory {
|
||||||
pub(crate) fn new(cx: &mut WindowContext) -> Self {
|
pub(crate) fn new(cx: &mut ViewContext<Self>) -> Self {
|
||||||
let items = [
|
let items = [
|
||||||
"Baguette (France)",
|
"Baguette (France)",
|
||||||
"Baklava (Turkey)",
|
"Baklava (Turkey)",
|
||||||
|
|
@ -135,11 +159,13 @@ impl PickerStory {
|
||||||
"Wiener Schnitzel (Austria)",
|
"Wiener Schnitzel (Austria)",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let story = cx.view().downgrade();
|
||||||
let picker = cx.new_view(|cx| {
|
let picker = cx.new_view(|cx| {
|
||||||
let items: Vec<String> = items.iter().map(|s| s.to_string()).collect();
|
let items: Vec<String> = items.iter().map(|s| s.to_string()).collect();
|
||||||
|
|
||||||
let mut picker = Picker::uniform_list(
|
let mut picker = Picker::uniform_list(
|
||||||
ListItemDeletegate {
|
ListItemDeletegate {
|
||||||
|
story,
|
||||||
selected_index: 0,
|
selected_index: 0,
|
||||||
matches: items.clone(),
|
matches: items.clone(),
|
||||||
items,
|
items,
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,14 @@ use gpui::{
|
||||||
StatefulInteractiveElement as _, Style, Styled, WindowContext,
|
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)]
|
#[derive(IntoElement)]
|
||||||
pub struct ListItem {
|
pub struct ListItem {
|
||||||
base: Stateful<Div>,
|
base: Stateful<Div>,
|
||||||
disabled: bool,
|
disabled: bool,
|
||||||
selected: bool,
|
selected: bool,
|
||||||
|
check_icon: Option<IconName>,
|
||||||
on_click: Option<Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
|
on_click: Option<Box<dyn Fn(&ClickEvent, &mut WindowContext) + 'static>>,
|
||||||
on_secondary_mouse_down: Option<Box<dyn Fn(&MouseDownEvent, &mut WindowContext) + 'static>>,
|
on_secondary_mouse_down: Option<Box<dyn Fn(&MouseDownEvent, &mut WindowContext) + 'static>>,
|
||||||
}
|
}
|
||||||
|
|
@ -23,9 +24,15 @@ impl ListItem {
|
||||||
selected: false,
|
selected: false,
|
||||||
on_click: None,
|
on_click: None,
|
||||||
on_secondary_mouse_down: 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 {
|
pub fn on_click(mut self, handler: impl Fn(&ClickEvent, &mut WindowContext) + 'static) -> Self {
|
||||||
self.on_click = Some(Box::new(handler));
|
self.on_click = Some(Box::new(handler));
|
||||||
self
|
self
|
||||||
|
|
@ -68,7 +75,10 @@ impl ParentElement for ListItem {
|
||||||
|
|
||||||
impl RenderOnce for ListItem {
|
impl RenderOnce for ListItem {
|
||||||
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
fn render(self, cx: &mut WindowContext) -> impl IntoElement {
|
||||||
self.base
|
h_flex()
|
||||||
|
.id("item-group")
|
||||||
|
.items_center()
|
||||||
|
.gap_2()
|
||||||
.w_full()
|
.w_full()
|
||||||
.relative()
|
.relative()
|
||||||
.gap_x_2()
|
.gap_x_2()
|
||||||
|
|
@ -85,12 +95,12 @@ impl RenderOnce for ListItem {
|
||||||
this.hover(|this| this.bg(cx.theme().accent))
|
this.hover(|this| this.bg(cx.theme().accent))
|
||||||
})
|
})
|
||||||
.when(self.selected, |this| this.bg(cx.theme().accent))
|
.when(self.selected, |this| this.bg(cx.theme().accent))
|
||||||
.map(|this| {
|
.child(self.base.when(self.selected, |this| {
|
||||||
if self.selected {
|
if let Some(icon) = self.check_icon {
|
||||||
this.child(IconName::Check)
|
this.child(icon)
|
||||||
} else {
|
} else {
|
||||||
this.child(div())
|
this
|
||||||
}
|
}
|
||||||
})
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,7 +56,7 @@ pub trait PickerDelegate: Sized + 'static {
|
||||||
fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<Picker<Self>>) {}
|
fn confirm(&mut self, secondary: bool, cx: &mut ViewContext<Picker<Self>>) {}
|
||||||
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {}
|
fn dismissed(&mut self, cx: &mut ViewContext<Picker<Self>>) {}
|
||||||
fn should_dismiss(&self) -> bool {
|
fn should_dismiss(&self) -> bool {
|
||||||
return true;
|
true
|
||||||
}
|
}
|
||||||
fn render_query(&self, input: &View<TextField>, _cx: &mut ViewContext<Picker<Self>>) -> Div {
|
fn render_query(&self, input: &View<TextField>, _cx: &mut ViewContext<Picker<Self>>) -> Div {
|
||||||
v_flex()
|
v_flex()
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue