diff --git a/crates/egui/src/menu.rs b/crates/egui/src/menu.rs index 893a1bd540b..3801f89b178 100644 --- a/crates/egui/src/menu.rs +++ b/crates/egui/src/menu.rs @@ -105,17 +105,35 @@ pub fn menu_button( stationary_menu_impl(ui, title, Box::new(add_contents)) } +/// Construct a top level menu with a custom button in a menu bar. +/// +/// Responds to primary clicks. +/// +/// Returns `None` if the menu is not open. +pub fn menu_custom_button( + ui: &mut Ui, + button: Button<'_>, + add_contents: impl FnOnce(&mut Ui) -> R, +) -> InnerResponse> { + stationary_menu_button_impl(ui, button, Box::new(add_contents)) +} + /// Construct a top level menu with an image in a menu bar. This would be e.g. "File", "Edit" etc. /// /// Responds to primary clicks. /// /// Returns `None` if the menu is not open. +#[deprecated = "Use `menu_custom_button` instead"] pub fn menu_image_button( ui: &mut Ui, image_button: ImageButton<'_>, add_contents: impl FnOnce(&mut Ui) -> R, ) -> InnerResponse> { - stationary_menu_image_impl(ui, image_button, Box::new(add_contents)) + stationary_menu_button_impl( + ui, + Button::image(image_button.image), + Box::new(add_contents), + ) } /// Construct a nested sub menu in another menu. @@ -226,15 +244,15 @@ fn stationary_menu_impl<'c, R>( /// Build a top level menu with an image button. /// /// Responds to primary clicks. -fn stationary_menu_image_impl<'c, R>( +fn stationary_menu_button_impl<'c, R>( ui: &mut Ui, - image_button: ImageButton<'_>, + button: Button<'_>, add_contents: Box R + 'c>, ) -> InnerResponse> { let bar_id = ui.id(); let mut bar_state = BarState::load(ui.ctx(), bar_id); - let button_response = ui.add(image_button); + let button_response = ui.add(button); let inner = bar_state.bar_menu(&button_response, add_contents); bar_state.store(ui.ctx(), bar_id); diff --git a/crates/egui/src/ui.rs b/crates/egui/src/ui.rs index 7317d94db89..74eecc846e4 100644 --- a/crates/egui/src/ui.rs +++ b/crates/egui/src/ui.rs @@ -2543,16 +2543,19 @@ impl Ui { /// If called from within a menu this will instead create a button for a sub-menu. /// /// ```ignore + /// # egui::__run_test_ui(|ui| { /// let img = egui::include_image!("../assets/ferris.png"); /// - /// ui.menu_image_button(img, |ui| { + /// ui.menu_image_button(title, img, |ui| { /// ui.menu_button("My sub-menu", |ui| { /// if ui.button("Close the menu").clicked() { /// ui.close_menu(); /// } /// }); /// }); + /// # }); /// ``` + /// /// /// See also: [`Self::close_menu`] and [`Response::context_menu`]. #[inline] @@ -2564,7 +2567,41 @@ impl Ui { if let Some(menu_state) = self.menu_state.clone() { menu::submenu_button(self, menu_state, String::new(), add_contents) } else { - menu::menu_image_button(self, ImageButton::new(image), add_contents) + menu::menu_custom_button(self, Button::image(image), add_contents) + } + } + + /// Create a menu button with an image and a text that when clicked will show the given menu. + /// + /// If called from within a menu this will instead create a button for a sub-menu. + /// + /// ``` + /// # egui::__run_test_ui(|ui| { + /// let img = egui::include_image!("../assets/ferris.png"); + /// let title = "My Menu"; + /// + /// ui.menu_image_text_button(img, title, |ui| { + /// ui.menu_button("My sub-menu", |ui| { + /// if ui.button("Close the menu").clicked() { + /// ui.close_menu(); + /// } + /// }); + /// }); + /// # }); + /// ``` + /// + /// See also: [`Self::close_menu`] and [`Response::context_menu`]. + #[inline] + pub fn menu_image_text_button<'a, R>( + &mut self, + image: impl Into>, + title: impl Into, + add_contents: impl FnOnce(&mut Ui) -> R, + ) -> InnerResponse> { + if let Some(menu_state) = self.menu_state.clone() { + menu::submenu_button(self, menu_state, title, add_contents) + } else { + menu::menu_custom_button(self, Button::image_and_text(image, title), add_contents) } } } diff --git a/crates/egui/src/widgets/image_button.rs b/crates/egui/src/widgets/image_button.rs index 8b206757efa..79460b456be 100644 --- a/crates/egui/src/widgets/image_button.rs +++ b/crates/egui/src/widgets/image_button.rs @@ -4,7 +4,7 @@ use crate::*; #[must_use = "You should put this widget in an ui with `ui.add(widget);`"] #[derive(Clone, Debug)] pub struct ImageButton<'a> { - image: Image<'a>, + pub(crate) image: Image<'a>, sense: Sense, frame: bool, selected: bool,