diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 0dec2215e..0074103db 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -107,6 +107,9 @@ Other Changes: default value of each `ImGuiItemFlags_LiveEditXXX`, because this is not expected to be a user preference but a programmer/widget preferences. Also, we strive to make the toolkit consistent. +- Popups: + - Added bool return value to `OpenPopup()`, `OpenPopupOnItemClick()` functions + to notify when the popup was just opened. (#9429) - InputText: - Added `style.InputTextCursorSize` to configure cursor/caret thickness. (#7031, #9409) This is automatically scaled by `style.ScaleAllSizes()`. @@ -131,7 +134,7 @@ Other Changes: - Headers: fixed label being clipped early to reserve space for a sort marker even when no sort marker is displayed. Auto-fitting a column still accounts for the possible marker, so that sorting after an auto-fit doesn't clip the label. -- Multi-Select +- Multi-Select: - Reworked ImGuiMultiSelectFlags_NoAutoSelect as it carried side-effects that were hardcoded/designed to use multi-selection on checkboxes. (#9391) Specifically removed those undocumented behaviors from _NoAutoSelect: diff --git a/imgui.cpp b/imgui.cpp index 741d6b2a7..b93e48a66 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -12430,24 +12430,26 @@ ImGuiWindow* ImGui::FindBlockingModal(ImGuiWindow* window) return NULL; } -void ImGui::OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags) +bool ImGui::OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiID id = g.CurrentWindow->GetID(str_id); IMGUI_DEBUG_LOG_POPUP("[popup] OpenPopup(\"%s\" -> 0x%08X)\n", str_id, id); - OpenPopupEx(id, popup_flags); + return OpenPopupEx(id, popup_flags); } -void ImGui::OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags) +bool ImGui::OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags) { - OpenPopupEx(id, popup_flags); + return OpenPopupEx(id, popup_flags); } // Mark popup as open (toggle toward open state). -// Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. -// Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). -// One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL) -void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags) +// - Return true when the popup is toggled open, which allows you to capture local state if needed. +// You may also call IsWindowAppearing() inside the later BeginPopup() scope if you need to prepare/compute data for the popup. +// - Popups are closed when user click outside, or activate a pressable item, or CloseCurrentPopup() is called within a BeginPopup()/EndPopup() block. +// - Popup identifiers are relative to the current ID-stack (so OpenPopup and BeginPopup needs to be at the same level). +// - One open popup per level of the popup hierarchy (NB: when assigning we reset the Window member of ImGuiPopupRef to NULL). +bool ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; ImGuiWindow* parent_window = g.CurrentWindow; @@ -12455,7 +12457,7 @@ void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags) if (popup_flags & ImGuiPopupFlags_NoOpenOverExistingPopup) if (IsPopupOpen((ImGuiID)0, ImGuiPopupFlags_AnyPopupId)) - return; + return false; ImGuiPopupData popup_ref; // Tagged as new ref as Window will be set back to NULL if we write this into OpenPopupStack. popup_ref.PopupId = id; @@ -12470,6 +12472,7 @@ void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags) if (g.OpenPopupStack.Size < current_stack_size + 1) { g.OpenPopupStack.push_back(popup_ref); + return true; } else { @@ -12497,6 +12500,8 @@ void ImGui::OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags) // This is equivalent to what ClosePopupToLevel() does. //if (g.OpenPopupStack[current_stack_size].PopupId == id) // FocusWindow(parent_window); + + return !keep_existing; } } @@ -12781,16 +12786,17 @@ bool ImGui::IsPopupOpenRequestForWindow(ImGuiPopupFlags popup_flags) // Helper to open a popup if mouse button is released over the item // - This is essentially the same as BeginPopupContextItem() but without the trailing BeginPopup() -void ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags) +bool ImGui::OpenPopupOnItemClick(const char* str_id, ImGuiPopupFlags popup_flags) { ImGuiContext& g = *GImGui; - ImGuiWindow* window = g.CurrentWindow; if (IsPopupOpenRequestForItem(popup_flags, g.LastItemData.ID)) { + ImGuiWindow* window = g.CurrentWindow; ImGuiID id = str_id ? window->GetID(str_id) : g.LastItemData.ID; // If user hasn't passed an ID, we can use the LastItemID. Using LastItemID as a Popup ID won't conflict! IM_ASSERT(id != 0); // You cannot pass a NULL str_id if the last item has no identifier (e.g. a Text() item) - OpenPopupEx(id, popup_flags); + return OpenPopupEx(id, popup_flags); } + return false; } // This is a helper to handle the simplest case of associating one named popup to one given widget. diff --git a/imgui.h b/imgui.h index 6b7389753..5ef2e61a5 100644 --- a/imgui.h +++ b/imgui.h @@ -850,15 +850,17 @@ namespace ImGui IMGUI_API void EndPopup(); // only call EndPopup() if BeginPopupXXX() returns true! // Popups: open/close functions - // - OpenPopup(): set popup state to open. ImGuiPopupFlags are available for opening options. + // - OpenPopup(): set popup state to open (unless one of the specified ImGuiPopupFlags prevent opening). + // - OpenPopupXXX() functions return true when the popup is toggled open, which allows you to capture local state if needed. + // You may also call IsWindowAppearing() inside the later BeginPopup() scope if you need to prepare/compute data for the popup. // - If not modal: they can be closed by clicking anywhere outside them, or by pressing ESCAPE. // - CloseCurrentPopup(): use inside the BeginPopup()/EndPopup() scope to close manually. // - CloseCurrentPopup() is called by default by Selectable()/MenuItem() when activated (FIXME: need some options). // - Use ImGuiPopupFlags_NoOpenOverExistingPopup to avoid opening a popup if there's already one at the same level. This is equivalent to e.g. testing for !IsAnyPopupOpen() prior to OpenPopup(). // - Use IsWindowAppearing() after BeginPopup() to tell if a window just opened. - IMGUI_API void OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags = 0); // call to mark popup as open (don't call every frame!). - IMGUI_API void OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags = 0); // id overload to facilitate calling from nested stacks - IMGUI_API void OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors) + IMGUI_API bool OpenPopup(const char* str_id, ImGuiPopupFlags popup_flags = 0); // call to mark popup as open (don't call every frame!). + IMGUI_API bool OpenPopup(ImGuiID id, ImGuiPopupFlags popup_flags = 0); // id overload to facilitate calling from nested stacks + IMGUI_API bool OpenPopupOnItemClick(const char* str_id = NULL, ImGuiPopupFlags popup_flags = 0); // helper to open popup when clicked on last item. Default to ImGuiPopupFlags_MouseButtonRight == 1. (note: actually triggers on the mouse _released_ event to be consistent with popup behaviors) IMGUI_API void CloseCurrentPopup(); // manually close the popup we have begin-ed into. // Popups: Open+Begin popup combined functions helpers to create context menus. diff --git a/imgui_internal.h b/imgui_internal.h index 7eb5780f2..584914fc4 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -3504,7 +3504,7 @@ namespace ImGui // Popups, Modals IMGUI_API bool BeginPopupEx(ImGuiID id, ImGuiWindowFlags extra_window_flags); IMGUI_API bool BeginPopupMenuEx(ImGuiID id, const char* label, ImGuiWindowFlags extra_window_flags); - IMGUI_API void OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None); + IMGUI_API bool OpenPopupEx(ImGuiID id, ImGuiPopupFlags popup_flags = ImGuiPopupFlags_None); IMGUI_API void ClosePopupToLevel(int remaining, bool restore_focus_to_window_under_popup); IMGUI_API void ClosePopupsOverWindow(ImGuiWindow* ref_window, bool restore_focus_to_window_under_popup); IMGUI_API void ClosePopupsExceptModals();