diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6a25fa65..7a7c1cd2 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -40,6 +40,7 @@ Other Changes: branch pressing arrow keys while dragging a window from a tab could trigger an assert. (#3025) - ColorButton: Added ImGuiColorEditFlags_NoBorder flag to remove the border normally enforced by default for standalone ColorButton. +- BeginMenu: Using same ID multiple times appends content to a menu. (#1207) - BeginMenu: Fixed a bug where SetNextWindowXXX data before a BeginMenu() would not be cleared when the menu is not open. (#3030) - InputText: Fixed password fields displaying ASCII spaces as blanks instead of using the '*' diff --git a/docs/TODO.txt b/docs/TODO.txt index 24c79e43..ea612c57 100644 --- a/docs/TODO.txt +++ b/docs/TODO.txt @@ -214,7 +214,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i - tooltip: tooltips with delay timers? or general timer policy? (instantaneous vs timed): IsItemHovered() with timer + implicit aabb-id for items with no ID. (#1485) - tooltip: drag tooltip hovering over source widget with IsItemHovered/SetTooltip flickers. - - menus: calling BeginMenu() twice with a same name doesn't append as Begin() does for regular windows (#1207) - menus: menu bars inside modal windows are acting weird. - status-bar: add a per-window status bar helper similar to what menu-bar does. - shortcuts: local-style shortcut api, e.g. parse "&Save" diff --git a/imgui.cpp b/imgui.cpp index 98293e62..5a1810f8 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -3623,6 +3623,7 @@ void ImGui::NewFrame() g.FrameCount += 1; g.TooltipOverrideCount = 0; g.WindowsActiveCount = 0; + g.RenderedMenusId.resize(0); // Setup current font and draw list shared data g.IO.Fonts->Locked = true; diff --git a/imgui_internal.h b/imgui_internal.h index 87773e99..852211f6 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -1159,6 +1159,7 @@ struct ImGuiContext float ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage? int TooltipOverrideCount; ImVector PrivateClipboard; // If no custom clipboard handler is defined + ImVector RenderedMenusId; // A list of menu IDs that were rendered at least once // Platform support ImVec2 PlatformImePos; // Cursor position request & last passed to the OS Input Method Editor diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index ba35af12..1a505a3e 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -6222,11 +6222,29 @@ bool ImGui::BeginMenu(const char* label, bool enabled) ImGuiContext& g = *GImGui; const ImGuiStyle& style = g.Style; const ImGuiID id = window->GetID(label); + bool menu_is_open = IsPopupOpen(id); + ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus; + + // Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu) + if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) + flags |= ImGuiWindowFlags_ChildWindow; + + if (g.RenderedMenusId.contains(id)) + { + // Menu with same ID was already created - append to it. + if (menu_is_open) + menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) + if (!menu_is_open) + g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values + return menu_is_open; + } + else + { + g.RenderedMenusId.push_back(id); // Tag menu as used. Next time BeginMenu() with same ID is called it will append to existing menu. + } ImVec2 label_size = CalcTextSize(label, NULL, true); - bool pressed; - bool menu_is_open = IsPopupOpen(id); bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back()); ImGuiWindow* backed_nav_window = g.NavWindow; if (menuset_is_open) @@ -6345,11 +6363,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled) if (menu_is_open) { - // Sub-menus are ChildWindow so that mouse can be hovering across them (otherwise top-most popup menu would steal focus and not allow hovering on parent menu) SetNextWindowPos(popup_pos, ImGuiCond_Always); - ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus; - if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu)) - flags |= ImGuiWindowFlags_ChildWindow; menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) } else