From 6d1cbb1bb682199a4cb7543b76fd281c74536b19 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Tue, 5 Dec 2023 12:57:54 +0100 Subject: [PATCH 1/5] fix(dropdown::multi::menu): panic in layout --- src/widget/dropdown/multi/menu.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/widget/dropdown/multi/menu.rs b/src/widget/dropdown/multi/menu.rs index cf5f5280820..83297c8f6e0 100644 --- a/src/widget/dropdown/multi/menu.rs +++ b/src/widget/dropdown/multi/menu.rs @@ -213,9 +213,7 @@ impl<'a, Message> iced_core::Overlay for Overlay<'a, M ) .width(self.width); - let mut node = self - .container - .layout(&mut self.state.children[0], renderer, &limits); + let mut node = self.container.layout(self.state, renderer, &limits); node.move_to(if space_below > space_above { position + Vector::new(0.0, self.target_height) From 711f6378ce7811bd2f6db72b74def5489a684268 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Tue, 5 Dec 2023 15:04:41 +0100 Subject: [PATCH 2/5] fix(dropdown::multi::menu): option description off center by 8 pixels --- src/widget/dropdown/multi/menu.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/widget/dropdown/multi/menu.rs b/src/widget/dropdown/multi/menu.rs index 83297c8f6e0..5cb5d01e3e6 100644 --- a/src/widget/dropdown/multi/menu.rs +++ b/src/widget/dropdown/multi/menu.rs @@ -584,9 +584,10 @@ where let bounds = Rectangle { x: bounds.x + self.padding.left, - y: bounds.y + self.padding.top, + // TODO: Figure out why it's offset by 8 pixels + y: bounds.y + self.padding.top + 8.0, width: bounds.width, - height: bounds.height, + height: elem_height, }; text::Renderer::fill_text( renderer, From e541186b6aa3d2466e1b607f225f83e386fc2d2d Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Tue, 5 Dec 2023 15:58:20 +0100 Subject: [PATCH 3/5] fix(dropdown::multi::menu): vertically center-align separators --- src/widget/dropdown/multi/menu.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/widget/dropdown/multi/menu.rs b/src/widget/dropdown/multi/menu.rs index 5cb5d01e3e6..0faedfea1ba 100644 --- a/src/widget/dropdown/multi/menu.rs +++ b/src/widget/dropdown/multi/menu.rs @@ -515,7 +515,7 @@ where let mut current_offset = 0.0; for (elem, elem_height) in visible_options { - let bounds = Rectangle { + let mut bounds = Rectangle { x: bounds.x, y: bounds.y + current_offset, width: bounds.width, @@ -530,13 +530,15 @@ where let item_x = bounds.x + appearance.border_width; let item_width = bounds.width - appearance.border_width * 2.0; + bounds = Rectangle { + x: item_x, + width: item_width, + ..bounds + }; + renderer.fill_quad( renderer::Quad { - bounds: Rectangle { - x: item_x, - width: item_width, - ..bounds - }, + bounds, border_color: Color::TRANSPARENT, border_width: 0.0, border_radius: appearance.border_radius, @@ -563,13 +565,15 @@ where let item_x = bounds.x + appearance.border_width; let item_width = bounds.width - appearance.border_width * 2.0; + bounds = Rectangle { + x: item_x, + width: item_width, + ..bounds + }; + renderer.fill_quad( renderer::Quad { - bounds: Rectangle { - x: item_x, - width: item_width, - ..bounds - }, + bounds, border_color: Color::TRANSPARENT, border_width: 0.0, border_radius: appearance.border_radius, @@ -617,7 +621,7 @@ where layout_node.move_to(Point { x: bounds.x, - y: bounds.y + self.padding.top, + y: bounds.y + (self.padding.vertical() / 2.0) - 4.0, }); Widget::::draw( From 9b0b7b379de823ac575000802c11257b1cc6bc7a Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Tue, 5 Dec 2023 16:17:06 +0100 Subject: [PATCH 4/5] fix(dropdown::multi): set correct line height for descriptions --- src/widget/dropdown/multi/widget.rs | 49 ++++++++++++----------------- 1 file changed, 20 insertions(+), 29 deletions(-) diff --git a/src/widget/dropdown/multi/widget.rs b/src/widget/dropdown/multi/widget.rs index 8b00f4dd7e1..3989fe8db58 100644 --- a/src/widget/dropdown/multi/widget.rs +++ b/src/widget/dropdown/multi/widget.rs @@ -382,6 +382,10 @@ pub fn overlay<'a, S: AsRef, Message: 'a, Item: Clone + PartialEq + 'static on_selected: &'a dyn Fn(Item) -> Message, ) -> Option> { if state.is_open { + let description_line_height = text::LineHeight::Absolute(Pixels( + text_line_height.to_absolute(Pixels(text_size)).0 + 4.0, + )); + let bounds = layout.bounds(); let menu = Menu::new( @@ -397,33 +401,20 @@ pub fn overlay<'a, S: AsRef, Message: 'a, Item: Clone + PartialEq + 'static None, ) .width({ - let measure = |label: &str, paragraph: &mut crate::Paragraph| { - paragraph.update(Text { - content: label, - bounds: Size::new(f32::MAX, f32::MAX), - size: iced::Pixels(text_size), - line_height: text_line_height, - font: font.unwrap_or_else(|| text::Renderer::default_font(renderer)), - horizontal_alignment: alignment::Horizontal::Left, - vertical_alignment: alignment::Vertical::Top, - shaping: text::Shaping::Advanced, - }); - paragraph.min_width().round() - }; - - let measure_description = |label: &str, paragraph: &mut crate::Paragraph| { - paragraph.update(Text { - content: label, - bounds: Size::new(f32::MAX, f32::MAX), - size: iced::Pixels(text_size + 4.0), - line_height: text_line_height, - font: font.unwrap_or_else(|| text::Renderer::default_font(renderer)), - horizontal_alignment: alignment::Horizontal::Left, - vertical_alignment: alignment::Vertical::Top, - shaping: text::Shaping::Advanced, - }); - paragraph.min_width().round() - }; + let measure = + |label: &str, paragraph: &mut crate::Paragraph, line_height: text::LineHeight| { + paragraph.update(Text { + content: label, + bounds: Size::new(f32::MAX, f32::MAX), + size: iced::Pixels(text_size), + line_height, + font: font.unwrap_or_else(|| text::Renderer::default_font(renderer)), + horizontal_alignment: alignment::Horizontal::Left, + vertical_alignment: alignment::Vertical::Top, + shaping: text::Shaping::Advanced, + }); + paragraph.min_width().round() + }; let mut desc_count = 0; selections @@ -437,7 +428,7 @@ pub fn overlay<'a, S: AsRef, Message: 'a, Item: Clone + PartialEq + 'static state.descriptions.last_mut().unwrap() }; desc_count += 1; - measure_description(desc.as_ref(), paragraph) + measure(desc.as_ref(), paragraph, description_line_height) } super::menu::OptionElement::Option((option, item)) => { @@ -451,7 +442,7 @@ pub fn overlay<'a, S: AsRef, Message: 'a, Item: Clone + PartialEq + 'static .push((item.clone(), crate::Paragraph::new())); &mut state.selections.last_mut().unwrap().1 }; - measure(option.as_ref(), paragraph) + measure(option.as_ref(), paragraph, text_line_height) } super::menu::OptionElement::Separator => 1.0, From 6ba524d1a9a7fe066e7ec1cbe1b75b8589410ac3 Mon Sep 17 00:00:00 2001 From: Michael Aaron Murphy Date: Tue, 5 Dec 2023 16:53:20 +0100 Subject: [PATCH 5/5] fix(dropdown::multi): paragraphs missing in layout on first init --- src/widget/dropdown/multi/widget.rs | 39 ++++++++++++++++++----------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/src/widget/dropdown/multi/widget.rs b/src/widget/dropdown/multi/widget.rs index 3989fe8db58..edf1ba293bb 100644 --- a/src/widget/dropdown/multi/widget.rs +++ b/src/widget/dropdown/multi/widget.rs @@ -94,14 +94,25 @@ impl<'a, S: AsRef, Message: 'a, Item: Clone + PartialEq + 'static> self.text_line_height, self.font, self.selections.selected.as_ref().and_then(|id| { - self.selections.get(id).map(AsRef::as_ref).zip( - tree.state - .downcast_mut::>() + self.selections.get(id).map(AsRef::as_ref).zip({ + let state = tree.state.downcast_mut::>(); + + if state.selections.is_empty() { + for list in &self.selections.lists { + for (_, item) in &list.options { + state + .selections + .push((item.clone(), crate::Paragraph::new())); + } + } + } + + state .selections .iter_mut() .find(|(i, _)| i == id) - .map(|(_, p)| p), - ) + .map(|(_, p)| p) + }) }), ) } @@ -432,16 +443,14 @@ pub fn overlay<'a, S: AsRef, Message: 'a, Item: Clone + PartialEq + 'static } super::menu::OptionElement::Option((option, item)) => { - let paragraph = if let Some(index) = - state.selections.iter().position(|(i, _)| i == item) - { - &mut state.selections[index].1 - } else { - state - .selections - .push((item.clone(), crate::Paragraph::new())); - &mut state.selections.last_mut().unwrap().1 - }; + let selection_index = state + .selections + .iter() + .position(|(i, _)| i == item) + .expect("selection missing from state"); + + let paragraph = &mut state.selections[selection_index].1; + measure(option.as_ref(), paragraph, text_line_height) }