From dd632e81b8e4074b4d5f2066e60a3ec8b8ea16b2 Mon Sep 17 00:00:00 2001 From: Latidoremi Date: Fri, 23 Feb 2024 21:46:27 +0800 Subject: [PATCH] improve closing logic --- src/native/menu/common.rs | 8 +++ src/native/menu/menu_bar.rs | 2 +- src/native/menu/menu_bar_overlay.rs | 86 +++++++++++------------------ src/native/menu/menu_tree.rs | 20 ++++++- 4 files changed, 60 insertions(+), 56 deletions(-) diff --git a/src/native/menu/common.rs b/src/native/menu/common.rs index f7441c8c..88a65f4f 100644 --- a/src/native/menu/common.rs +++ b/src/native/menu/common.rs @@ -67,6 +67,14 @@ pub(super) enum Axis { pub(super) type Index = Option; +/// Should be returned from the recursive event processing function, +/// tells the caller which type of event has been processed +pub(super) enum RecEvent { + Event, + Close, + None, +} + pub fn pad_rectangle(rect: Rectangle, padding: Padding) -> Rectangle { Rectangle { x: rect.x - padding.left, diff --git a/src/native/menu/menu_bar.rs b/src/native/menu/menu_bar.rs index a83c6a86..d0270025 100644 --- a/src/native/menu/menu_bar.rs +++ b/src/native/menu/menu_bar.rs @@ -89,7 +89,7 @@ where self.check_bounds_width = check_bounds_width; self } - + /// Sets the draw path option of the [`MenuBar`] pub fn draw_path(mut self, draw_path: DrawPath) -> Self { self.draw_path = draw_path; diff --git a/src/native/menu/menu_bar_overlay.rs b/src/native/menu/menu_bar_overlay.rs index 1613a625..5bad3e7a 100644 --- a/src/native/menu/menu_bar_overlay.rs +++ b/src/native/menu/menu_bar_overlay.rs @@ -19,14 +19,6 @@ use iced::{ use super::{common::*, menu_bar::MenuBarState, menu_tree::*}; use crate::style::menu_bar::*; -/// Should be returned from the recursive event processing function, -/// tells the caller which type of event has been processed -enum RecEvent { - Event, - Close, - None, -} - pub(super) struct MenuBarOverlay<'a, 'b, Message, Theme, Renderer> where Theme: StyleSheet, @@ -247,7 +239,7 @@ where let menu_state = menu_tree.state.downcast_mut::(); - if let Some(active) = menu_state.active { + let rec_event = if let Some(active) = menu_state.active { let next_tree = &mut menu_tree.children[active]; let next_item = &mut menu.items[active]; let next_parent_bounds = { @@ -255,13 +247,14 @@ where .children() .nth(active - menu_state.slice.start_index) else { + prev_bounds_list.pop(); return RecEvent::Event; }; layout.bounds() }; - let re = rec( + rec( next_tree, next_item, event, @@ -274,55 +267,40 @@ where viewport, prev_bounds_list, &mut menu_state.active, - ); - - prev_bounds_list.pop(); - - match re { - RecEvent::Event => RecEvent::Event, - RecEvent::Close => { - if cursor.is_over(prescroll) { - menu.on_event(menu_tree, event, menu_layout, cursor, renderer, clipboard, shell, viewport); - menu.open_event(menu_tree, menu_layout, cursor); - RecEvent::Event - } else if cursor.is_over(offset_bounds) { - RecEvent::Event - } else { - menu.close_event(menu_tree, menu_layout, cursor, parent_bounds, prev_bounds_list, prev); - if prev.is_some() { - RecEvent::None - } else { - RecEvent::Close - } - } - } - RecEvent::None => { - if cursor.is_over(prescroll) { - menu.on_event(menu_tree, event, menu_layout, cursor, renderer, clipboard, shell, viewport); - menu.open_event(menu_tree, menu_layout, cursor); - RecEvent::Event - } else if cursor.is_over(offset_bounds) { - RecEvent::Event - } else { + ) + } else { + RecEvent::Close + }; + + prev_bounds_list.pop(); + + match rec_event { + RecEvent::Event => RecEvent::Event, + RecEvent::Close => { + if menu_state.pressed || cursor.is_over(prescroll){ + menu.on_event(menu_tree, event, menu_layout, cursor, renderer, clipboard, shell, viewport); + menu.open_event(menu_tree, menu_layout, cursor); + RecEvent::Event + } else if cursor.is_over(offset_bounds) { + RecEvent::Event + } else { + menu.close_event(menu_tree, menu_layout, cursor, parent_bounds, prev_bounds_list, prev); + if prev.is_some() { RecEvent::None + } else { + RecEvent::Close } } } - } else { - prev_bounds_list.pop(); - - if cursor.is_over(prescroll) { - menu.on_event(menu_tree, event, menu_layout, cursor, renderer, clipboard, shell, viewport); - menu.open_event(menu_tree, menu_layout, cursor); - RecEvent::Event - } else if cursor.is_over(offset_bounds) { - RecEvent::Event - } else { - menu.close_event(menu_tree, menu_layout, cursor, parent_bounds, prev_bounds_list, prev); - if prev.is_some() { - RecEvent::None + RecEvent::None => { + if menu_state.pressed || cursor.is_over(prescroll){ + menu.on_event(menu_tree, event, menu_layout, cursor, renderer, clipboard, shell, viewport); + menu.open_event(menu_tree, menu_layout, cursor); + RecEvent::Event + } else if cursor.is_over(offset_bounds) { + RecEvent::Event } else { - RecEvent::Close + RecEvent::None } } } diff --git a/src/native/menu/menu_tree.rs b/src/native/menu/menu_tree.rs index 6ca6aca5..247412e9 100644 --- a/src/native/menu/menu_tree.rs +++ b/src/native/menu/menu_tree.rs @@ -61,6 +61,7 @@ pub(super) struct MenuState { scroll_offset: f32, pub(super) active: Index, pub(super) slice: MenuSlice, + pub(super) pressed: bool, } impl Default for MenuState { fn default() -> Self { @@ -73,6 +74,7 @@ impl Default for MenuState { lower_bound_rel: 0.0, upper_bound_rel: f32::MAX, }, + pressed: false, } } } @@ -346,6 +348,16 @@ where .fold(Ignored, event::Status::merge); match event { + Event::Mouse(mouse::Event::ButtonPressed(mouse::Button::Left)) => { + if cursor.is_over(prescroll) { + menu_state.pressed = true; + } + Ignored + } + Event::Mouse(mouse::Event::ButtonReleased(mouse::Button::Left)) => { + menu_state.pressed = false; + Ignored + } Event::Mouse(mouse::Event::WheelScrolled { delta }) => { if cursor.is_over(prescroll) { process_scroll_event(menu_state, prescroll, *delta, viewport.size()); @@ -546,6 +558,12 @@ where let offset_bounds = lc.next().unwrap().bounds(); let check_bounds = lc.next().unwrap().bounds(); + let menu_state = tree.state.downcast_mut::(); + + if menu_state.pressed { + return; + } + let open = { if cursor.is_over(prescroll) || cursor.is_over(parent_bounds) @@ -561,9 +579,9 @@ where if !open { *prev = None; - let menu_state = tree.state.downcast_mut::(); menu_state.scroll_offset = 0.0; menu_state.active = None; + menu_state.pressed = false; } } }