feat: add optional placeholder text to dropdown

This commit is contained in:
Jonatan Pettersson 2026-01-16 14:19:06 +01:00 committed by Jeremy Soller
parent 85709b5c29
commit 3e6c9a6add

View file

@ -47,6 +47,8 @@ where
gap: f32, gap: f32,
#[setters(into)] #[setters(into)]
padding: Padding, padding: Padding,
#[setters(strip_option, into)]
placeholder: Option<Cow<'a, str>>,
#[setters(strip_option)] #[setters(strip_option)]
text_size: Option<f32>, text_size: Option<f32>,
text_line_height: text::LineHeight, text_line_height: text::LineHeight,
@ -86,6 +88,7 @@ where
selections, selections,
icons: Cow::Borrowed(&[]), icons: Cow::Borrowed(&[]),
selected, selected,
placeholder: None,
width: Length::Shrink, width: Length::Shrink,
gap: Self::DEFAULT_GAP, gap: Self::DEFAULT_GAP,
padding: Self::DEFAULT_PADDING, padding: Self::DEFAULT_PADDING,
@ -115,6 +118,7 @@ where
selections, selections,
icons, icons,
selected, selected,
placeholder,
width, width,
gap, gap,
padding, padding,
@ -131,6 +135,7 @@ where
selections, selections,
icons, icons,
selected, selected,
placeholder,
width, width,
gap, gap,
padding, padding,
@ -241,6 +246,7 @@ where
.map(AsRef::as_ref) .map(AsRef::as_ref)
.zip(tree.state.downcast_mut::<State>().selections.get_mut(id)) .zip(tree.state.downcast_mut::<State>().selections.get_mut(id))
}), }),
self.placeholder.as_deref(),
!self.icons.is_empty(), !self.icons.is_empty(),
) )
} }
@ -313,6 +319,7 @@ where
font, font,
self.selected.and_then(|id| self.selections.get(id)), self.selected.and_then(|id| self.selections.get(id)),
self.selected.and_then(|id| self.icons.get(id)), self.selected.and_then(|id| self.icons.get(id)),
self.placeholder.as_deref(),
tree.state.downcast_ref::<State>(), tree.state.downcast_ref::<State>(),
viewport, viewport,
); );
@ -451,6 +458,7 @@ pub fn layout(
text_line_height: text::LineHeight, text_line_height: text::LineHeight,
font: Option<crate::font::Font>, font: Option<crate::font::Font>,
selection: Option<(&str, &mut crate::Plain)>, selection: Option<(&str, &mut crate::Plain)>,
placeholder: Option<&str>,
has_icons: bool, has_icons: bool,
) -> layout::Node { ) -> layout::Node {
use std::f32; use std::f32;
@ -459,8 +467,8 @@ pub fn layout(
let max_width = match width { let max_width = match width {
Length::Shrink => { Length::Shrink => {
let measure = move |(label, paragraph): (_, &mut crate::Plain)| -> f32 { let measure = move |(label, paragraph): (_, Option<&mut crate::Plain>)| -> f32 {
paragraph.update(Text { let text = Text {
content: label, content: label,
bounds: Size::new(f32::MAX, f32::MAX), bounds: Size::new(f32::MAX, f32::MAX),
size: iced::Pixels(text_size), size: iced::Pixels(text_size),
@ -470,11 +478,22 @@ pub fn layout(
vertical_alignment: alignment::Vertical::Top, vertical_alignment: alignment::Vertical::Top,
shaping: text::Shaping::Advanced, shaping: text::Shaping::Advanced,
wrapping: text::Wrapping::default(), wrapping: text::Wrapping::default(),
}); };
let paragraph = match paragraph {
Some(p) => {
p.update(text);
p
}
None => &mut crate::Plain::new(text),
};
paragraph.min_width().round() paragraph.min_width().round()
}; };
selection.map(measure).unwrap_or_default() selection
.map(|(l, p)| (l, Some(p)))
.or_else(|| placeholder.map(|l| (l, None)))
.map(measure)
.unwrap_or_default()
} }
_ => 0.0, _ => 0.0,
}; };
@ -841,6 +860,7 @@ pub fn draw<'a, S>(
font: crate::font::Font, font: crate::font::Font,
selected: Option<&'a S>, selected: Option<&'a S>,
icon: Option<&'a icon::Handle>, icon: Option<&'a icon::Handle>,
placeholder: Option<&'a str>,
state: &'a State, state: &'a State,
viewport: &Rectangle, viewport: &Rectangle,
) where ) where
@ -880,7 +900,7 @@ pub fn draw<'a, S>(
); );
} }
if let Some(content) = selected.map(AsRef::as_ref) { if let Some(content) = selected.map(AsRef::as_ref).or(placeholder) {
let text_size = text_size.unwrap_or_else(|| text::Renderer::default_size(renderer).0); let text_size = text_size.unwrap_or_else(|| text::Renderer::default_size(renderer).0);
let mut bounds = Rectangle { let mut bounds = Rectangle {