From 8f5986125d7772eeb67dcda55b43041d234e44b6 Mon Sep 17 00:00:00 2001 From: sor-ca <95582611+sor-ca@users.noreply.github.com> Date: Fri, 31 May 2024 10:02:02 +0300 Subject: [PATCH] Make `egu::menu` types public (#4544) Sometimes we need to fix the current state of the application in the moment when you open the context menu, to save it, and to use it during creation of context menu and response handling. Making some structs, related with menu creating, allow us to create functions for this cases. For example, ```rust pub fn context_menu_custom<'a, T>( response: &Response, //variable for fixing state in the moment when you open context menu state: &mut T, //function which allow to get some king of state. //In this case state depends on cursor position, in other cases it may depend on system time or something else get_state: impl FnOnce(Pos2) -> T, //set contents of menu depending on state set_contents: impl 'a + FnOnce(&T) -> Box, ) -> Option> { let menu_id = Id::new("__egui::context_menu"); let mut bar_state = BarState::load(&response.ctx, menu_id); let root = &mut bar_state; let menu_response = MenuRoot::context_interaction(response, root); if let egui::menu::MenuResponse::Create(p, _) = &menu_response { *state = get_state(*p); }; let add_contents = set_contents(&state); MenuRoot::handle_menu_response(root, menu_response); let inner_response = bar_state.show(response, add_contents); bar_state.store(&response.ctx, menu_id); inner_response } ``` The example of using such function you may see in [`my repository`](https://github.com/sor-ca/context_menu) It is very simple example, and is this case, the problem may be solved without fn context_menu_custom, but in more complex situations, it may be very useful Related issue: https://github.com/emilk/egui/issues/4162 --------- Co-authored-by: Emil Ernerfeldt --- crates/egui/src/menu.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/crates/egui/src/menu.rs b/crates/egui/src/menu.rs index d23d5d20f31..7d76763f53a 100644 --- a/crates/egui/src/menu.rs +++ b/crates/egui/src/menu.rs @@ -25,16 +25,16 @@ use std::sync::Arc; /// What is saved between frames. #[derive(Clone, Default)] -pub(crate) struct BarState { +pub struct BarState { open_menu: MenuRootManager, } impl BarState { - fn load(ctx: &Context, bar_id: Id) -> Self { + pub fn load(ctx: &Context, bar_id: Id) -> Self { ctx.data_mut(|d| d.get_temp::(bar_id).unwrap_or_default()) } - fn store(self, ctx: &Context, bar_id: Id) { + pub fn store(self, ctx: &Context, bar_id: Id) { ctx.data_mut(|d| d.insert_temp(bar_id, self)); } @@ -242,7 +242,7 @@ pub(crate) fn context_menu_opened(response: &Response) -> bool { /// Stores the state for the context menu. #[derive(Clone, Default)] -pub(crate) struct MenuRootManager { +pub struct MenuRootManager { inner: Option, } @@ -287,7 +287,7 @@ impl std::ops::DerefMut for MenuRootManager { /// Menu root associated with an Id from a Response #[derive(Clone)] -pub(crate) struct MenuRoot { +pub struct MenuRoot { pub menu_state: Arc>, pub id: Id, } @@ -372,7 +372,7 @@ impl MenuRoot { } /// Interaction with a context menu (secondary click). - fn context_interaction(response: &Response, root: &mut Option) -> MenuResponse { + pub fn context_interaction(response: &Response, root: &mut Option) -> MenuResponse { let response = response.interact(Sense::click()); let hovered = response.hovered(); let secondary_clicked = response.secondary_clicked(); @@ -398,7 +398,7 @@ impl MenuRoot { }) } - fn handle_menu_response(root: &mut MenuRootManager, menu_response: MenuResponse) { + pub fn handle_menu_response(root: &mut MenuRootManager, menu_response: MenuResponse) { match menu_response { MenuResponse::Create(pos, id) => { root.inner = Some(Self::new(pos, id)); @@ -421,8 +421,8 @@ impl MenuRoot { } } -#[derive(Copy, Clone, PartialEq)] -pub(crate) enum MenuResponse { +#[derive(Copy, Clone, PartialEq, Eq)] +pub enum MenuResponse { Close, Stay, Create(Pos2, Id), @@ -562,7 +562,10 @@ impl SubMenu { } } -pub(crate) struct MenuState { +/// Components of menu state, public for advanced usage. +/// +/// Usually you don't need to use it directly. +pub struct MenuState { /// The opened sub-menu and its [`Id`] sub_menu: Option<(Id, Arc>)>,