@@ -269,7 +269,7 @@ impl Control for Menu {
269269 }
270270 } else if let Some ( WidgetMessage :: KeyDown ( key_code) ) = message. data ( ) {
271271 if !message. handled ( ) {
272- if keyboard_navigation ( ui, * key_code, self , self . handle ) {
272+ if keyboard_navigation ( ui, * key_code, self , self . handle . to_variant ( ) ) {
273273 message. set_handled ( true ) ;
274274 } else if * key_code == KeyCode :: Escape {
275275 ui. send ( self . handle , MenuMessage :: Deactivate ) ;
@@ -463,6 +463,27 @@ impl MenuItem {
463463 WidgetMessage :: Visibility ( !self . items_container . is_empty ( ) ) ,
464464 ) ;
465465 }
466+
467+ fn close_menu_chain ( & self , ui : & UserInterface ) {
468+ let mut menu_item_ref_container = Some ( self ) ;
469+ while let Some ( menu_item_ref) = menu_item_ref_container {
470+ let popup_handle =
471+ menu_item_ref. find_by_criteria_up ( ui, |n| n. has_component :: < ContextMenu > ( ) ) ;
472+
473+ ui. send (
474+ menu_item_ref. handle ,
475+ MenuItemMessage :: Close { deselect : true } ,
476+ ) ;
477+
478+ if let Ok ( panel) = ui. try_get_of_type :: < ContextMenu > ( popup_handle) {
479+ // Continue search from parent menu item of popup.
480+ menu_item_ref_container = ui. try_get ( panel. parent_menu_item ) . ok ( ) ;
481+ } else {
482+ // Prevent infinite loops.
483+ break ;
484+ }
485+ }
486+ }
466487}
467488
468489// MenuItem uses popup to show its content, popup can be top-most only if it is
@@ -475,7 +496,7 @@ fn find_menu(from: Handle<UiNode>, ui: &UserInterface) -> Handle<UiNode> {
475496 while handle. is_some ( ) {
476497 if let Some ( ( _, panel) ) = ui. find_component_up :: < ContextMenu > ( handle) {
477498 // Continue search from parent menu item of popup.
478- handle = panel. parent_menu_item ;
499+ handle = panel. parent_menu_item . to_base ( ) ;
479500 } else {
480501 // Maybe we have Menu as parent for MenuItem.
481502 return ui. find_handle_up ( handle, & mut |n| n. cast :: < Menu > ( ) . is_some ( ) ) ;
@@ -500,25 +521,6 @@ fn is_any_menu_item_contains_point(ui: &UserInterface, pt: Vector2<f32>) -> bool
500521 false
501522}
502523
503- fn close_menu_chain ( from : Handle < UiNode > , ui : & UserInterface ) {
504- let mut handle = from;
505- while handle. is_some ( ) {
506- let popup_handle = ui. find_handle_up ( handle, & mut |n| n. has_component :: < ContextMenu > ( ) ) ;
507-
508- if let Ok ( panel) = ui. try_get_of_type :: < ContextMenu > ( popup_handle) {
509- if * panel. popup . is_open {
510- ui. send ( popup_handle, PopupMessage :: Close ) ;
511- }
512-
513- // Continue search from parent menu item of popup.
514- handle = panel. parent_menu_item ;
515- } else {
516- // Prevent infinite loops.
517- break ;
518- }
519- }
520- }
521-
522524uuid_provider ! ( MenuItem = "72e002c6-6060-4583-b5b7-0c5500244fef" ) ;
523525
524526impl Control for MenuItem {
@@ -564,7 +566,7 @@ impl Control for MenuItem {
564566 ui. send ( menu, MenuMessage :: Deactivate ) ;
565567 } else {
566568 // Or close the menu chain if menu item is in "orphaned" state.
567- close_menu_chain ( self . parent ( ) , ui) ;
569+ self . close_menu_chain ( ui) ;
568570 }
569571 }
570572 message. set_handled ( true ) ;
@@ -722,7 +724,7 @@ impl Control for MenuItem {
722724 if let Some ( panel) = node. component_ref :: < ContextMenu > ( ) {
723725 // Once we found popup in chain, we must extract handle
724726 // of parent menu item to continue search.
725- handle = panel. parent_menu_item ;
727+ handle = panel. parent_menu_item . to_base ( ) ;
726728 } else {
727729 handle = node. parent ( ) ;
728730 }
@@ -756,12 +758,8 @@ impl Control for MenuItem {
756758 if !is_any_menu_item_contains_point ( ui, ui. cursor_position ( ) )
757759 && find_menu ( self . parent ( ) , ui) . is_none ( )
758760 {
759- if * panel. popup . is_open {
760- ui. send ( * self . items_panel , PopupMessage :: Close ) ;
761- }
762-
763761 // Close all other popups.
764- close_menu_chain ( self . parent ( ) , ui) ;
762+ self . close_menu_chain ( ui) ;
765763 }
766764 }
767765 }
@@ -1138,7 +1136,7 @@ pub struct ContextMenu {
11381136 #[ component( include) ]
11391137 pub popup : Popup ,
11401138 /// Parent menu item of the context menu. Allows you to build chained context menus.
1141- pub parent_menu_item : Handle < UiNode > ,
1139+ pub parent_menu_item : Handle < MenuItem > ,
11421140}
11431141
11441142impl ConstructorProvider < UiNode , UserInterface > for ContextMenu {
@@ -1179,13 +1177,8 @@ impl Control for ContextMenu {
11791177
11801178 if let Some ( WidgetMessage :: KeyDown ( key_code) ) = message. data ( ) {
11811179 if !message. handled ( ) {
1182- if let Ok ( parent_menu_item) = ui. try_get_node ( self . parent_menu_item ) {
1183- if keyboard_navigation (
1184- ui,
1185- * key_code,
1186- parent_menu_item. deref ( ) ,
1187- self . parent_menu_item ,
1188- ) {
1180+ if let Ok ( parent_menu_item) = ui. try_get ( self . parent_menu_item ) {
1181+ if keyboard_navigation ( ui, * key_code, parent_menu_item, self . parent_menu_item ) {
11891182 message. set_handled ( true ) ;
11901183 }
11911184 }
@@ -1197,7 +1190,7 @@ impl Control for ContextMenu {
11971190/// Creates [`ContextMenu`] widgets.
11981191pub struct ContextMenuBuilder {
11991192 popup_builder : PopupBuilder ,
1200- parent_menu_item : Handle < UiNode > ,
1193+ parent_menu_item : Handle < MenuItem > ,
12011194}
12021195
12031196impl ContextMenuBuilder {
@@ -1210,7 +1203,7 @@ impl ContextMenuBuilder {
12101203 }
12111204
12121205 /// Sets the desired parent menu item.
1213- pub fn with_parent_menu_item ( mut self , parent_menu_item : Handle < UiNode > ) -> Self {
1206+ pub fn with_parent_menu_item ( mut self , parent_menu_item : Handle < MenuItem > ) -> Self {
12141207 self . parent_menu_item = parent_menu_item;
12151208 self
12161209 }
@@ -1234,7 +1227,7 @@ fn keyboard_navigation(
12341227 ui : & UserInterface ,
12351228 key_code : KeyCode ,
12361229 parent_menu_item : & dyn Control ,
1237- parent_menu_item_handle : Handle < UiNode > ,
1230+ parent_menu_item_handle : Handle < MenuItem > ,
12381231) -> bool {
12391232 let Some ( items_container) = parent_menu_item
12401233 . query_component_ref ( TypeId :: of :: < ItemsContainer > ( ) )
0 commit comments