Skip to content

Commit 0342a3c

Browse files
rokupsocornut
authored andcommitted
Menus: Implement BeginMenu() appending to existing menu when executed with same ID multiple times. (ocornut#1207)
1 parent 898e91f commit 0342a3c

File tree

5 files changed

+23
-7
lines changed

5 files changed

+23
-7
lines changed

docs/CHANGELOG.txt

+1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Other Changes:
4040
branch pressing arrow keys while dragging a window from a tab could trigger an assert. (#3025)
4141
- ColorButton: Added ImGuiColorEditFlags_NoBorder flag to remove the border normally enforced
4242
by default for standalone ColorButton.
43+
- BeginMenu: Using same ID multiple times appends content to a menu. (#1207)
4344
- BeginMenu: Fixed a bug where SetNextWindowXXX data before a BeginMenu() would not be cleared
4445
when the menu is not open. (#3030)
4546
- InputText: Fixed password fields displaying ASCII spaces as blanks instead of using the '*'

docs/TODO.txt

-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,6 @@ It's mostly a bunch of personal notes, probably incomplete. Feel free to query i
214214
- tooltip: tooltips with delay timers? or general timer policy? (instantaneous vs timed): IsItemHovered() with timer + implicit aabb-id for items with no ID. (#1485)
215215
- tooltip: drag tooltip hovering over source widget with IsItemHovered/SetTooltip flickers.
216216

217-
- menus: calling BeginMenu() twice with a same name doesn't append as Begin() does for regular windows (#1207)
218217
- menus: menu bars inside modal windows are acting weird.
219218
- status-bar: add a per-window status bar helper similar to what menu-bar does.
220219
- shortcuts: local-style shortcut api, e.g. parse "&Save"

imgui.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -3623,6 +3623,7 @@ void ImGui::NewFrame()
36233623
g.FrameCount += 1;
36243624
g.TooltipOverrideCount = 0;
36253625
g.WindowsActiveCount = 0;
3626+
g.RenderedMenusId.resize(0);
36263627

36273628
// Setup current font and draw list shared data
36283629
g.IO.Fonts->Locked = true;

imgui_internal.h

+1
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,7 @@ struct ImGuiContext
11591159
float ScrollbarClickDeltaToGrabCenter; // Distance between mouse and center of grab box, normalized in parent space. Use storage?
11601160
int TooltipOverrideCount;
11611161
ImVector<char> PrivateClipboard; // If no custom clipboard handler is defined
1162+
ImVector<ImGuiID> RenderedMenusId; // A list of menu IDs that were rendered at least once
11621163

11631164
// Platform support
11641165
ImVec2 PlatformImePos; // Cursor position request & last passed to the OS Input Method Editor

imgui_widgets.cpp

+20-6
Original file line numberDiff line numberDiff line change
@@ -6222,11 +6222,29 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
62226222
ImGuiContext& g = *GImGui;
62236223
const ImGuiStyle& style = g.Style;
62246224
const ImGuiID id = window->GetID(label);
6225+
bool menu_is_open = IsPopupOpen(id);
6226+
ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus;
62256227

6226-
ImVec2 label_size = CalcTextSize(label, NULL, true);
6228+
// 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)
6229+
if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu))
6230+
flags |= ImGuiWindowFlags_ChildWindow;
6231+
6232+
if (g.RenderedMenusId.contains(id))
6233+
{
6234+
// Menu with same ID was already created - append to it.
6235+
if (menu_is_open)
6236+
menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
6237+
if (!menu_is_open)
6238+
g.NextWindowData.ClearFlags(); // We behave like Begin() and need to consume those values
6239+
return menu_is_open;
6240+
}
6241+
else
6242+
{
6243+
g.RenderedMenusId.push_back(id); // Tag menu as used. Next time BeginMenu() with same ID is called it will append to existing menu.
6244+
}
62276245

6246+
ImVec2 label_size = CalcTextSize(label, NULL, true);
62286247
bool pressed;
6229-
bool menu_is_open = IsPopupOpen(id);
62306248
bool menuset_is_open = !(window->Flags & ImGuiWindowFlags_Popup) && (g.OpenPopupStack.Size > g.BeginPopupStack.Size && g.OpenPopupStack[g.BeginPopupStack.Size].OpenParentId == window->IDStack.back());
62316249
ImGuiWindow* backed_nav_window = g.NavWindow;
62326250
if (menuset_is_open)
@@ -6345,11 +6363,7 @@ bool ImGui::BeginMenu(const char* label, bool enabled)
63456363

63466364
if (menu_is_open)
63476365
{
6348-
// 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)
63496366
SetNextWindowPos(popup_pos, ImGuiCond_Always);
6350-
ImGuiWindowFlags flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus;
6351-
if (window->Flags & (ImGuiWindowFlags_Popup|ImGuiWindowFlags_ChildMenu))
6352-
flags |= ImGuiWindowFlags_ChildWindow;
63536367
menu_is_open = BeginPopupEx(id, flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display)
63546368
}
63556369
else

0 commit comments

Comments
 (0)