| 7182 | } |
| 7183 | |
| 7184 | bool ImGui::MenuItemEx(const char* label, const char* icon, const char* shortcut, bool selected, bool enabled) |
| 7185 | { |
| 7186 | ImGuiWindow* window = GetCurrentWindow(); |
| 7187 | if (window->SkipItems) |
| 7188 | return false; |
| 7189 | |
| 7190 | ImGuiContext& g = *GImGui; |
| 7191 | ImGuiStyle& style = g.Style; |
| 7192 | ImVec2 pos = window->DC.CursorPos; |
| 7193 | ImVec2 label_size = CalcTextSize(label, NULL, true); |
| 7194 | |
| 7195 | // See BeginMenuEx() for comments about this. |
| 7196 | const bool menuset_is_open = IsRootOfOpenMenuSet(); |
| 7197 | if (menuset_is_open) |
| 7198 | PushItemFlag(ImGuiItemFlags_NoWindowHoverableCheck, true); |
| 7199 | |
| 7200 | // We've been using the equivalent of ImGuiSelectableFlags_SetNavIdOnHover on all Selectable() since early Nav system days (commit 43ee5d73), |
| 7201 | // but I am unsure whether this should be kept at all. For now moved it to be an opt-in feature used by menus only. |
| 7202 | bool pressed; |
| 7203 | PushID(label); |
| 7204 | if (!enabled) |
| 7205 | BeginDisabled(); |
| 7206 | |
| 7207 | // We use ImGuiSelectableFlags_NoSetKeyOwner to allow down on one menu item, move, up on another. |
| 7208 | const ImGuiSelectableFlags selectable_flags = ImGuiSelectableFlags_SelectOnRelease | ImGuiSelectableFlags_NoSetKeyOwner | ImGuiSelectableFlags_SetNavIdOnHover; |
| 7209 | const ImGuiMenuColumns* offsets = &window->DC.MenuColumns; |
| 7210 | if (window->DC.LayoutType == ImGuiLayoutType_Horizontal) |
| 7211 | { |
| 7212 | // Mimic the exact layout spacing of BeginMenu() to allow MenuItem() inside a menu bar, which is a little misleading but may be useful |
| 7213 | // Note that in this situation: we don't render the shortcut, we render a highlight instead of the selected tick mark. |
| 7214 | float w = label_size.x; |
| 7215 | window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * 0.5f); |
| 7216 | ImVec2 text_pos(window->DC.CursorPos.x + offsets->OffsetLabel, window->DC.CursorPos.y + window->DC.CurrLineTextBaseOffset); |
| 7217 | PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(style.ItemSpacing.x * 2.0f, style.ItemSpacing.y)); |
| 7218 | pressed = Selectable("", selected, selectable_flags, ImVec2(w, 0.0f)); |
| 7219 | PopStyleVar(); |
| 7220 | if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) |
| 7221 | RenderText(text_pos, label); |
| 7222 | window->DC.CursorPos.x += IM_FLOOR(style.ItemSpacing.x * (-1.0f + 0.5f)); // -1 spacing to compensate the spacing added when Selectable() did a SameLine(). It would also work to call SameLine() ourselves after the PopStyleVar(). |
| 7223 | } |
| 7224 | else |
| 7225 | { |
| 7226 | // Menu item inside a vertical menu |
| 7227 | // (In a typical menu window where all items are BeginMenu() or MenuItem() calls, extra_w will always be 0.0f. |
| 7228 | // Only when they are other items sticking out we're going to add spacing, yet only register minimum width into the layout system. |
| 7229 | float icon_w = (icon && icon[0]) ? CalcTextSize(icon, NULL).x : 0.0f; |
| 7230 | float shortcut_w = (shortcut && shortcut[0]) ? CalcTextSize(shortcut, NULL).x : 0.0f; |
| 7231 | float checkmark_w = IM_FLOOR(g.FontSize * 1.20f); |
| 7232 | float min_w = window->DC.MenuColumns.DeclColumns(icon_w, label_size.x, shortcut_w, checkmark_w); // Feedback for next frame |
| 7233 | float stretch_w = ImMax(0.0f, GetContentRegionAvail().x - min_w); |
| 7234 | pressed = Selectable("", false, selectable_flags | ImGuiSelectableFlags_SpanAvailWidth, ImVec2(min_w, 0.0f)); |
| 7235 | if (g.LastItemData.StatusFlags & ImGuiItemStatusFlags_Visible) |
| 7236 | { |
| 7237 | RenderText(pos + ImVec2(offsets->OffsetLabel, 0.0f), label); |
| 7238 | if (icon_w > 0.0f) |
| 7239 | RenderText(pos + ImVec2(offsets->OffsetIcon, 0.0f), icon); |
| 7240 | if (shortcut_w > 0.0f) |
| 7241 | { |
nothing calls this directly
no test coverage detected