Give each menu `Area` an id distinct from the id of what was clicked (#4114)

* Closes https://github.com/emilk/egui/issues/4113

Previously the `Id` of the menu `Area` was using the same id as the
thing that was clicked (i.e. the button opening menu), which lead to id
clashes
This commit is contained in:
Emil Ernerfeldt 2024-02-29 14:18:06 +01:00 committed by GitHub
parent e8af6f38fc
commit 86d7f296ae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 21 additions and 21 deletions

View File

@ -39,13 +39,14 @@ impl BarState {
}
/// Show a menu at pointer if primary-clicked response.
///
/// Should be called from [`Context`] on a [`Response`]
pub fn bar_menu<R>(
&mut self,
response: &Response,
add_contents: impl FnOnce(&mut Ui) -> R,
) -> Option<InnerResponse<R>> {
MenuRoot::stationary_click_interaction(response, &mut self.open_menu, response.id);
MenuRoot::stationary_click_interaction(response, &mut self.open_menu);
self.open_menu.show(response, add_contents)
}
@ -134,7 +135,7 @@ pub(crate) fn submenu_button<R>(
/// wrapper for the contents of every menu.
pub(crate) fn menu_ui<'c, R>(
ctx: &Context,
menu_id: impl Into<Id>,
menu_id: Id,
menu_state_arc: &Arc<RwLock<MenuState>>,
add_contents: impl FnOnce(&mut Ui) -> R + 'c,
) -> InnerResponse<R> {
@ -144,7 +145,7 @@ pub(crate) fn menu_ui<'c, R>(
menu_state.rect.min
};
let area = Area::new(menu_id)
let area = Area::new(menu_id.with("__menu"))
.order(Order::Foreground)
.fixed_pos(pos)
.constrain_to(ctx.screen_rect())
@ -222,7 +223,7 @@ pub(crate) fn context_menu(
let menu_id = Id::new(CONTEXT_MENU_ID_STR);
let mut bar_state = BarState::load(&response.ctx, menu_id);
MenuRoot::context_click_interaction(response, &mut bar_state, response.id);
MenuRoot::context_click_interaction(response, &mut bar_state);
let inner_response = bar_state.show(response, add_contents);
bar_state.store(&response.ctx, menu_id);
@ -237,6 +238,7 @@ pub(crate) struct MenuRootManager {
impl MenuRootManager {
/// Show a menu at pointer if right-clicked response.
///
/// Should be called from [`Context`] on a [`Response`]
pub fn show<R>(
&mut self,
@ -308,11 +310,9 @@ impl MenuRoot {
/// Interaction with a stationary menu, i.e. fixed in another Ui.
///
/// Responds to primary clicks.
fn stationary_interaction(
response: &Response,
root: &mut MenuRootManager,
id: Id,
) -> MenuResponse {
fn stationary_interaction(response: &Response, root: &mut MenuRootManager) -> MenuResponse {
let id = response.id;
if (response.clicked() && root.is_menu_open(id))
|| response.ctx.input(|i| i.key_pressed(Key::Escape))
{
@ -357,8 +357,8 @@ impl MenuRoot {
MenuResponse::Stay
}
/// Interaction with a context menu (secondary clicks).
fn context_interaction(response: &Response, root: &mut Option<Self>, id: Id) -> MenuResponse {
/// Interaction with a context menu (secondary click).
fn context_interaction(response: &Response, root: &mut Option<Self>) -> MenuResponse {
let response = response.interact(Sense::click());
response.ctx.input(|input| {
let pointer = &input.pointer;
@ -371,7 +371,7 @@ impl MenuRoot {
}
if !in_old_menu {
if response.hovered() && response.secondary_clicked() {
return MenuResponse::Create(pos, id);
return MenuResponse::Create(pos, response.id);
} else if (response.hovered() && pointer.primary_down()) || destroy {
return MenuResponse::Close;
}
@ -392,14 +392,14 @@ impl MenuRoot {
}
/// Respond to secondary (right) clicks.
pub fn context_click_interaction(response: &Response, root: &mut MenuRootManager, id: Id) {
let menu_response = Self::context_interaction(response, root, id);
pub fn context_click_interaction(response: &Response, root: &mut MenuRootManager) {
let menu_response = Self::context_interaction(response, root);
Self::handle_menu_response(root, menu_response);
}
// Responds to primary clicks.
pub fn stationary_click_interaction(response: &Response, root: &mut MenuRootManager, id: Id) {
let menu_response = Self::stationary_interaction(response, root, id);
pub fn stationary_click_interaction(response: &Response, root: &mut MenuRootManager) {
let menu_response = Self::stationary_interaction(response, root);
Self::handle_menu_response(root, menu_response);
}
}

View File

@ -105,17 +105,17 @@ impl WidgetRects {
// e.g. calling `response.interact(…)` to add more interaction.
let (idx_in_layer, existing) = entry.get_mut();
egui_assert!(
existing.layer_id == widget_rect.layer_id,
"Widget changed layer_id during the frame"
);
// Update it:
existing.rect = widget_rect.rect; // last wins
existing.interact_rect = widget_rect.interact_rect; // last wins
existing.sense |= widget_rect.sense;
existing.enabled |= widget_rect.enabled;
egui_assert!(
existing.layer_id == widget_rect.layer_id,
"Widget changed layer_id during the frame"
);
if existing.layer_id == widget_rect.layer_id {
layer_widgets[*idx_in_layer] = *existing;
}