| 6962 | } |
| 6963 | |
| 6964 | bool ImGui::BeginMenuEx(const char* label, const char* icon, bool enabled) |
| 6965 | { |
| 6966 | ImGuiWindow* window = GetCurrentWindow(); |
| 6967 | if (window->SkipItems) |
| 6968 | return false; |
| 6969 | |
| 6970 | ImGuiContext& g = *GImGui; |
| 6971 | const ImGuiStyle& style = g.Style; |
| 6972 | const ImGuiID id = window->GetID(label); |
| 6973 | bool menu_is_open = IsPopupOpen(id, ImGuiPopupFlags_None); |
| 6974 | |
| 6975 | // 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) |
| 6976 | // 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. |
| 6977 | ImGuiWindowFlags window_flags = ImGuiWindowFlags_ChildMenu | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoNavFocus; |
| 6978 | if (window->Flags & ImGuiWindowFlags_ChildMenu) |
| 6979 | window_flags |= ImGuiWindowFlags_ChildWindow; |
| 6980 | |
| 6981 | // If a menu with same the ID was already submitted, we will append to it, matching the behavior of Begin(). |
| 6982 | // 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. |
| 6983 | // If somehow this is ever becoming a problem we can switch to use e.g. ImGuiStorage mapping key to last frame used. |
| 6984 | if (g.MenusIdSubmittedThisFrame.contains(id)) |
| 6985 | { |
| 6986 | if (menu_is_open) |
| 6987 | menu_is_open = BeginPopupEx(id, window_flags); // menu_is_open can be 'false' when the popup is completely clipped (e.g. zero size display) |
| 6988 | else |
| 6989 | g.NextWindowData.ClearFlags(); // we behave like Begin() and need to consume those values |
| 6990 | return menu_is_open; |
| 6991 | } |
| 6992 | |
| 6993 | // Tag menu as used. Next time BeginMenu() with same ID is called it will append to existing menu |
| 6994 | g.MenusIdSubmittedThisFrame.push_back(id); |
| 6995 | |
| 6996 | ImVec2 label_size = CalcTextSize(label, NULL, true); |
| 6997 | |
| 6998 | // 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) |
| 6999 | // This is only done for items for the menu set and not the full parent window. |
| 7000 | const bool menuset_is_open = IsRootOfOpenMenuSet(); |
| 7001 | if (menuset_is_open) |
| 7002 | PushItemFlag(ImGuiItemFlags_NoWindowHoverableCheck, true); |
| 7003 | |
| 7004 | // The reference position stored in popup_pos will be used by Begin() to find a suitable position for the child menu, |
| 7005 | // However the final position is going to be different! It is chosen by FindBestWindowPosForPopup(). |
| 7006 | // e.g. Menus tend to overlap each other horizontally to amplify relative Z-ordering. |
| 7007 | ImVec2 popup_pos, pos = window->DC.CursorPos; |
| 7008 | PushID(label); |
| 7009 | if (!enabled) |
| 7010 | BeginDisabled(); |
| 7011 | const ImGuiMenuColumns* offsets = &window->DC.MenuColumns; |
| 7012 | bool pressed; |
| 7013 | |
| 7014 | // We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another. |
| 7015 | const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_NoHoldingActiveID | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SelectOnClick | ImGuiSelectableFlags_DontClosePopups; |
| 7016 | if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) |
| 7017 | { |
| 7018 | // Menu inside an horizontal menu bar |
| 7019 | // Selectable extend their highlight by half ItemSpacing in each direction. |
| 7020 | // For ChildMenu, the popup position will be overwritten by the call to FindBestWindowPosForPopup() in Begin() |
| 7021 | popup_pos = ImVec2(pos.x - 1.0f - IM_FLOOR(style.ItemSpacing.x * 0.5f), pos.y - style.FramePadding.y + window->MenuBarHeight()); |
nothing calls this directly
no test coverage detected