| 7612 | } |
| 7613 | |
| 7614 | bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) |
| 7615 | { |
| 7616 | ImGuiWindow* window = GetCurrentWindow(); |
| 7617 | if (window->SkipItems) |
| 7618 | return false; |
| 7619 | |
| 7620 | ImGuiContext& g = *GImGui; |
| 7621 | const ImGuiStyle& style = g.Style; |
| 7622 | const ImGuiID id = window->GetID(label); |
| 7623 | bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None); |
| 7624 | |
| 7625 | // 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) |
| 7626 | // 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. |
| 7627 | ImGuiWindowFlags window_flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus; |
| 7628 | if (window->Flags & ImGuiWindowFlags_ChildMenu) |
| 7629 | window_flags |= ImGuiWindowFlags_ChildWindow; |
| 7630 | |
| 7631 | // If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin(). |
| 7632 | // 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. |
| 7633 | // If somehow this is ever becoming a problem we can switch to use e.g. ImGuiStorage mapping key to last frame used. |
| 7634 | if (g.MenusIdSubmittedThisFrame.contains(id)) |
| 7635 | { |
| 7636 | if (menu_is_open) |
| 7637 | menu_is_open = BeginPopupEx(id, window_flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) |
| 7638 | else |
| 7639 | g.NextWindowData.ClearFlags(); // we behave like Begin() and need to consume those values |
| 7640 | return menu_is_open; |
| 7641 | } |
| 7642 | |
| 7643 | // Tag menu as used. Next time BeginMenu() with same ID is called it will append to existing menu |
| 7644 | g.MenusIdSubmittedThisFrame.push_back(id); |
| 7645 | |
| 7646 | ImVec2 label_size = CalcTextSize(label, NULL, true); |
| 7647 | |
| 7648 | // 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) |
| 7649 | // This is only done for items for the menu set and not the full parent window. |
| 7650 | const bool menuset_is_open = IsRootOfOpenMenuSet(); |
| 7651 | if (menuset_is_open) |
| 7652 | PushItemFlag(ImGuiItemFlags_NoWindowHoverableCheck, true); |
| 7653 | |
| 7654 | // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu, |
| 7655 | // However the final position is going to be different! It is chosen by FindBestWindowPosForPopup(). |
| 7656 | // e.g. Menus tend to overlap each other horizontally to amplify relative Z-ordering. |
| 7657 | ImVec2 popup_pos, pos = window->DC.CursorPos; |
| 7658 | PushID(label); |
| 7659 | if (!enabled) |
| 7660 | BeginDisabled(); |
| 7661 | const ImGuiMenuColumns* offsets = &window->DC.MenuColumns; |
| 7662 | bool pressed; |
| 7663 | |
| 7664 | // We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another. |
| 7665 | const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_NoAutoClosePopups; |
| 7666 | if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) |
| 7667 | { |
| 7668 | // Menu inside an horizontal menu bar |
| 7669 | // Selectable extend their highlight by half ItemSpacing in each direction. |
| 7670 | // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin() |
| 7671 | 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