| 9125 | } |
| 9126 | |
| 9127 | bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) |
| 9128 | { |
| 9129 | ImGuiWindow* window = GetCurrentWindow(); |
| 9130 | if (window->SkipItems) |
| 9131 | return false; |
| 9132 | |
| 9133 | ImGuiContext& g = *GImGui; |
| 9134 | const ImGuiStyle& style = g.Style; |
| 9135 | const ImGuiID id = window->GetID(label); |
| 9136 | bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None); |
| 9137 | |
| 9138 | // 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) |
| 9139 | // The first menu in a hierarchy isn't so hovering doesn't get across (otherwise e.g. resizing borders with ImGuiButtonFlags_FlattenChildren would react), but top-most BeginMenu() will bypass that limitation. |
| 9140 | ImGuiWindowFlags window_flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus; |
| 9141 | if (window->Flags & ImGuiWindowFlags_ChildMenu) |
| 9142 | window_flags |= ImGuiWindowFlags_ChildWindow; |
| 9143 | |
| 9144 | // If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin(). |
| 9145 | // We are relying on a O(N) search - so O(N log N) over the frame - which seems like the most efficient for the expected small amount of BeginMenu() calls per frame. |
| 9146 | // If somehow this is ever becoming a problem we can switch to use e.g. ImGuiStorage mapping key to last frame used. |
| 9147 | if (g.MenusIdSubmittedThisFrame.contains(id)) |
| 9148 | { |
| 9149 | if (menu_is_open) |
| 9150 | menu_is_open = BeginPopupMenuEx(id, label, window_flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) |
| 9151 | else |
| 9152 | g.NextWindowData.ClearFlags(); // we behave like Begin() and need to consume those values |
| 9153 | return menu_is_open; |
| 9154 | } |
| 9155 | |
| 9156 | // Tag menu as used. Next time BeginMenu() with same ID is called it will append to existing menu |
| 9157 | g.MenusIdSubmittedThisFrame.push_back(id); |
| 9158 | |
| 9159 | ImVec2 label_size = CalcTextSize(label, NULL, true); |
| 9160 | |
| 9161 | // Odd hack to allow hovering across menus of a same menu-set (otherwise we wouldn't be able to hover parent without always being a Child window) |
| 9162 | // This is only done for items for the menu set and not the full parent window. |
| 9163 | const bool menuset_is_open = IsRootOfOpenMenuSet(); |
| 9164 | if (menuset_is_open) |
| 9165 | PushItemFlag(ImGuiItemFlags_NoWindowHoverableCheck, true); |
| 9166 | |
| 9167 | // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu, |
| 9168 | // However the final position is going to be different! It is chosen by FindBestWindowPosForPopup(). |
| 9169 | // e.g. Menus tend to overlap each other horizontally to amplify relative Z-ordering. |
| 9170 | ImVec2 popup_pos, pos = window->DC.CursorPos; |
| 9171 | PushID(label); |
| 9172 | if (!enabled) |
| 9173 | BeginDisabled(); |
| 9174 | const ImGuiMenuColumns* offsets = &window->DC.MenuColumns; |
| 9175 | bool pressed; |
| 9176 | |
| 9177 | // We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another. |
| 9178 | const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_NoAutoClosePopups; |
| 9179 | if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) |
| 9180 | { |
| 9181 | // Menu inside a horizontal menu bar |
| 9182 | // Selectable extend their highlight by half ItemSpacing in each direction. |
| 9183 | // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin() |
| 9184 | popup_pos = ImVec2(pos.x - 1.0f - IM_TRUNC(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight); |
nothing calls this directly
no test coverage detected