diff --git a/examples/menu/src/main.rs b/examples/menu/src/main.rs index 9a0deadc..b6df5bca 100644 --- a/examples/menu/src/main.rs +++ b/examples/menu/src/main.rs @@ -141,278 +141,294 @@ impl Application for App { let menu_tpl_1 = |items| Menu::new(items).max_width(180.0).offset(15.0).spacing(5.0); let menu_tpl_2 = |items| Menu::new(items).max_width(180.0).offset(0.0).spacing(5.0); - let mb = menu_bar!((debug_button_s("Nested Menus"), { - let sub5 = menu_tpl_2(menu_items!((debug_button("Item"))(debug_button("Item"))( - debug_button("Item") - )(debug_button("Item"))( - debug_button("Item") - ))); - - let sub4 = menu_tpl_2(menu_items!((debug_button("Item"))(debug_button("Item"))( - debug_button("Item") - )(debug_button("Item")))) - .width(200.0); - - let sub3 = menu_tpl_2(menu_items!((debug_button("You can"))(debug_button( - "nest menus" - ))(submenu_button("SUB"), sub4)( - debug_button("how ever") - )(debug_button("You like"))( - submenu_button("SUB"), sub5 - ))) - .width(180.0); - - let sub2 = menu_tpl_2(menu_items!((debug_button("Item"))(debug_button("Item"))( - debug_button("Item") - )( - submenu_button("More sub menus"), sub3 - )(debug_button("Item"))( - debug_button("Item") - )(debug_button("Item")))) - .width(160.0); - - let sub1 = menu_tpl_2(menu_items!((debug_button("Item"))(debug_button("Item"))( - submenu_button("Another sub menu"), - sub2 - )(debug_button("Item"))( - debug_button("Item") - )(debug_button("Item")))) - .width(220.0); - - menu_tpl_1(menu_items!((debug_button("Item"))(debug_button("Item"))( - submenu_button("A sub menu"), - sub1 - )(debug_button("Item"))( - debug_button("Item") - )(debug_button("Item")))) - .width(140.0) - })( - debug_button_s("Widgets"), - menu_tpl_1(menu_items!((debug_button("You can use any widget"))( - debug_button("as a menu item") - )( - button( + #[rustfmt::skip] + let mb = menu_bar!( + (debug_button_s("Nested Menus"), { + let sub5 = menu_tpl_2(menu_items!( + (debug_button("Item")) + (debug_button("Item")) + (debug_button("Item")) + (debug_button("Item")) + (debug_button("Item")) + )); + + let sub4 = menu_tpl_2(menu_items!( + (debug_button("Item")) + (debug_button("Item")) + (debug_button("Item")) + (debug_button("Item")) + )).width(200.0); + + let sub3 = menu_tpl_2(menu_items!( + (debug_button("You can")) + (debug_button("nest menus")) + (submenu_button("SUB"), sub4) + (debug_button("how ever")) + (debug_button("You like")) + (submenu_button("SUB"), sub5) + )).width(180.0); + + let sub2 = menu_tpl_2(menu_items!( + (debug_button("Item")) + (debug_button("Item")) + (debug_button("Item")) + (submenu_button("More sub menus"), sub3) + (debug_button("Item")) + (debug_button("Item")) + (debug_button("Item")) + )).width(160.0); + + let sub1 = menu_tpl_2(menu_items!( + (debug_button("Item")) + (debug_button("Item")) + (submenu_button("Another sub menu"), sub2) + (debug_button("Item")) + (debug_button("Item")) + (debug_button("Item")) + )).width(220.0); + + menu_tpl_1(menu_items!( + (debug_button("Item")) + (debug_button("Item")) + (submenu_button("A sub menu"), sub1) + (debug_button("Item")) + (debug_button("Item")) + (debug_button("Item")) + )).width(140.0) + }) + (debug_button_s("Widgets"), menu_tpl_1(menu_items!( + (debug_button("You can use any widget")) + (debug_button("as a menu item")) + (button( text("Button") .width(Length::Fill) .vertical_alignment(alignment::Vertical::Center), + ) + .width(Length::Fill) + .on_press(Message::Debug("Button".into())) ) - .width(Length::Fill) - .on_press(Message::Debug("Button".into())) - )( - // checkbox("Checkbox", self.check, Message::CheckChange).width(Length::Fill) - checkbox("Checkbox", self.check) - .on_toggle(|x| Message::CheckChange(x)) + (checkbox("Checkbox", self.check).on_toggle(|x| Message::CheckChange(x)) .width(Length::Fill) - )(row![ - "Slider", - horizontal_space().width(Length::Fixed(8.0)), - slider(0..=255, self.value, Message::ValueChange) - ])( - text_input("", &self.text).on_input(Message::TextChange) - )( - container(toggler( - Some("Or as a sub menu item".to_string()), - self.toggle, - Message::ToggleChange, - )) - .padding([0, 8]) - .height(30.0) - .align_y(alignment::Vertical::Center), - menu_tpl_2(menu_items!((debug_button("Item"))(debug_button("Item"))( - debug_button("Item") - )(debug_button("Item")))) - )(debug_button("Separator"))( - separator() - )(debug_button( - "Labeled Separator" - ))(labeled_separator("Separator"))( - debug_button("Dot Separator") - )(dot_separator(&self.theme))( - debug_button("Item") - ))) - .width(240.0) - )( - debug_button_s("Controls"), - menu_tpl_1(menu_items!((row![toggler( - Some("Dark Mode".into()), - self.dark_mode, - Message::ThemeChange - )] - .padding([0, 8]))(color_button([ - 0.45, 0.25, 0.57 - ]))(color_button([ - 0.15, 0.59, 0.64 - ]))(color_button([ - 0.76, 0.82, 0.20 - ]))(color_button([ - 0.17, 0.27, 0.33 - ]))( - labeled_button("Primary", Message::None).width(Length::Fill), - { - let [r, g, b, _] = self.theme.palette().primary.into_rgba8(); - - menu_tpl_2(menu_items!((slider(0..=255, r, move |x| { - Message::ColorChange(Color::from_rgb8(x, g, b)) - }))(slider( - 0..=255, - g, - move |x| { Message::ColorChange(Color::from_rgb8(r, x, b)) } - ))(slider( - 0..=255, - b, - move |x| { Message::ColorChange(Color::from_rgb8(r, g, x)) } - )))) - } - ))) - )( - debug_button_s("Scroll"), - menu_tpl_1(menu_items!((debug_button("ajrs"))(debug_button("bsdfho"))( - debug_button("clkjhbf") - )(debug_button("dekjdaud"))( - debug_button("ecsh") - )(debug_button("fweiu"))( - debug_button("giwe") - )(debug_button("heruyv"))( - debug_button("isabe") - )( - submenu_button("jcsu"), - menu_tpl_2(menu_items!((debug_button("ajrs"))(debug_button("bsdfho"))( - debug_button("clkjhbf") - )(debug_button("dekjdaud"))( - debug_button("ecsh") - )(debug_button("fweiu"))( - debug_button("giwe") - )(debug_button("heruyv"))( - debug_button("isabe") - )(debug_button("jcsu"))( - debug_button("kaljkahd") - )( - submenu_button("luyortp"), - menu_tpl_2(menu_items!((debug_button("ajrs"))(debug_button("bsdfho"))( - debug_button("clkjhbf") - )(debug_button("dekjdaud"))( - debug_button("ecsh") - )(debug_button("fweiu"))( - debug_button("giwe") - )(debug_button("heruyv"))( - debug_button("isabe") - )(debug_button("jcsu"))( - debug_button("kaljkahd") - )(debug_button("luyortp"))( - debug_button("mmdyrc") - )(debug_button("nquc")))) - )(debug_button("mmdyrc"))( - debug_button("nquc") - ))) - )(debug_button("kaljkahd"))( - debug_button("luyortp") - )(debug_button("mmdyrc"))( - debug_button("nquc") - )(debug_button("ajrs"))( - debug_button("bsdfho") - )(debug_button("clkjhbf"))( - debug_button("dekjdaud") - )(debug_button("ecsh"))( - debug_button("fweiu") - )(debug_button("giwe"))( - debug_button("heruyv") - )(debug_button("isabe"))( - debug_button("jcsu") - )(debug_button("kaljkahd"))( - debug_button("luyortp") - )(debug_button("mmdyrc"))( - debug_button("nquc") - )(debug_button("ajrs"))( - debug_button("bsdfho") - )(debug_button("clkjhbf"))( - submenu_button("dekjdaud"), - menu_tpl_2(menu_items!((debug_button("ajrs"))(debug_button("bsdfho"))( - debug_button("clkjhbf") - )(debug_button("dekjdaud"))( - debug_button("ecsh") - )(debug_button("fweiu"))( - debug_button("giwe") - )(debug_button("heruyv"))( - debug_button("isabe") - )(debug_button("jcsu"))( - debug_button("kaljkahd") - )(debug_button("luyortp"))( - debug_button("mmdyrc") - )(debug_button("nquc"))( - debug_button("ajrs") - )(debug_button("bsdfho"))( - debug_button("clkjhbf") - )(debug_button("dekjdaud"))( - debug_button("ecsh") - )(debug_button("fweiu"))( - debug_button("giwe") - )(debug_button("heruyv"))( - debug_button("isabe") - )(debug_button("jcsu"))( - debug_button("kaljkahd") - )(debug_button("luyortp"))( - debug_button("mmdyrc") - )(debug_button("nquc")))) - )(debug_button("ecsh"))( - debug_button("fweiu") - )(debug_button("giwe"))( - debug_button("heruyv") - )(debug_button("isabe"))( - debug_button("jcsu") - )(debug_button("kaljkahd"))( - debug_button("luyortp") - )(debug_button("mmdyrc"))( - debug_button("nquc") - )(debug_button("ajrs"))( - debug_button("bsdfho") - )(debug_button("clkjhbf"))( - debug_button("dekjdaud") - )(debug_button("ecsh"))( - debug_button("fweiu") - )(debug_button("giwe"))( - debug_button("heruyv") - )(debug_button("isabe"))( - debug_button("jcsu") - )(debug_button("kaljkahd"))( - debug_button("luyortp") - )(debug_button("mmdyrc"))( - debug_button("nquc") + ) + ( + row![ + "Slider", + horizontal_space().width(Length::Fixed(8.0)), + slider(0..=255, self.value, Message::ValueChange) + ] + ) + (text_input("", &self.text).on_input(Message::TextChange)) + (container(toggler( + Some("Or as a sub menu item".to_string()), + self.toggle, + Message::ToggleChange, + )) + .padding([0, 8]) + .height(30.0) + .align_y(alignment::Vertical::Center), + menu_tpl_2(menu_items!( + (debug_button("Item")) + (debug_button("Item")) + (debug_button("Item")) + (debug_button("Item")) + )) + ) + (debug_button("Separator")) + (separator()) + (debug_button("Labeled Separator")) + (labeled_separator("Separator")) + (debug_button("Dot Separator")) + (dot_separator(&self.theme)) + (debug_button("Item")) + (debug_button("Item")) + )).width(240.0)) + (debug_button_s("Controls"), menu_tpl_1(menu_items!( + (row![toggler( + Some("Dark Mode".into()), + self.dark_mode, + Message::ThemeChange + )].padding([0, 8]) + ) + (color_button([0.45, 0.25, 0.57])) + (color_button([0.15, 0.59, 0.64])) + (color_button([0.76, 0.82, 0.20])) + (color_button([0.17, 0.27, 0.33])) + (labeled_button("Primary", Message::None) + .width(Length::Fill), + { + let [r, g, b, _] = self.theme.palette().primary.into_rgba8(); + + menu_tpl_2(menu_items!( + (slider(0..=255, r, move |x| { + Message::ColorChange(Color::from_rgb8(x, g, b)) + })) + (slider(0..=255, g, move |x| { + Message::ColorChange(Color::from_rgb8(r, x, b)) + })) + (slider(0..=255, b, move |x| { + Message::ColorChange(Color::from_rgb8(r, g, x)) + })) + )) + } + ) ))) - )(debug_button_s("Dynamic height"), { - let slider_count = 3; - let slider_width = 30; - let spacing = 5; - let pad = 20; - let [r, g, b, _] = self.theme.palette().primary.into_rgba8(); - - menu_tpl_1(menu_items!((labeled_separator("Primary"))( - row![ - vertical_slider(0..=255, r, move |x| Message::ColorChange(Color::from_rgb8( - x, g, b + (debug_button_s("Scroll"), menu_tpl_1(menu_items!( + (debug_button("ajrs")) + (debug_button("bsdfho")) + (debug_button("clkjhbf")) + (debug_button("dekjdaud")) + (debug_button("ecsh")) + (debug_button("fweiu")) + (debug_button("giwe")) + (debug_button("heruyv")) + (debug_button("isabe")) + (submenu_button("jcsu"), menu_tpl_2(menu_items!( + (debug_button("ajrs")) + (debug_button("bsdfho")) + (debug_button("clkjhbf")) + (debug_button("dekjdaud")) + (debug_button("ecsh")) + (debug_button("fweiu")) + (debug_button("giwe")) + (debug_button("heruyv")) + (debug_button("isabe")) + (debug_button("jcsu")) + (debug_button("kaljkahd")) + (submenu_button("luyortp"), menu_tpl_2(menu_items!( + (debug_button("ajrs")) + (debug_button("bsdfho")) + (debug_button("clkjhbf")) + (debug_button("dekjdaud")) + (debug_button("ecsh")) + (debug_button("fweiu")) + (debug_button("giwe")) + (debug_button("heruyv")) + (debug_button("isabe")) + (debug_button("jcsu")) + (debug_button("kaljkahd")) + (debug_button("luyortp")) + (debug_button("mmdyrc")) + (debug_button("nquc")) ))) - .width(slider_width), - vertical_slider(0..=255, g, move |x| Message::ColorChange(Color::from_rgb8( - r, x, b - ))) - .width(slider_width), - vertical_slider(0..=255, b, move |x| Message::ColorChange(Color::from_rgb8( - r, g, x - ))) - .width(slider_width), - ] - .spacing(spacing) - .height(100.0) - )(separator())( - debug_button("AABB").height(40) - )(debug_button("CCDD").height(140))( - debug_button("EEFF").height(30) - )(debug_button("GGHH").height(100))( - debug_button("IIJJ").height(60) - )(debug_button("KKLL").height(120))( - debug_button("MMNN").height(50) + (debug_button("mmdyrc")) + (debug_button("nquc")) + ))) + (debug_button("kaljkahd")) + (debug_button("luyortp")) + (debug_button("mmdyrc")) + (debug_button("nquc")) + (debug_button("ajrs")) + (debug_button("bsdfho")) + (debug_button("clkjhbf")) + (debug_button("dekjdaud")) + (debug_button("ecsh")) + (debug_button("fweiu")) + (debug_button("giwe")) + (debug_button("heruyv")) + (debug_button("isabe")) + (debug_button("jcsu")) + (debug_button("kaljkahd")) + (debug_button("luyortp")) + (debug_button("mmdyrc")) + (debug_button("nquc")) + (debug_button("ajrs")) + (debug_button("bsdfho")) + (debug_button("clkjhbf")) + (submenu_button("dekjdaud"), menu_tpl_2(menu_items!( + (debug_button("ajrs")) + (debug_button("bsdfho")) + (debug_button("clkjhbf")) + (debug_button("dekjdaud")) + (debug_button("ecsh")) + (debug_button("fweiu")) + (debug_button("giwe")) + (debug_button("heruyv")) + (debug_button("isabe")) + (debug_button("jcsu")) + (debug_button("kaljkahd")) + (debug_button("luyortp")) + (debug_button("mmdyrc")) + (debug_button("nquc")) + (debug_button("ajrs")) + (debug_button("bsdfho")) + (debug_button("clkjhbf")) + (debug_button("dekjdaud")) + (debug_button("ecsh")) + (debug_button("fweiu")) + (debug_button("giwe")) + (debug_button("heruyv")) + (debug_button("isabe")) + (debug_button("jcsu")) + (debug_button("kaljkahd")) + (debug_button("luyortp")) + (debug_button("mmdyrc")) + (debug_button("nquc")) + ))) + (debug_button("ecsh")) + (debug_button("fweiu")) + (debug_button("giwe")) + (debug_button("heruyv")) + (debug_button("isabe")) + (debug_button("jcsu")) + (debug_button("kaljkahd")) + (debug_button("luyortp")) + (debug_button("mmdyrc")) + (debug_button("nquc")) + (debug_button("ajrs")) + (debug_button("bsdfho")) + (debug_button("clkjhbf")) + (debug_button("dekjdaud")) + (debug_button("ecsh")) + (debug_button("fweiu")) + (debug_button("giwe")) + (debug_button("heruyv")) + (debug_button("isabe")) + (debug_button("jcsu")) + (debug_button("kaljkahd")) + (debug_button("luyortp")) + (debug_button("mmdyrc")) + (debug_button("nquc")) ))) - .width(slider_width * slider_count + (slider_count - 1) * spacing + pad) - })); + (debug_button_s("Dynamic height"), { + let slider_count = 3; + let slider_width = 30; + let spacing = 5; + let pad = 20; + let [r, g, b, _] = self.theme.palette().primary.into_rgba8(); + + menu_tpl_1(menu_items!( + (labeled_separator("Primary")) + ( + row![ + vertical_slider(0..=255, r, move |x| Message::ColorChange(Color::from_rgb8( + x, g, b + ))) + .width(slider_width) + , + vertical_slider(0..=255, g, move |x| Message::ColorChange(Color::from_rgb8( + r, x, b + ))) + .width(slider_width) + , + vertical_slider(0..=255, b, move |x| Message::ColorChange(Color::from_rgb8( + r, g, x + ))) + .width(slider_width) + , + ].spacing(spacing) + .height(100.0) + ) + (separator()) + (debug_button("AABB").height(40)) + (debug_button("CCDD").height(140)) + (debug_button("EEFF").height(30)) + (debug_button("GGHH").height(100)) + (debug_button("IIJJ").height(60)) + (debug_button("KKLL").height(120)) + (debug_button("MMNN").height(50)) + )).width(slider_width * slider_count + (slider_count - 1) * spacing + pad) + }) + ); let r = row![ horizontal_space().width(295), @@ -529,10 +545,13 @@ fn color_button<'a>( fn separator<'a>() -> quad::Quad { quad::Quad { - color: [0.5; 3].into(), - border_radius: [4.0; 4], - inner_bounds: InnerBounds::Ratio(0.98, 0.1), - height: Length::Fixed(30.0), + quad_color: Color::from([0.5; 3]).into(), + quad_border: Border { + radius: [4.0; 4].into(), + ..Default::default() + }, + inner_bounds: InnerBounds::Ratio(0.98, 0.2), + height: Length::Fixed(20.0), ..Default::default() } } @@ -540,29 +559,24 @@ fn separator<'a>() -> quad::Quad { fn dot_separator<'a>(theme: &iced::Theme) -> Element<'a, Message, iced::Theme, iced::Renderer> { row((0..20).map(|_| { quad::Quad { - color: theme.extended_palette().background.base.text, - border_radius: [4.0; 4], + quad_color: theme.extended_palette().background.base.text.into(), inner_bounds: InnerBounds::Square(4.0), - ..Default::default() + ..separator() } .into() })) - .height(30.0) + .height(20.0) .into() } fn labeled_separator(label: &'_ str) -> Element<'_, Message, iced::Theme, iced::Renderer> { let q_1 = quad::Quad { - color: [0.5; 3].into(), - border_radius: [4.0; 4], - inner_bounds: InnerBounds::Ratio(0.98, 0.1), - ..Default::default() + height: Length::Fill, + ..separator() }; let q_2 = quad::Quad { - color: [0.5; 3].into(), - border_radius: [4.0; 4], - inner_bounds: InnerBounds::Ratio(0.98, 0.1), - ..Default::default() + height: Length::Fill, + ..separator() }; row![ @@ -572,7 +586,7 @@ fn labeled_separator(label: &'_ str) -> Element<'_, Message, iced::Theme, iced:: .vertical_alignment(alignment::Vertical::Center), q_2, ] - .height(30.0) + .height(20.0) .into() } @@ -580,10 +594,13 @@ fn circle(color: Color) -> quad::Quad { let radius = 10.0; quad::Quad { - color, + quad_color: color.into(), inner_bounds: InnerBounds::Square(radius * 2.0), - border_radius: [radius; 4], - height: 20.0.into(), + quad_border: Border { + radius: [radius; 4].into(), + ..Default::default() + }, + height: Length::Fixed(20.0), ..Default::default() } } diff --git a/src/native/menu.rs b/src/native/menu.rs index 43b9996b..c0013a00 100644 --- a/src/native/menu.rs +++ b/src/native/menu.rs @@ -150,6 +150,6 @@ mod menu_bar_overlay; mod menu_tree; pub use crate::style::menu_bar::{Appearance, StyleSheet}; +pub use common::DrawPath; pub use menu_bar::MenuBar; pub use menu_tree::{Item, Menu}; -pub use common::DrawPath; diff --git a/src/native/menu/common.rs b/src/native/menu/common.rs index f25296f5..8a6c5767 100644 --- a/src/native/menu/common.rs +++ b/src/native/menu/common.rs @@ -15,27 +15,27 @@ pub struct CloseCondition { */ /// -/// ## FakeHovering: +/// ## FakeHovering: /// -/// Places cursors at the path items, i.e. fake hovering, -/// useful when you want to customize the styling of each item in the path, -/// or you simple want the look of the items when they are hovered over. -/// -/// The downside is when some widgets in the path don't response to hovering, -/// the path won't be fully drawn, and when you want uniform path styling +/// Places cursors at the path items, +/// useful when you want to customize the styling of each item in the path, +/// or you simple want the look of the items when they are hovered over. +/// +/// The downside is when some widgets in the path don't response to hovering, +/// the path won't be fully drawn, and when you want uniform path styling /// but some widgets response to hovering differently. -/// +/// /// ## Backdrop: /// -/// Draws a rectangle behind each path item, -/// requires path items to have transparent backgrounds, -/// useful when you want uniform path styling. -/// -/// The downside is, -/// depend on the style you're going for, -/// sometimes manually syncing the path styling to the path items is needed +/// Draws a rectangle behind each path item, +/// requires path items to have transparent backgrounds, +/// useful when you want uniform path styling. +/// +/// The downside is, +/// depend on the style you're going for, +/// oftentimes manually syncing the path's styling to the path items' is necessary /// -pub enum DrawPath{ +pub enum DrawPath { /// FakeHovering FakeHovering, /// Backdrop diff --git a/src/native/menu/menu_bar.rs b/src/native/menu/menu_bar.rs index c0873ba1..cc5ef37e 100644 --- a/src/native/menu/menu_bar.rs +++ b/src/native/menu/menu_bar.rs @@ -253,15 +253,12 @@ where let state = tree.state.downcast_ref::(); if state.open { - if let Some(active) = state.active_root{ - let Some(active_bounds) = layout.children() - .nth(active) - .map(|l| l.bounds()) - else{ + if let Some(active) = state.active_root { + let Some(active_bounds) = layout.children().nth(active).map(|l| l.bounds()) else { return; }; - match self.draw_path{ + match self.draw_path { DrawPath::Backdrop => { renderer.fill_quad( renderer::Quad { @@ -269,11 +266,11 @@ where border: styling.path_border, ..Default::default() }, - styling.path + styling.path, ); } DrawPath::FakeHovering => { - if !cursor.is_over(active_bounds){ + if !cursor.is_over(active_bounds) { cursor = mouse::Cursor::Available(active_bounds.center()) } } @@ -313,6 +310,7 @@ where check_bounds_width: self.check_bounds_width, draw_path: &self.draw_path, style: &self.style, + // is_over: false, } .overlay_element(), ) diff --git a/src/native/menu/menu_bar_overlay.rs b/src/native/menu/menu_bar_overlay.rs index db36b5c3..8dbf7a76 100644 --- a/src/native/menu/menu_bar_overlay.rs +++ b/src/native/menu/menu_bar_overlay.rs @@ -42,6 +42,7 @@ where pub(super) check_bounds_width: f32, pub(super) draw_path: &'b DrawPath, pub(super) style: &'b Theme::Style, + // pub(super) is_over: bool, } impl<'a, 'b, Message, Theme, Renderer> MenuBarOverlay<'a, 'b, Message, Theme, Renderer> where @@ -394,6 +395,76 @@ where } } + fn mouse_interaction( + &self, + layout: Layout<'_>, + cursor: mouse::Cursor, + viewport: &Rectangle, + renderer: &Renderer, + ) -> mouse::Interaction { + let bar = self.tree.state.downcast_ref::(); + let Some(active) = bar.active_root else { + return mouse::Interaction::default(); + }; + + // let viewport = layout.bounds(); + let mut lc = layout.children(); + let _bar_bounds = lc.next().unwrap().bounds(); + let _roots_layout = lc.next().unwrap(); + + // let parent_bounds = roots_layout.children().nth(active).unwrap().bounds(); + let menu_layouts_layout = lc.next().unwrap(); // Node{0, [menu_node...]} + let mut menu_layouts = menu_layouts_layout.children(); // [menu_node...] + + let active_root = &self.roots[active]; + let active_tree = &self.tree.children[active]; + + fn rec<'a, 'b, Message, Theme: StyleSheet, Renderer: renderer::Renderer>( + tree: &Tree, + item: &Item<'a, Message, Theme, Renderer>, + layout_iter: &mut impl Iterator>, + cursor: mouse::Cursor, + renderer: &Renderer, + viewport: &Rectangle, + ) -> mouse::Interaction { + let menu = item.menu.as_ref().expect("No menu defined in this item"); + let menu_tree = &tree.children[1]; + + let Some(menu_layout) = layout_iter.next() else { + return mouse::Interaction::default(); + }; // menu_node: Node{inf, [ slice_node, prescroll, offset_bounds, check_bounds ]} + + let menu_state = menu_tree.state.downcast_ref::(); + + let i = menu.mouse_interaction(menu_tree, menu_layout, cursor, viewport, renderer); + + if let Some(active) = menu_state.active { + let next_tree = &menu_tree.children[active]; + let next_item = &menu.items[active]; + rec( + next_tree, + next_item, + layout_iter, + cursor, + renderer, + viewport, + ) + .max(i) + } else { + i + } + } + + rec( + active_tree, + active_root, + &mut menu_layouts, + cursor, + renderer, + viewport, + ) + } + fn draw( &self, renderer: &mut Renderer, @@ -440,38 +511,22 @@ where let menu_state = menu_tree.state.downcast_ref::(); - let mut draw_menu = || { - menu.draw( - draw_path, - menu_tree, - renderer, - theme, - style, - theme_style, - menu_layout, - cursor, - viewport, - ); - }; + menu.draw( + draw_path, + menu_tree, + renderer, + theme, + style, + theme_style, + menu_layout, + cursor, + viewport, + ); if let Some(active) = menu_state.active { let next_tree = &menu_tree.children[active]; let next_item = &menu.items[active]; - // let mut mc = menu_layout.children(); - // let slice_layout = mc.next().unwrap(); // slice_node - // let active_bounds = { - // let Some(layout) = slice_layout - // .children() - // .nth(active - menu_state.slice.start_index) - // else { - // return; - // }; - // layout.bounds() - // }; - - draw_menu(); - renderer.with_layer(*viewport, |r| { rec( draw_path, @@ -486,8 +541,6 @@ where viewport, ); }); - } else { - draw_menu(); } } @@ -505,7 +558,25 @@ where ); } - fn is_over(&self, _layout: Layout<'_>, _renderer: &Renderer, _cursor_position: Point) -> bool { + fn is_over(&self, layout: Layout<'_>, _renderer: &Renderer, cursor_position: Point) -> bool { + let mut lc = layout.children(); + let _bar_bounds = lc.next().unwrap().bounds(); + let _roots_layout = lc.next().unwrap(); + let Some(menu_layouts) = lc.next().map(|l| l.children()) else { + return false; + }; // [menu_node...] + + for menu_layout in menu_layouts { + // menu_node: Node{inf, [ slice_node, prescroll, offset_bounds, check_bounds ]} + let mut mc = menu_layout.children(); + let _slice_layout = mc.next().unwrap(); + let prescroll = mc.next().unwrap().bounds(); + + if prescroll.contains(cursor_position) { + return true; + } + } + false } } diff --git a/src/native/menu/menu_tree.rs b/src/native/menu/menu_tree.rs index aaebda83..6ca6aca5 100644 --- a/src/native/menu/menu_tree.rs +++ b/src/native/menu/menu_tree.rs @@ -301,6 +301,7 @@ where child_direction, ) } + /// tree: Tree{ menu_state, \[item_tree...] } /// /// layout: Node{inf, \[ slice_node, prescroll, offset_bounds, check_bounds ]} @@ -360,6 +361,34 @@ where .merge(status) } + /// tree: Tree{ menu_state, \[item_tree...] } + /// + /// layout: Node{inf, \[ slice_node, prescroll, offset_bounds, check_bounds ]} + pub(super) fn mouse_interaction( + &self, + tree: &Tree, + layout: Layout<'_>, + cursor: mouse::Cursor, + viewport: &Rectangle, + renderer: &Renderer, + ) -> mouse::Interaction { + let mut lc = layout.children(); + let slice_layout = lc.next().unwrap(); + + let menu_state = tree.state.downcast_ref::(); + let slice = &menu_state.slice; + + self.items[slice.start_index..=slice.end_index] + .iter() + .zip(tree.children[slice.start_index..=slice.end_index].iter()) // [item_tree...] + .zip(slice_layout.children()) // [item_layout...] + .map(|((item, tree), layout)| { + item.mouse_interaction(tree, layout, cursor, viewport, renderer) + }) + .max() + .unwrap_or_default() + } + /// tree: Tree{menu_state, \[item_tree...]} /// /// layout: Node{inf, \[ items_node, slice_node, prescroll, offset_bounds, check_bounds ]} @@ -400,7 +429,8 @@ where // draw path if let Some(active) = menu_state.active { - let Some(active_bounds) = slice_layout.children() + let Some(active_bounds) = slice_layout + .children() .nth(active - menu_state.slice.start_index) .map(|l| l.bounds()) else { @@ -425,8 +455,7 @@ where } } } - - + // draw start let Some(start) = self.items.get(slice.start_index) else { return; @@ -455,17 +484,11 @@ where }); // draw the rest - let Some(items) = self - .items - .get(slice.start_index + 1..=slice.end_index) - else { + let Some(items) = self.items.get(slice.start_index + 1..=slice.end_index) else { return; }; - let Some(trees) = tree - .children - .get(slice.start_index + 1..=slice.end_index) - else { + let Some(trees) = tree.children.get(slice.start_index + 1..=slice.end_index) else { return; }; @@ -700,6 +723,25 @@ where ) } + /// tree: Tree{stateless, \[widget_tree, menu_tree]} + /// + pub(super) fn mouse_interaction( + &self, + tree: &Tree, + layout: Layout<'_>, + cursor: mouse::Cursor, + viewport: &Rectangle, + renderer: &Renderer, + ) -> mouse::Interaction { + self.item.as_widget().mouse_interaction( + &tree.children[0], + layout, + cursor, + viewport, + renderer, + ) + } + /// tree: Tree{stateless, \[widget_tree, menu_tree]} /// pub(super) fn draw( diff --git a/src/native/quad.rs b/src/native/quad.rs index a3ffdcd7..1c97a479 100644 --- a/src/native/quad.rs +++ b/src/native/quad.rs @@ -11,7 +11,7 @@ use iced::{ Layout, Widget, }, mouse::Cursor, - Border, Color, Element, Length, Rectangle, Shadow, Size, + Background, Border, Color, Element, Length, Rectangle, Shadow, Size, }; /// A dummy widget that draws a quad @@ -21,30 +21,46 @@ pub struct Quad { pub width: Length, /// Height of the quad pub height: Length, - /// Color of the quad - pub color: Color, - /// Background color of the quad - pub background: Option, + /// Methods for creating inner bounds pub inner_bounds: InnerBounds, - /// Border radius of the Quad - pub border_radius: [f32; 4], - /// Border width of the quad - pub border_width: f32, - /// Border color of the quad - pub border_color: Color, + + /// Color of the quad + pub quad_color: Background, + /// Border of the quad + pub quad_border: Border, + /// Shadow of the quad + pub quad_shadow: Shadow, + + /// Background color of the quad + pub bg_color: Option, + /// Border of the background + pub bg_border: Border, + /// Shadow of the background + pub bg_shadow: Shadow, } impl Default for Quad { fn default() -> Self { Self { width: Length::Fill, height: Length::Fill, - color: Color::from([0.5; 3]), - background: None, inner_bounds: InnerBounds::Ratio(0.5, 0.5), - border_radius: [0.0, 0.0, 0.0, 0.0], - border_width: 0.0, - border_color: Color::TRANSPARENT, + + quad_color: Color::from([0.5; 3]).into(), + quad_border: Border { + color: Color::TRANSPARENT, + width: 0.0, + radius: [0.0, 0.0, 0.0, 0.0].into(), + }, + quad_shadow: Shadow::default(), + + bg_color: None, + bg_border: Border { + color: Color::TRANSPARENT, + width: 0.0, + radius: [0.0, 0.0, 0.0, 0.0].into(), + }, + bg_shadow: Shadow::default(), } } } @@ -72,16 +88,12 @@ where _cursor: Cursor, _viewport: &Rectangle, ) { - if let Some(b) = self.background { + if let Some(b) = self.bg_color { renderer.fill_quad( renderer::Quad { bounds: layout.bounds(), - border: Border { - radius: self.border_radius.into(), - width: self.border_width, - color: self.border_color, - }, - shadow: Shadow::default(), + border: self.bg_border, + shadow: self.bg_shadow, }, b, ); @@ -89,14 +101,10 @@ where renderer.fill_quad( renderer::Quad { bounds: self.inner_bounds.get_bounds(layout.bounds()), - border: Border { - radius: self.border_radius.into(), - width: self.border_width, - color: self.border_color, - }, - shadow: Shadow::default(), + border: self.quad_border, + shadow: self.quad_shadow, }, - self.color, + self.quad_color, ); } } diff --git a/src/style/menu_bar.rs b/src/style/menu_bar.rs index b34f0d59..1f355f70 100644 --- a/src/style/menu_bar.rs +++ b/src/style/menu_bar.rs @@ -49,11 +49,11 @@ impl std::default::Default for Appearance { blur_radius: 10.0, }, menu_background_expand: [5; 4].into(), - path: Color::from([0.3;3]).into(), - path_border: Border{ + path: Color::from([0.3; 3]).into(), + path_border: Border { radius: [6.0; 4].into(), ..Default::default() - } + }, } } }