From 0a4d7f0fe146c47b553e377aca53b57217ad3a51 Mon Sep 17 00:00:00 2001 From: Latidoremi Date: Thu, 3 Aug 2023 13:39:15 +0800 Subject: [PATCH 1/7] Remove get_children_size and get_child_positions --- examples/menu/src/main.rs | 74 ++++++++++++++++++++++- src/native/menu/menu_inner.rs | 111 +++++++++++++++++++++++----------- 2 files changed, 146 insertions(+), 39 deletions(-) diff --git a/examples/menu/src/main.rs b/examples/menu/src/main.rs index cbfb459a..498b7942 100644 --- a/examples/menu/src/main.rs +++ b/examples/menu/src/main.rs @@ -13,7 +13,7 @@ pub fn main() -> iced::Result { App::run(iced::Settings { default_text_size: 15.0, window: iced::window::Settings { - size: (800, 500), + size: (1000, 500), // position: iced::window::Position::Default, ..Default::default() }, @@ -25,9 +25,14 @@ pub fn main() -> iced::Result { enum SizeOption { Uniform, Static, + DynamicHeight, } impl SizeOption { - const ALL: [SizeOption; 2] = [SizeOption::Uniform, SizeOption::Static]; + const ALL: [SizeOption; 3] = [ + SizeOption::Uniform, + SizeOption::Static, + SizeOption::DynamicHeight, + ]; } impl std::fmt::Display for SizeOption { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { @@ -37,6 +42,7 @@ impl std::fmt::Display for SizeOption { match self { Self::Uniform => "Uniform", Self::Static => "Static", + Self::DynamicHeight => "DynamicHeight", } ) } @@ -91,7 +97,7 @@ impl Application for App { flip_v: false, dark_mode: false, text: "Text Input".into(), - size_option: SizeOption::Static, + size_option: SizeOption::DynamicHeight, }, iced::Command::none(), ) @@ -180,6 +186,15 @@ impl Application for App { ) .item_width(ItemWidth::Static(180)) .item_height(ItemHeight::Static(25)), + SizeOption::DynamicHeight => menu_bar!( + menu_1(self), + menu_2(self), + menu_3(self), + menu_4(self), + menu_6(self), + ) + .item_width(ItemWidth::Static(180)) + .item_height(ItemHeight::Static(25)), } .spacing(4.0) .bounds_expand(30) @@ -276,6 +291,14 @@ fn debug_item<'a>(label: &str) -> MenuTree<'a, Message, iced::Renderer> { menu_tree!(debug_button(label).width(Length::Fill).height(Length::Fill)) } +fn debug_item2<'a>(label: &str) -> MenuTree<'a, Message, iced::Renderer> { + menu_tree!(debug_button(label).width(Length::Fill).height(Length::Shrink)) +} + +fn debug_item3<'a>(label: &str, h: f32) -> MenuTree<'a, Message, iced::Renderer> { + menu_tree!(debug_button(label).width(Length::Fill).height(Length::Fixed(h))) +} + fn color_item<'a>(color: impl Into) -> MenuTree<'a, Message, iced::Renderer> { let color = color.into(); menu_tree!(base_button(circle(color), Message::ColorChange(color))) @@ -725,3 +748,48 @@ fn menu_5<'a>(app: &App) -> MenuTree<'a, Message, iced::Renderer> { root } + +fn menu_6<'a>(app: &App) -> MenuTree<'a, Message, iced::Renderer> { + let slider_count = 3; + let slider_width = 30; + let spacing = 4; + + let [r, g, b, _] = app.theme.palette().primary.into_rgba8(); + + let sliders = menu_tree!(row![ + vertical_slider(0..=255, r, move |x| Message::ColorChange(Color::from_rgb8( + x, g, b + ))) + .width(30), + vertical_slider(0..=255, g, move |x| Message::ColorChange(Color::from_rgb8( + r, x, b + ))) + .width(30), + vertical_slider(0..=255, b, move |x| Message::ColorChange(Color::from_rgb8( + r, g, x + ))) + .width(30), + ] + .spacing(4)) + .height(100); + + let root = menu_tree( + debug_button("Dynamic Height"), + vec![ + labeled_separator("Primary"), + sliders, + debug_item2("AABB") + // .height(80) + , + debug_item3("CCDD", 50.0) + // .height(60) + , + debug_item2("EEFF") + // .height(50) + , + ], + ) + .width(slider_width * slider_count + (slider_count - 1) * spacing); + + root +} diff --git a/src/native/menu/menu_inner.rs b/src/native/menu/menu_inner.rs index 807503cb..8d2a64e4 100644 --- a/src/native/menu/menu_inner.rs +++ b/src/native/menu/menu_inner.rs @@ -209,6 +209,7 @@ struct MenuSlice { /// Menu bounds in overlay space struct MenuBounds { child_positions: Vec, + child_sizes: Vec, children_bounds: Rectangle, parent_bounds: Rectangle, check_bounds: Rectangle, @@ -228,7 +229,9 @@ impl MenuBounds { where Renderer: renderer::Renderer, { - let children_size = get_children_size(menu_tree, item_width, item_height); + // let children_size = get_children_size(menu_tree, item_width, item_height); + // let child_positions = get_child_positions(menu_tree, item_height); + let (children_size, child_positions, child_sizes) = get_children_layout(menu_tree, item_width, item_height); // viewport space parent bounds let view_parent_bounds = parent_bounds + overlay_offset; @@ -238,11 +241,11 @@ impl MenuBounds { aod.point(view_parent_bounds, children_size, viewport_size) - overlay_offset; let children_bounds = Rectangle::new(children_position, children_size); - let child_positions = get_child_positions(menu_tree, item_height); let check_bounds = pad_rectangle(children_bounds, [bounds_expand; 4].into()); Self { child_positions, + child_sizes, children_bounds, parent_bounds, check_bounds, @@ -1075,11 +1078,62 @@ where Size::new(width, height) } -fn get_children_size( +// fn get_children_size( +// menu_tree: &MenuTree<'_, Message, Renderer>, +// item_width: ItemWidth, +// item_height: ItemHeight, +// ) -> Size +// where +// Renderer: renderer::Renderer, +// { +// let width = match item_width { +// ItemWidth::Uniform(u) => f32::from(u), +// ItemWidth::Static(s) => f32::from(menu_tree.width.unwrap_or(s)), +// }; + +// let height = match item_height { +// ItemHeight::Uniform(u) => f32::from(u) * (menu_tree.children.len() as f32), +// ItemHeight::Static(s) => menu_tree +// .children +// .iter() +// .fold(0.0, |h, mt| h + f32::from(mt.height.unwrap_or(s))), +// }; + +// Size::new(width, height) +// } + +// fn get_child_positions( +// menu_tree: &MenuTree<'_, Message, Renderer>, +// item_height: ItemHeight, +// ) -> Vec +// where +// Renderer: renderer::Renderer, +// { +// match item_height { +// ItemHeight::Uniform(u) => { +// let children_count = menu_tree.children.len(); +// (0..children_count) +// .map(|i| (i as f32) * f32::from(u)) +// .collect() +// } +// ItemHeight::Static(s) => { +// let max_index = menu_tree.children.len() - 1; +// std::iter::once(0.0) +// .chain(menu_tree.children[0..max_index].iter().scan(0.0, |p, mt| { +// *p += f32::from(mt.height.unwrap_or(s)); +// Some(*p) +// })) +// .collect::>() +// } +// } +// } + +/// Returns (children_size, child_positions, child_sizes) +fn get_children_layout( menu_tree: &MenuTree<'_, Message, Renderer>, item_width: ItemWidth, item_height: ItemHeight, -) -> Size +) -> (Size, Vec, Vec) where Renderer: renderer::Renderer, { @@ -1088,41 +1142,26 @@ where ItemWidth::Static(s) => f32::from(menu_tree.width.unwrap_or(s)), }; - let height = match item_height { - ItemHeight::Uniform(u) => f32::from(u) * (menu_tree.children.len() as f32), - ItemHeight::Static(s) => menu_tree - .children - .iter() - .fold(0.0, |h, mt| h + f32::from(mt.height.unwrap_or(s))), + let child_sizes:Vec = match item_height { + ItemHeight::Uniform(u) => { + let count = menu_tree.children.len(); + (0..count).map(|_| Size::new(width, u as f32) ).collect() + }, + ItemHeight::Static(s) => { + menu_tree.children.iter().map(|mt| Size::new(width, mt.height.unwrap_or(s) as f32) ).collect() + }, }; - Size::new(width, height) -} + let max_index = menu_tree.children.len() - 1; + let child_positions:Vec = std::iter::once(0.0) + .chain(child_sizes[0..max_index].iter().scan(0.0, |acc, x|{ + *acc += x.height; + Some(*acc) + })).collect(); + + let height = child_sizes.iter().fold(0.0, |acc, x| acc + x.height ); -fn get_child_positions( - menu_tree: &MenuTree<'_, Message, Renderer>, - item_height: ItemHeight, -) -> Vec -where - Renderer: renderer::Renderer, -{ - match item_height { - ItemHeight::Uniform(u) => { - let children_count = menu_tree.children.len(); - (0..children_count) - .map(|i| (i as f32) * f32::from(u)) - .collect() - } - ItemHeight::Static(s) => { - let max_index = menu_tree.children.len() - 1; - std::iter::once(0.0) - .chain(menu_tree.children[0..max_index].iter().scan(0.0, |p, mt| { - *p += f32::from(mt.height.unwrap_or(s)); - Some(*p) - })) - .collect::>() - } - } + (Size::new(width, height), child_positions, child_sizes) } fn search_bound( From ab43ddd0282a7b5a21e13b1bc9d21c8e26ac8284 Mon Sep 17 00:00:00 2001 From: Latidoremi Date: Thu, 3 Aug 2023 18:05:19 +0800 Subject: [PATCH 2/7] Remove get_item_size --- src/native/menu/menu_inner.rs | 51 ++++++++++++++++++----------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/src/native/menu/menu_inner.rs b/src/native/menu/menu_inner.rs index 8d2a64e4..c9ed9b7e 100644 --- a/src/native/menu/menu_inner.rs +++ b/src/native/menu/menu_inner.rs @@ -287,10 +287,12 @@ impl MenuState { let child_nodes = self.menu_bounds.child_positions[start_index..=end_index] .iter() + .zip(self.menu_bounds.child_sizes[start_index..=end_index].iter()) .zip(menu_tree.children[start_index..=end_index].iter()) - .map(|(cp, mt)| { + .map(|((cp, size), mt)| { let mut position = *cp; - let mut size = get_item_size(mt, children_bounds.width, item_height); + let mut size = *size; + // let mut size = get_item_size(mt, children_bounds.width, item_height); if position < lower_bound_rel && (position + size.height) > lower_bound_rel { size.height = position + size.height - lower_bound_rel; @@ -330,7 +332,8 @@ impl MenuState { let position = self.menu_bounds.child_positions[index]; let limits = Limits::new( Size::ZERO, - get_item_size(menu_tree, children_bounds.width, item_height), + // get_item_size(menu_tree, children_bounds.width, item_height), + self.menu_bounds.child_sizes[index] ); let parent_offset = children_bounds.position() - Point::ORIGIN; let mut node = menu_tree.item.as_widget().layout(renderer, &limits); @@ -947,11 +950,13 @@ where 0.0, last_menu_bounds.child_positions[new_index] + last_menu_state.scroll_offset, ); - let item_size = get_item_size( - item, - last_menu_bounds.children_bounds.width, - menu.item_height, - ); + let item_size = last_menu_bounds.child_sizes[new_index]; + + // let item_size = get_item_size( + // item, + // last_menu_bounds.children_bounds.width, + // menu.item_height, + // ); // overlay space item bounds let item_bounds = Rectangle::new(item_position, item_size) @@ -1062,21 +1067,21 @@ where Captured } -fn get_item_size( - menu_tree: &MenuTree<'_, Message, Renderer>, - width: f32, - item_height: ItemHeight, -) -> Size -where - Renderer: renderer::Renderer, -{ - let height = match item_height { - ItemHeight::Uniform(u) => f32::from(u), - ItemHeight::Static(s) => f32::from(menu_tree.height.unwrap_or(s)), - }; +// fn get_item_size( +// menu_tree: &MenuTree<'_, Message, Renderer>, +// width: f32, +// item_height: ItemHeight, +// ) -> Size +// where +// Renderer: renderer::Renderer, +// { +// let height = match item_height { +// ItemHeight::Uniform(u) => f32::from(u), +// ItemHeight::Static(s) => f32::from(menu_tree.height.unwrap_or(s)), +// }; - Size::new(width, height) -} +// Size::new(width, height) +// } // fn get_children_size( // menu_tree: &MenuTree<'_, Message, Renderer>, @@ -1090,7 +1095,6 @@ where // ItemWidth::Uniform(u) => f32::from(u), // ItemWidth::Static(s) => f32::from(menu_tree.width.unwrap_or(s)), // }; - // let height = match item_height { // ItemHeight::Uniform(u) => f32::from(u) * (menu_tree.children.len() as f32), // ItemHeight::Static(s) => menu_tree @@ -1098,7 +1102,6 @@ where // .iter() // .fold(0.0, |h, mt| h + f32::from(mt.height.unwrap_or(s))), // }; - // Size::new(width, height) // } From 537e60f115c8a1db37577af4217d590342775a22 Mon Sep 17 00:00:00 2001 From: Latidoremi Date: Thu, 3 Aug 2023 18:17:48 +0800 Subject: [PATCH 3/7] Dynamic item height --- src/native/menu/menu_inner.rs | 106 +++++++++------------------------- 1 file changed, 27 insertions(+), 79 deletions(-) diff --git a/src/native/menu/menu_inner.rs b/src/native/menu/menu_inner.rs index c9ed9b7e..96f1fb3e 100644 --- a/src/native/menu/menu_inner.rs +++ b/src/native/menu/menu_inner.rs @@ -10,7 +10,7 @@ use iced_widget::core::{ mouse::{self, Cursor}, overlay, renderer, touch, widget::Tree, - Clipboard, Color, Layout, Padding, Point, Rectangle, Shell, Size, Vector, + Clipboard, Color, Layout, Padding, Point, Rectangle, Shell, Size, Vector, Length, }; /// The condition of when to close a menu @@ -49,7 +49,8 @@ pub enum ItemHeight { /// the default value will be used instead, /// which is the value of the Static variant Static(u16), - // TODO: Flex, + /// Dynamic item height + Dynamic(u16), } /// Methods for drawing path highlight @@ -218,6 +219,7 @@ impl MenuBounds { #[allow(clippy::too_many_arguments)] fn new( menu_tree: &MenuTree<'_, Message, Renderer>, + renderer: &Renderer, item_width: ItemWidth, item_height: ItemHeight, viewport_size: Size, @@ -229,9 +231,7 @@ impl MenuBounds { where Renderer: renderer::Renderer, { - // let children_size = get_children_size(menu_tree, item_width, item_height); - // let child_positions = get_child_positions(menu_tree, item_height); - let (children_size, child_positions, child_sizes) = get_children_layout(menu_tree, item_width, item_height); + let (children_size, child_positions, child_sizes) = get_children_layout(menu_tree, renderer, item_width, item_height); // viewport space parent bounds let view_parent_bounds = parent_bounds + overlay_offset; @@ -292,7 +292,6 @@ impl MenuState { .map(|((cp, size), mt)| { let mut position = *cp; let mut size = *size; - // let mut size = get_item_size(mt, children_bounds.width, item_height); if position < lower_bound_rel && (position + size.height) > lower_bound_rel { size.height = position + size.height - lower_bound_rel; @@ -332,7 +331,6 @@ impl MenuState { let position = self.menu_bounds.child_positions[index]; let limits = Limits::new( Size::ZERO, - // get_item_size(menu_tree, children_bounds.width, item_height), self.menu_bounds.child_sizes[index] ); let parent_offset = children_bounds.position() - Point::ORIGIN; @@ -371,7 +369,7 @@ impl MenuState { let end_index = ((upper_bound_rel / f32::from(u)).floor() as usize).min(max_index); (start_index, end_index) } - ItemHeight::Static(s) => { + ItemHeight::Static(s) | ItemHeight::Dynamic(s) => { let positions = &self.menu_bounds.child_positions; let start_index = @@ -478,6 +476,7 @@ where init_root_menu( self, + renderer, overlay_cursor, viewport_size, overlay_offset, @@ -502,6 +501,7 @@ where let overlay_cursor = view_cursor.position().unwrap_or_default() - overlay_offset; process_overlay_events( self, + renderer, viewport_size, overlay_offset, view_cursor, @@ -672,6 +672,7 @@ fn pad_rectangle(rect: Rectangle, padding: Padding) -> Rectangle { fn init_root_menu( menu: &mut Menu<'_, '_, Message, Renderer>, + renderer: &Renderer, overlay_cursor: Point, viewport_size: Size, overlay_offset: Vector, @@ -716,6 +717,7 @@ fn init_root_menu( let menu_bounds = MenuBounds::new( mt, + renderer, menu.item_width, menu.item_height, viewport_size, @@ -800,6 +802,7 @@ where #[allow(unused_results)] fn process_overlay_events( menu: &mut Menu<'_, '_, Message, Renderer>, + renderer: &Renderer, viewport_size: Size, overlay_offset: Vector, view_cursor: Cursor, @@ -924,7 +927,7 @@ where let new_index = match menu.item_height { ItemHeight::Uniform(u) => (height_diff / f32::from(u)).floor() as usize, - ItemHeight::Static(s) => { + ItemHeight::Static(s) | ItemHeight::Dynamic(s) => { let max_index = active_menu.children.len() - 1; search_bound( 0, @@ -952,12 +955,6 @@ where ); let item_size = last_menu_bounds.child_sizes[new_index]; - // let item_size = get_item_size( - // item, - // last_menu_bounds.children_bounds.width, - // menu.item_height, - // ); - // overlay space item bounds let item_bounds = Rectangle::new(item_position, item_size) + (last_menu_bounds.children_bounds.position() - Point::ORIGIN); @@ -976,6 +973,7 @@ where scroll_offset: 0.0, menu_bounds: MenuBounds::new( item, + renderer, menu.item_width, menu.item_height, viewport_size, @@ -1067,73 +1065,10 @@ where Captured } -// fn get_item_size( -// menu_tree: &MenuTree<'_, Message, Renderer>, -// width: f32, -// item_height: ItemHeight, -// ) -> Size -// where -// Renderer: renderer::Renderer, -// { -// let height = match item_height { -// ItemHeight::Uniform(u) => f32::from(u), -// ItemHeight::Static(s) => f32::from(menu_tree.height.unwrap_or(s)), -// }; - -// Size::new(width, height) -// } - -// fn get_children_size( -// menu_tree: &MenuTree<'_, Message, Renderer>, -// item_width: ItemWidth, -// item_height: ItemHeight, -// ) -> Size -// where -// Renderer: renderer::Renderer, -// { -// let width = match item_width { -// ItemWidth::Uniform(u) => f32::from(u), -// ItemWidth::Static(s) => f32::from(menu_tree.width.unwrap_or(s)), -// }; -// let height = match item_height { -// ItemHeight::Uniform(u) => f32::from(u) * (menu_tree.children.len() as f32), -// ItemHeight::Static(s) => menu_tree -// .children -// .iter() -// .fold(0.0, |h, mt| h + f32::from(mt.height.unwrap_or(s))), -// }; -// Size::new(width, height) -// } - -// fn get_child_positions( -// menu_tree: &MenuTree<'_, Message, Renderer>, -// item_height: ItemHeight, -// ) -> Vec -// where -// Renderer: renderer::Renderer, -// { -// match item_height { -// ItemHeight::Uniform(u) => { -// let children_count = menu_tree.children.len(); -// (0..children_count) -// .map(|i| (i as f32) * f32::from(u)) -// .collect() -// } -// ItemHeight::Static(s) => { -// let max_index = menu_tree.children.len() - 1; -// std::iter::once(0.0) -// .chain(menu_tree.children[0..max_index].iter().scan(0.0, |p, mt| { -// *p += f32::from(mt.height.unwrap_or(s)); -// Some(*p) -// })) -// .collect::>() -// } -// } -// } - /// Returns (children_size, child_positions, child_sizes) fn get_children_layout( menu_tree: &MenuTree<'_, Message, Renderer>, + renderer: &Renderer, item_width: ItemWidth, item_height: ItemHeight, ) -> (Size, Vec, Vec) @@ -1153,6 +1088,19 @@ where ItemHeight::Static(s) => { menu_tree.children.iter().map(|mt| Size::new(width, mt.height.unwrap_or(s) as f32) ).collect() }, + ItemHeight::Dynamic(d) => { + menu_tree.children.iter().map(|mt|{ + let w = mt.item.as_widget(); + match w.height() { + Length::Fixed(f) => Size::new(width, f as f32), + Length::Shrink => Size::new( + width, + w.layout(renderer, &Limits::new(Size::ZERO, Size::new(width, f32::MAX))).size().height + ), + _ => Size::new(width, d as f32) + } + }).collect() + } }; let max_index = menu_tree.children.len() - 1; From da6ba3f2f5da935e283620816b96a321334d96c1 Mon Sep 17 00:00:00 2001 From: Latidoremi Date: Thu, 3 Aug 2023 18:20:32 +0800 Subject: [PATCH 4/7] Clean up --- examples/menu/src/main.rs | 20 ++++++------ src/native/menu/menu_inner.rs | 61 +++++++++++++++++++---------------- 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/examples/menu/src/main.rs b/examples/menu/src/main.rs index 498b7942..0444ecc4 100644 --- a/examples/menu/src/main.rs +++ b/examples/menu/src/main.rs @@ -292,11 +292,15 @@ fn debug_item<'a>(label: &str) -> MenuTree<'a, Message, iced::Renderer> { } fn debug_item2<'a>(label: &str) -> MenuTree<'a, Message, iced::Renderer> { - menu_tree!(debug_button(label).width(Length::Fill).height(Length::Shrink)) + menu_tree!(debug_button(label) + .width(Length::Fill) + .height(Length::Shrink)) } fn debug_item3<'a>(label: &str, h: f32) -> MenuTree<'a, Message, iced::Renderer> { - menu_tree!(debug_button(label).width(Length::Fill).height(Length::Fixed(h))) + menu_tree!(debug_button(label) + .width(Length::Fill) + .height(Length::Fixed(h))) } fn color_item<'a>(color: impl Into) -> MenuTree<'a, Message, iced::Renderer> { @@ -778,15 +782,9 @@ fn menu_6<'a>(app: &App) -> MenuTree<'a, Message, iced::Renderer> { vec![ labeled_separator("Primary"), sliders, - debug_item2("AABB") - // .height(80) - , - debug_item3("CCDD", 50.0) - // .height(60) - , - debug_item2("EEFF") - // .height(50) - , + debug_item2("AABB"), // .height(80) + debug_item3("CCDD", 50.0), // .height(60) + debug_item2("EEFF"), // .height(50) ], ) .width(slider_width * slider_count + (slider_count - 1) * spacing); diff --git a/src/native/menu/menu_inner.rs b/src/native/menu/menu_inner.rs index 96f1fb3e..fb25a7be 100644 --- a/src/native/menu/menu_inner.rs +++ b/src/native/menu/menu_inner.rs @@ -10,7 +10,7 @@ use iced_widget::core::{ mouse::{self, Cursor}, overlay, renderer, touch, widget::Tree, - Clipboard, Color, Layout, Padding, Point, Rectangle, Shell, Size, Vector, Length, + Clipboard, Color, Layout, Length, Padding, Point, Rectangle, Shell, Size, Vector, }; /// The condition of when to close a menu @@ -231,7 +231,8 @@ impl MenuBounds { where Renderer: renderer::Renderer, { - let (children_size, child_positions, child_sizes) = get_children_layout(menu_tree, renderer, item_width, item_height); + let (children_size, child_positions, child_sizes) = + get_children_layout(menu_tree, renderer, item_width, item_height); // viewport space parent bounds let view_parent_bounds = parent_bounds + overlay_offset; @@ -263,7 +264,6 @@ impl MenuState { &self, overlay_offset: Vector, slice: MenuSlice, - item_height: ItemHeight, renderer: &Renderer, menu_tree: &MenuTree<'_, Message, Renderer>, ) -> Node @@ -329,10 +329,7 @@ impl MenuState { let children_bounds = self.menu_bounds.children_bounds + overlay_offset; let position = self.menu_bounds.child_positions[index]; - let limits = Limits::new( - Size::ZERO, - self.menu_bounds.child_sizes[index] - ); + let limits = Limits::new(Size::ZERO, self.menu_bounds.child_sizes[index]); let parent_offset = children_bounds.position() - Point::ORIGIN; let mut node = menu_tree.item.as_widget().layout(renderer, &limits); node.move_to(Point::new( @@ -604,7 +601,7 @@ where // calc layout let children_node = - ms.layout(overlay_offset, slice, self.item_height, r, menu_root); + ms.layout(overlay_offset, slice, r, menu_root); let children_layout = Layout::new(&children_node); let children_bounds = children_layout.bounds(); @@ -954,7 +951,7 @@ where last_menu_bounds.child_positions[new_index] + last_menu_state.scroll_offset, ); let item_size = last_menu_bounds.child_sizes[new_index]; - + // overlay space item bounds let item_bounds = Rectangle::new(item_position, item_size) + (last_menu_bounds.children_bounds.position() - Point::ORIGIN); @@ -1080,37 +1077,47 @@ where ItemWidth::Static(s) => f32::from(menu_tree.width.unwrap_or(s)), }; - let child_sizes:Vec = match item_height { + let child_sizes: Vec = match item_height { ItemHeight::Uniform(u) => { let count = menu_tree.children.len(); - (0..count).map(|_| Size::new(width, u as f32) ).collect() - }, - ItemHeight::Static(s) => { - menu_tree.children.iter().map(|mt| Size::new(width, mt.height.unwrap_or(s) as f32) ).collect() - }, - ItemHeight::Dynamic(d) => { - menu_tree.children.iter().map(|mt|{ + (0..count).map(|_| Size::new(width, u as f32)).collect() + } + ItemHeight::Static(s) => menu_tree + .children + .iter() + .map(|mt| Size::new(width, mt.height.unwrap_or(s) as f32)) + .collect(), + ItemHeight::Dynamic(d) => menu_tree + .children + .iter() + .map(|mt| { let w = mt.item.as_widget(); match w.height() { Length::Fixed(f) => Size::new(width, f as f32), Length::Shrink => Size::new( - width, - w.layout(renderer, &Limits::new(Size::ZERO, Size::new(width, f32::MAX))).size().height + width, + w.layout( + renderer, + &Limits::new(Size::ZERO, Size::new(width, f32::MAX)), + ) + .size() + .height, ), - _ => Size::new(width, d as f32) + _ => Size::new(width, d as f32), } - }).collect() - } + }) + .collect(), }; let max_index = menu_tree.children.len() - 1; - let child_positions:Vec = std::iter::once(0.0) - .chain(child_sizes[0..max_index].iter().scan(0.0, |acc, x|{ + let child_positions: Vec = std::iter::once(0.0) + .chain(child_sizes[0..max_index].iter().scan(0.0, |acc, x| { *acc += x.height; Some(*acc) - })).collect(); - - let height = child_sizes.iter().fold(0.0, |acc, x| acc + x.height ); + })) + .collect(); + + let height = child_sizes.iter().fold(0.0, |acc, x| acc + x.height); (Size::new(width, height), child_positions, child_sizes) } From 73fa6b641e00accf36c6b7b95bcb030520fae947 Mon Sep 17 00:00:00 2001 From: Latidoremi Date: Thu, 3 Aug 2023 21:06:18 +0800 Subject: [PATCH 5/7] Fix search_bound --- examples/menu/src/main.rs | 198 ++++++++++++++++++++++++++++++++-- src/native/menu/menu_inner.rs | 74 +++++++------ 2 files changed, 234 insertions(+), 38 deletions(-) diff --git a/examples/menu/src/main.rs b/examples/menu/src/main.rs index 0444ecc4..9db00e50 100644 --- a/examples/menu/src/main.rs +++ b/examples/menu/src/main.rs @@ -190,11 +190,11 @@ impl Application for App { menu_1(self), menu_2(self), menu_3(self), - menu_4(self), - menu_6(self), + menu_44(self), + menu_55(self), ) .item_width(ItemWidth::Static(180)) - .item_height(ItemHeight::Static(25)), + .item_height(ItemHeight::Dynamic(32)), } .spacing(4.0) .bounds_expand(30) @@ -331,7 +331,8 @@ fn sub_menu<'a>( .height(Length::Fill) .vertical_alignment(alignment::Vertical::Center), arrow - ], + ] + .align_items(iced::Alignment::Center), msg, ) .width(Length::Fill) @@ -347,6 +348,46 @@ fn debug_sub_menu<'a>( sub_menu(label, Message::Debug(label.into()), children) } +fn sub_menu2<'a>( + label: &str, + msg: Message, + children: Vec>, +) -> MenuTree<'a, Message, iced::Renderer> { + let handle = svg::Handle::from_path(format!( + "{}/caret-right-fill.svg", + env!("CARGO_MANIFEST_DIR") + )); + let arrow = svg(handle) + .width(Length::Shrink) + .style(theme::Svg::custom_fn(|theme| svg::Appearance { + color: Some(theme.extended_palette().background.base.text), + })); + + menu_tree( + base_button( + row![ + text(label) + .width(Length::Fill) + .height(Length::Shrink) + .vertical_alignment(alignment::Vertical::Center), + arrow + ] + .align_items(iced::Alignment::Center), + msg, + ) + .width(Length::Fill) + .height(Length::Shrink), + children, + ) +} + +fn debug_sub_menu2<'a>( + label: &str, + children: Vec>, +) -> MenuTree<'a, Message, iced::Renderer> { + sub_menu2(label, Message::Debug(label.into()), children) +} + fn separator<'a>() -> MenuTree<'a, Message, iced::Renderer> { menu_tree!(quad::Quad { color: [0.5; 3].into(), @@ -720,6 +761,146 @@ fn menu_4<'a>(_app: &App) -> MenuTree<'a, Message, iced::Renderer> { root } +fn menu_44<'a>(_app: &App) -> MenuTree<'a, Message, iced::Renderer> { + let dekjdaud = debug_sub_menu2( + "dekjdaud", + vec![ + debug_item2("ajrs"), + debug_item2("bsdfho"), + debug_item2("clkjhbf"), + debug_item2("dekjdaud"), + debug_item2("ecsh"), + debug_item2("fweiu"), + debug_item2("giwe"), + debug_item2("heruyv"), + debug_item2("isabe"), + debug_item2("jcsu"), + debug_item2("kaljkahd"), + debug_item2("luyortp"), + debug_item2("mmdyrc"), + debug_item2("nquc"), + debug_item2("ajrs"), + debug_item2("bsdfho"), + debug_item2("clkjhbf"), + debug_item2("dekjdaud"), + debug_item2("ecsh"), + debug_item2("fweiu"), + debug_item2("giwe"), + debug_item2("heruyv"), + debug_item2("isabe"), + debug_item2("jcsu"), + debug_item2("kaljkahd"), + debug_item2("luyortp"), + debug_item2("mmdyrc"), + debug_item2("nquc"), + ], + ); + + let luyortp = debug_sub_menu2( + "luyortp", + vec![ + debug_item2("ajrs"), // 0 + debug_item2("bsdfho"), + debug_item2("clkjhbf"), + debug_item2("dekjdaud"), + debug_item2("ecsh"), + debug_item2("fweiu"), + debug_item2("giwe"), + debug_item2("heruyv"), + debug_item2("isabe"), + debug_item2("jcsu"), + debug_item2("kaljkahd"), + debug_item2("luyortp"), + debug_item2("mmdyrc"), + debug_item2("nquc"), // 13 + ], + ); + + let jcsu = debug_sub_menu2( + "jcsu", + vec![ + debug_item2("ajrs"), // 0 + debug_item2("bsdfho"), + debug_item2("clkjhbf"), + debug_item2("dekjdaud"), + debug_item2("ecsh"), + debug_item2("fweiu"), + debug_item2("giwe"), + debug_item2("heruyv"), + debug_item2("isabe"), + debug_item2("jcsu"), + debug_item2("kaljkahd"), + luyortp, // 11 + debug_item2("mmdyrc"), + debug_item2("nquc"), // 13 + ], + ); + + let root = menu_tree( + debug_button("Scroll"), + vec![ + debug_item2("ajrs"), // 0 + debug_item2("bsdfho"), + debug_item2("clkjhbf"), + debug_item2("dekjdaud"), + debug_item2("ecsh"), + debug_item2("fweiu"), + debug_item2("giwe"), + debug_item2("heruyv"), + debug_item2("isabe"), + jcsu, // 9 + debug_item2("kaljkahd"), + debug_item2("luyortp"), + debug_item2("mmdyrc"), + debug_item2("nquc"), // 13 + debug_item2("ajrs"), // 14 + debug_item2("bsdfho"), + debug_item2("clkjhbf"), + debug_item2("dekjdaud"), + debug_item2("ecsh"), + debug_item2("fweiu"), + debug_item2("giwe"), + debug_item2("heruyv"), + debug_item2("isabe"), + debug_item2("jcsu"), + debug_item2("kaljkahd"), + debug_item2("luyortp"), + debug_item2("mmdyrc"), + debug_item2("nquc"), // 27 + debug_item2("ajrs"), // 28 + debug_item2("bsdfho"), + debug_item2("clkjhbf"), + dekjdaud, + debug_item2("ecsh"), + debug_item2("fweiu"), + debug_item2("giwe"), + debug_item2("heruyv"), + debug_item2("isabe"), + debug_item2("jcsu"), + debug_item2("kaljkahd"), + debug_item2("luyortp"), + debug_item2("mmdyrc"), + debug_item2("nquc"), // 41 + debug_item2("ajrs"), // 42 + debug_item2("bsdfho"), + debug_item2("clkjhbf"), + debug_item2("dekjdaud"), + debug_item2("ecsh"), + debug_item2("fweiu"), + debug_item2("giwe"), + debug_item2("heruyv"), + debug_item2("isabe"), + debug_item2("jcsu"), + debug_item2("kaljkahd"), // 52 + debug_item2("luyortp"), + debug_item2("mmdyrc"), + debug_item2("nquc"), // 55 + ], + ); + + root +} + fn menu_5<'a>(app: &App) -> MenuTree<'a, Message, iced::Renderer> { let slider_count = 3; let slider_width = 30; @@ -753,7 +934,7 @@ fn menu_5<'a>(app: &App) -> MenuTree<'a, Message, iced::Renderer> { root } -fn menu_6<'a>(app: &App) -> MenuTree<'a, Message, iced::Renderer> { +fn menu_55<'a>(app: &App) -> MenuTree<'a, Message, iced::Renderer> { let slider_count = 3; let slider_width = 30; let spacing = 4; @@ -764,14 +945,17 @@ fn menu_6<'a>(app: &App) -> MenuTree<'a, Message, iced::Renderer> { vertical_slider(0..=255, r, move |x| Message::ColorChange(Color::from_rgb8( x, g, b ))) + .height(80) .width(30), vertical_slider(0..=255, g, move |x| Message::ColorChange(Color::from_rgb8( r, x, b ))) + .height(80) .width(30), vertical_slider(0..=255, b, move |x| Message::ColorChange(Color::from_rgb8( r, g, x ))) + .height(80) .width(30), ] .spacing(4)) @@ -782,9 +966,9 @@ fn menu_6<'a>(app: &App) -> MenuTree<'a, Message, iced::Renderer> { vec![ labeled_separator("Primary"), sliders, - debug_item2("AABB"), // .height(80) + debug_item2("AABB"), // .height(80) debug_item3("CCDD", 50.0), // .height(60) - debug_item2("EEFF"), // .height(50) + debug_item2("EEFF"), // .height(50) ], ) .width(slider_width * slider_count + (slider_count - 1) * spacing); diff --git a/src/native/menu/menu_inner.rs b/src/native/menu/menu_inner.rs index fb25a7be..f3eda2f2 100644 --- a/src/native/menu/menu_inner.rs +++ b/src/native/menu/menu_inner.rs @@ -232,7 +232,7 @@ impl MenuBounds { Renderer: renderer::Renderer, { let (children_size, child_positions, child_sizes) = - get_children_layout(menu_tree, renderer, item_width, item_height); + get_children_layout(menu_tree, renderer, viewport_size, item_width, item_height); // viewport space parent bounds let view_parent_bounds = parent_bounds + overlay_offset; @@ -318,7 +318,6 @@ impl MenuState { &self, overlay_offset: Vector, index: usize, - item_height: ItemHeight, renderer: &Renderer, menu_tree: &MenuTree<'_, Message, Renderer>, ) -> Node @@ -339,12 +338,11 @@ impl MenuState { node } - fn slice( + fn slice( &self, viewport_size: Size, overlay_offset: Vector, item_height: ItemHeight, - menu_tree: &MenuTree<'_, Message, Renderer>, ) -> MenuSlice { // viewport space children bounds let children_bounds = self.menu_bounds.children_bounds + overlay_offset; @@ -366,19 +364,25 @@ impl MenuState { let end_index = ((upper_bound_rel / f32::from(u)).floor() as usize).min(max_index); (start_index, end_index) } - ItemHeight::Static(s) | ItemHeight::Dynamic(s) => { + ItemHeight::Static(_) | ItemHeight::Dynamic(_) => { let positions = &self.menu_bounds.child_positions; + let sizes = &self.menu_bounds.child_sizes; - let start_index = - search_bound(0, 0, max_index, s, lower_bound_rel, positions, menu_tree); + let start_index = search_bound( + 0, + 0, + max_index, + lower_bound_rel, + positions, + sizes, + ); let end_index = search_bound( max_index, start_index, max_index, - s, upper_bound_rel, positions, - menu_tree, + &sizes, ) .min(max_index); @@ -462,7 +466,6 @@ where let menu_status = process_menu_events( self.tree, self.menu_roots, - self.item_height, event.clone(), view_cursor, renderer, @@ -595,17 +598,20 @@ where let draw_menu = |r: &mut Renderer| { // calc slice let slice = - ms.slice(viewport_size, overlay_offset, self.item_height, menu_root); + ms.slice(viewport_size, overlay_offset, self.item_height); let start_index = slice.start_index; let end_index = slice.end_index; // calc layout - let children_node = - ms.layout(overlay_offset, slice, r, menu_root); + let children_node = ms.layout(overlay_offset, slice, r, menu_root); let children_layout = Layout::new(&children_node); let children_bounds = children_layout.bounds(); // draw menu background + // let bounds = pad_rectangle(children_bounds, styling.background_expand.into()); + // println!("cursor: {:?}", view_cursor); + // println!("bg_bounds: {:?}", bounds); + // println!("color: {:?}\n", styling.background); let menu_quad = renderer::Quad { bounds: pad_rectangle(children_bounds, styling.background_expand.into()), border_radius: styling.border_radius.into(), @@ -740,7 +746,6 @@ fn init_root_menu( fn process_menu_events<'b, Message, Renderer>( tree: &'b mut Tree, menu_roots: &'b mut [MenuTree<'_, Message, Renderer>], - item_height: ItemHeight, event: event::Event, view_cursor: Cursor, renderer: &Renderer, @@ -774,7 +779,6 @@ where let child_node = last_ms.layout_single( overlay_offset, last_ms.index.expect("missing index within menu state."), - item_height, renderer, mt, ); @@ -924,16 +928,15 @@ where let new_index = match menu.item_height { ItemHeight::Uniform(u) => (height_diff / f32::from(u)).floor() as usize, - ItemHeight::Static(s) | ItemHeight::Dynamic(s) => { + ItemHeight::Static(_) | ItemHeight::Dynamic(_) => { let max_index = active_menu.children.len() - 1; search_bound( 0, 0, max_index, - s, height_diff, &last_menu_bounds.child_positions, - active_menu, + &last_menu_bounds.child_sizes, ) } }; @@ -1066,6 +1069,7 @@ where fn get_children_layout( menu_tree: &MenuTree<'_, Message, Renderer>, renderer: &Renderer, + viewport_size: Size, item_width: ItemWidth, item_height: ItemHeight, ) -> (Size, Vec, Vec) @@ -1094,15 +1098,23 @@ where let w = mt.item.as_widget(); match w.height() { Length::Fixed(f) => Size::new(width, f as f32), - Length::Shrink => Size::new( - width, - w.layout( - renderer, - &Limits::new(Size::ZERO, Size::new(width, f32::MAX)), - ) - .size() - .height, - ), + Length::Shrink => { + let l_height = w + .layout( + renderer, + &Limits::new(Size::ZERO, Size::new(width, viewport_size.height)), + ) + .size() + .height; + + let height = if (viewport_size.height - l_height).abs() < 0.0001 { + d as f32 + } else { + l_height + }; + + Size::new(width, height) + } _ => Size::new(width, d as f32), } }) @@ -1122,14 +1134,13 @@ where (Size::new(width, height), child_positions, child_sizes) } -fn search_bound( +fn search_bound( default: usize, default_left: usize, default_right: usize, - default_height: u16, bound: f32, positions: &[f32], - menu_tree: &MenuTree<'_, Message, Renderer>, + sizes: &[Size], ) -> usize { // binary search let mut left = default_left; @@ -1144,7 +1155,8 @@ fn search_bound( left = m; } } - let height = f32::from(menu_tree.children[left].height.unwrap_or(default_height)); + // let height = f32::from(menu_tree.children[left].height.unwrap_or(default_height)); + let height = sizes[left].height; if positions[left] + height > bound { index = left; } From 53bec137e8b07aa16e66e7e7b1f8436ec45a95da Mon Sep 17 00:00:00 2001 From: Latidoremi Date: Thu, 3 Aug 2023 23:21:35 +0800 Subject: [PATCH 6/7] Minor fix --- examples/menu/src/main.rs | 207 +++------------------------------- src/native/menu/menu_inner.rs | 44 ++++---- 2 files changed, 36 insertions(+), 215 deletions(-) diff --git a/examples/menu/src/main.rs b/examples/menu/src/main.rs index 9db00e50..f7356813 100644 --- a/examples/menu/src/main.rs +++ b/examples/menu/src/main.rs @@ -175,7 +175,7 @@ impl Application for App { SizeOption::Uniform => { menu_bar!(menu_1(self), menu_2(self), menu_3(self), menu_4(self)) .item_width(ItemWidth::Uniform(180)) - .item_height(ItemHeight::Uniform(25)) + .item_height(ItemHeight::Uniform(27)) } SizeOption::Static => menu_bar!( menu_1(self), @@ -185,16 +185,16 @@ impl Application for App { menu_5(self), ) .item_width(ItemWidth::Static(180)) - .item_height(ItemHeight::Static(25)), + .item_height(ItemHeight::Static(35)), SizeOption::DynamicHeight => menu_bar!( menu_1(self), menu_2(self), menu_3(self), - menu_44(self), - menu_55(self), + menu_4(self), + menu_6(self), ) .item_width(ItemWidth::Static(180)) - .item_height(ItemHeight::Dynamic(32)), + .item_height(ItemHeight::Dynamic(35)), } .spacing(4.0) .bounds_expand(30) @@ -348,46 +348,6 @@ fn debug_sub_menu<'a>( sub_menu(label, Message::Debug(label.into()), children) } -fn sub_menu2<'a>( - label: &str, - msg: Message, - children: Vec>, -) -> MenuTree<'a, Message, iced::Renderer> { - let handle = svg::Handle::from_path(format!( - "{}/caret-right-fill.svg", - env!("CARGO_MANIFEST_DIR") - )); - let arrow = svg(handle) - .width(Length::Shrink) - .style(theme::Svg::custom_fn(|theme| svg::Appearance { - color: Some(theme.extended_palette().background.base.text), - })); - - menu_tree( - base_button( - row![ - text(label) - .width(Length::Fill) - .height(Length::Shrink) - .vertical_alignment(alignment::Vertical::Center), - arrow - ] - .align_items(iced::Alignment::Center), - msg, - ) - .width(Length::Fill) - .height(Length::Shrink), - children, - ) -} - -fn debug_sub_menu2<'a>( - label: &str, - children: Vec>, -) -> MenuTree<'a, Message, iced::Renderer> { - sub_menu2(label, Message::Debug(label.into()), children) -} - fn separator<'a>() -> MenuTree<'a, Message, iced::Renderer> { menu_tree!(quad::Quad { color: [0.5; 3].into(), @@ -761,146 +721,6 @@ fn menu_4<'a>(_app: &App) -> MenuTree<'a, Message, iced::Renderer> { root } -fn menu_44<'a>(_app: &App) -> MenuTree<'a, Message, iced::Renderer> { - let dekjdaud = debug_sub_menu2( - "dekjdaud", - vec![ - debug_item2("ajrs"), - debug_item2("bsdfho"), - debug_item2("clkjhbf"), - debug_item2("dekjdaud"), - debug_item2("ecsh"), - debug_item2("fweiu"), - debug_item2("giwe"), - debug_item2("heruyv"), - debug_item2("isabe"), - debug_item2("jcsu"), - debug_item2("kaljkahd"), - debug_item2("luyortp"), - debug_item2("mmdyrc"), - debug_item2("nquc"), - debug_item2("ajrs"), - debug_item2("bsdfho"), - debug_item2("clkjhbf"), - debug_item2("dekjdaud"), - debug_item2("ecsh"), - debug_item2("fweiu"), - debug_item2("giwe"), - debug_item2("heruyv"), - debug_item2("isabe"), - debug_item2("jcsu"), - debug_item2("kaljkahd"), - debug_item2("luyortp"), - debug_item2("mmdyrc"), - debug_item2("nquc"), - ], - ); - - let luyortp = debug_sub_menu2( - "luyortp", - vec![ - debug_item2("ajrs"), // 0 - debug_item2("bsdfho"), - debug_item2("clkjhbf"), - debug_item2("dekjdaud"), - debug_item2("ecsh"), - debug_item2("fweiu"), - debug_item2("giwe"), - debug_item2("heruyv"), - debug_item2("isabe"), - debug_item2("jcsu"), - debug_item2("kaljkahd"), - debug_item2("luyortp"), - debug_item2("mmdyrc"), - debug_item2("nquc"), // 13 - ], - ); - - let jcsu = debug_sub_menu2( - "jcsu", - vec![ - debug_item2("ajrs"), // 0 - debug_item2("bsdfho"), - debug_item2("clkjhbf"), - debug_item2("dekjdaud"), - debug_item2("ecsh"), - debug_item2("fweiu"), - debug_item2("giwe"), - debug_item2("heruyv"), - debug_item2("isabe"), - debug_item2("jcsu"), - debug_item2("kaljkahd"), - luyortp, // 11 - debug_item2("mmdyrc"), - debug_item2("nquc"), // 13 - ], - ); - - let root = menu_tree( - debug_button("Scroll"), - vec![ - debug_item2("ajrs"), // 0 - debug_item2("bsdfho"), - debug_item2("clkjhbf"), - debug_item2("dekjdaud"), - debug_item2("ecsh"), - debug_item2("fweiu"), - debug_item2("giwe"), - debug_item2("heruyv"), - debug_item2("isabe"), - jcsu, // 9 - debug_item2("kaljkahd"), - debug_item2("luyortp"), - debug_item2("mmdyrc"), - debug_item2("nquc"), // 13 - debug_item2("ajrs"), // 14 - debug_item2("bsdfho"), - debug_item2("clkjhbf"), - debug_item2("dekjdaud"), - debug_item2("ecsh"), - debug_item2("fweiu"), - debug_item2("giwe"), - debug_item2("heruyv"), - debug_item2("isabe"), - debug_item2("jcsu"), - debug_item2("kaljkahd"), - debug_item2("luyortp"), - debug_item2("mmdyrc"), - debug_item2("nquc"), // 27 - debug_item2("ajrs"), // 28 - debug_item2("bsdfho"), - debug_item2("clkjhbf"), - dekjdaud, - debug_item2("ecsh"), - debug_item2("fweiu"), - debug_item2("giwe"), - debug_item2("heruyv"), - debug_item2("isabe"), - debug_item2("jcsu"), - debug_item2("kaljkahd"), - debug_item2("luyortp"), - debug_item2("mmdyrc"), - debug_item2("nquc"), // 41 - debug_item2("ajrs"), // 42 - debug_item2("bsdfho"), - debug_item2("clkjhbf"), - debug_item2("dekjdaud"), - debug_item2("ecsh"), - debug_item2("fweiu"), - debug_item2("giwe"), - debug_item2("heruyv"), - debug_item2("isabe"), - debug_item2("jcsu"), - debug_item2("kaljkahd"), // 52 - debug_item2("luyortp"), - debug_item2("mmdyrc"), - debug_item2("nquc"), // 55 - ], - ); - - root -} - fn menu_5<'a>(app: &App) -> MenuTree<'a, Message, iced::Renderer> { let slider_count = 3; let slider_width = 30; @@ -934,7 +754,7 @@ fn menu_5<'a>(app: &App) -> MenuTree<'a, Message, iced::Renderer> { root } -fn menu_55<'a>(app: &App) -> MenuTree<'a, Message, iced::Renderer> { +fn menu_6<'a>(app: &App) -> MenuTree<'a, Message, iced::Renderer> { let slider_count = 3; let slider_width = 30; let spacing = 4; @@ -945,30 +765,29 @@ fn menu_55<'a>(app: &App) -> MenuTree<'a, Message, iced::Renderer> { vertical_slider(0..=255, r, move |x| Message::ColorChange(Color::from_rgb8( x, g, b ))) - .height(80) .width(30), vertical_slider(0..=255, g, move |x| Message::ColorChange(Color::from_rgb8( r, x, b ))) - .height(80) .width(30), vertical_slider(0..=255, b, move |x| Message::ColorChange(Color::from_rgb8( r, g, x ))) - .height(80) .width(30), ] - .spacing(4)) - .height(100); + .spacing(4) + .height(100)); let root = menu_tree( debug_button("Dynamic Height"), vec![ labeled_separator("Primary"), sliders, - debug_item2("AABB"), // .height(80) - debug_item3("CCDD", 50.0), // .height(60) - debug_item2("EEFF"), // .height(50) + debug_item2("AABB"), + debug_item3("CCDD", 50.0), + debug_item2("EEFF"), + debug_item("GGHH").height(100), + debug_item2("IIJJ"), ], ) .width(slider_width * slider_count + (slider_count - 1) * spacing); diff --git a/src/native/menu/menu_inner.rs b/src/native/menu/menu_inner.rs index f3eda2f2..695d94a3 100644 --- a/src/native/menu/menu_inner.rs +++ b/src/native/menu/menu_inner.rs @@ -42,14 +42,19 @@ pub enum ItemWidth { /// The height of an item #[derive(Debug, Clone, Copy)] pub enum ItemHeight { - /// Use uniform height + /// Use uniform height. Uniform(u16), - /// Static tries to use the height value of each menu tree, - /// if that value is None, - /// the default value will be used instead, - /// which is the value of the Static variant + /// Static tries to use `MenuTree.height` as item height, + /// when it's `None` it'll fallback to the value of the `Static` variant. Static(u16), - /// Dynamic item height + /// Dynamic tries to automatically choose the proper item height for you, + /// but it only works in certain cases: + /// + /// - Fixed height + /// - Shrink height + /// - Menu tree height + /// + /// If none of these is the case, it'll fallback to the value of the `Dynamic` variant. Dynamic(u16), } @@ -232,7 +237,7 @@ impl MenuBounds { Renderer: renderer::Renderer, { let (children_size, child_positions, child_sizes) = - get_children_layout(menu_tree, renderer, viewport_size, item_width, item_height); + get_children_layout(menu_tree, renderer, item_width, item_height); // viewport space parent bounds let view_parent_bounds = parent_bounds + overlay_offset; @@ -368,14 +373,7 @@ impl MenuState { let positions = &self.menu_bounds.child_positions; let sizes = &self.menu_bounds.child_sizes; - let start_index = search_bound( - 0, - 0, - max_index, - lower_bound_rel, - positions, - sizes, - ); + let start_index = search_bound(0, 0, max_index, lower_bound_rel, positions, sizes); let end_index = search_bound( max_index, start_index, @@ -597,8 +595,7 @@ where let draw_menu = |r: &mut Renderer| { // calc slice - let slice = - ms.slice(viewport_size, overlay_offset, self.item_height); + let slice = ms.slice(viewport_size, overlay_offset, self.item_height); let start_index = slice.start_index; let end_index = slice.end_index; @@ -1069,7 +1066,6 @@ where fn get_children_layout( menu_tree: &MenuTree<'_, Message, Renderer>, renderer: &Renderer, - viewport_size: Size, item_width: ItemWidth, item_height: ItemHeight, ) -> (Size, Vec, Vec) @@ -1102,12 +1098,12 @@ where let l_height = w .layout( renderer, - &Limits::new(Size::ZERO, Size::new(width, viewport_size.height)), + &Limits::new(Size::ZERO, Size::new(width, f32::MAX)), ) .size() .height; - let height = if (viewport_size.height - l_height).abs() < 0.0001 { + let height = if (f32::MAX - l_height) < 0.001 { d as f32 } else { l_height @@ -1115,7 +1111,13 @@ where Size::new(width, height) } - _ => Size::new(width, d as f32), + _ => { + if let Some(h) = mt.height { + Size::new(width, h as f32) + } else { + Size::new(width, d as f32) + } + } } }) .collect(), From 30463445faacf0ab9f734d2b10962445d1d5ef8a Mon Sep 17 00:00:00 2001 From: Latidoremi Date: Fri, 4 Aug 2023 09:43:17 +0800 Subject: [PATCH 7/7] Clippy --- src/native/menu/menu_inner.rs | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/native/menu/menu_inner.rs b/src/native/menu/menu_inner.rs index 695d94a3..26269867 100644 --- a/src/native/menu/menu_inner.rs +++ b/src/native/menu/menu_inner.rs @@ -380,7 +380,7 @@ impl MenuState { max_index, upper_bound_rel, positions, - &sizes, + sizes, ) .min(max_index); @@ -1062,6 +1062,7 @@ where Captured } +#[allow(clippy::pedantic)] /// Returns (children_size, child_positions, child_sizes) fn get_children_layout( menu_tree: &MenuTree<'_, Message, Renderer>, @@ -1080,12 +1081,12 @@ where let child_sizes: Vec = match item_height { ItemHeight::Uniform(u) => { let count = menu_tree.children.len(); - (0..count).map(|_| Size::new(width, u as f32)).collect() + (0..count).map(|_| Size::new(width, f32::from(u))).collect() } ItemHeight::Static(s) => menu_tree .children .iter() - .map(|mt| Size::new(width, mt.height.unwrap_or(s) as f32)) + .map(|mt| Size::new(width, f32::from(mt.height.unwrap_or(s)))) .collect(), ItemHeight::Dynamic(d) => menu_tree .children @@ -1093,7 +1094,7 @@ where .map(|mt| { let w = mt.item.as_widget(); match w.height() { - Length::Fixed(f) => Size::new(width, f as f32), + Length::Fixed(f) => Size::new(width, f), Length::Shrink => { let l_height = w .layout( @@ -1104,20 +1105,17 @@ where .height; let height = if (f32::MAX - l_height) < 0.001 { - d as f32 + f32::from(d) } else { l_height }; Size::new(width, height) } - _ => { - if let Some(h) = mt.height { - Size::new(width, h as f32) - } else { - Size::new(width, d as f32) - } - } + _ => mt.height.map_or_else( + || Size::new(width, f32::from(d)), + |h| Size::new(width, f32::from(h)), + ), } }) .collect(),