diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 4478bcba6..662f065a0 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -54,6 +54,8 @@ Other Changes: - Window: Allow menu and popups windows from ignoring the style.WindowMinSize values so short menus/popups are not padded. (#1909) - Window: Added global io.OptResizeWindowsFromEdges option to enable resizing windows from their edges and from the lower-left corner. (#1495) - Window: Collapse button shows hovering highlight + clicking and dragging on it allows to drag the window as well. + - Added IsItemEdited() to query if the last item modified its value (or was pressed). This is equivalent to the bool returned by most widgets. + It is useful in some situation e.g. using InputText() with ImGuiInputTextFlags_EnterReturnsTrue. (#2034) - InputText: Added support for buffer size/capacity changes via the ImGuiInputTextFlags_CallbackResize flag. (#2006, #1443, #1008). - InputText: Fixed not tracking the cursor horizontally When modifying the text buffer through a callback. - InputText: Fixed minor off-by-one issue when submitting a buffer size smaller than the initial zero-terminated buffer contents. diff --git a/imgui.cpp b/imgui.cpp index 1e36dc839..8eeb9e0fd 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -5246,6 +5246,12 @@ bool ImGui::IsItemVisible() return window->ClipRect.Overlaps(window->DC.LastItemRect); } +bool ImGui::IsItemEdited() +{ + ImGuiWindow* window = GetCurrentWindowRead(); + return (window->DC.LastItemStatusFlags & ImGuiItemStatusFlags_ValueChanged) != 0; +} + // Allow last item to be overlapped by a subsequent item. Both may be activated during the same frame before the later one takes priority. void ImGui::SetItemAllowOverlap() { @@ -11954,6 +11960,7 @@ bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(v return false; // Assume all items have even height (= 1 line of text). If you need items of different or variable sizes you can create a custom version of ListBox() in your code without using the clipper. + ImGuiContext& g = *GImGui; bool value_changed = false; ImGuiListClipper clipper(items_count, GetTextLineHeightWithSpacing()); // We know exactly our line height here so we pass it as a minor optimization, but generally you don't need to. while (clipper.Step()) @@ -11975,6 +11982,9 @@ bool ImGui::ListBox(const char* label, int* current_item, bool (*items_getter)(v PopID(); } ListBoxFooter(); + if (value_changed) + MarkItemValueChanged(g.CurrentWindow->DC.LastItemId); + return value_changed; } @@ -13268,7 +13278,7 @@ void ImGui::EndGroup() } // If the current ActiveId was declared within the boundary of our group, we copy it to LastItemId so IsItemActive(), IsItemDeactivated() etc. will be functional on the entire group. - // It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but put a little more burden on individual widgets. + // It would be be neater if we replaced window.DC.LastItemId by e.g. 'bool LastItemIsActive', but would put a little more burden on individual widgets. // (and if you grep for LastItemId you'll notice it is only used in that context. if ((group_data.BackupActiveIdIsAlive != g.ActiveId) && (g.ActiveIdIsAlive == g.ActiveId) && g.ActiveId) // && g.ActiveIdWindow->RootWindow == window->RootWindow) window->DC.LastItemId = g.ActiveId; diff --git a/imgui.h b/imgui.h index 78ebc51b6..678024b41 100644 --- a/imgui.h +++ b/imgui.h @@ -521,6 +521,7 @@ namespace ImGui IMGUI_API bool IsItemFocused(); // is the last item focused for keyboard/gamepad navigation? IMGUI_API bool IsItemClicked(int mouse_button = 0); // is the last item clicked? (e.g. button/node just clicked on) == IsMouseClicked(mouse_button) && IsItemHovered() IMGUI_API bool IsItemVisible(); // is the last item visible? (items may be out of sight because of clipping/scrolling) + IMGUI_API bool IsItemEdited(); // did the last item modify its underlying value this frame? or was pressed? This is generally the same as the "bool" return value of many widgets. IMGUI_API bool IsItemDeactivated(); // was the last item just made inactive (item was previously active). Useful for Undo/Redo patterns with widgets that requires continuous editing. IMGUI_API bool IsItemDeactivatedAfterChange(); // was the last item just made inactive and made a value change when it was active? (e.g. Slider/Drag moved). Useful for Undo/Redo patterns with widgets that requires continuous editing. Note that you may get false positives (some widgets such as Combo()/ListBox()/Selectable() will return true even when clicking an already selected item). IMGUI_API bool IsAnyItemHovered(); diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 35754e00b..b05f27209 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1275,7 +1275,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::TreePop(); } - if (ImGui::TreeNode("Active, Focused, Hovered & Focused Tests")) + if (ImGui::TreeNode("Active, Focused and Hovered Tests")) { // Display the value of IsItemHovered() and other common item state functions. Note that the flags can be combined. // (because BulletText is an item itself and that would affect the output of IsItemHovered() we pass all state in a single call to simplify the code). @@ -1304,6 +1304,7 @@ void ImGui::ShowDemoWindow(bool* p_open) "IsItemHovered(_AllowWhenOverlapped) = %d\n" "IsItemHovered(_RectOnly) = %d\n" "IsItemActive() = %d\n" + "IsItemEdited() = %d\n" "IsItemDeactivated() = %d\n" "IsItemDeactivatedAfterChange() = %d\n" "IsItemVisible() = %d\n", @@ -1315,6 +1316,7 @@ void ImGui::ShowDemoWindow(bool* p_open) ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenOverlapped), ImGui::IsItemHovered(ImGuiHoveredFlags_RectOnly), ImGui::IsItemActive(), + ImGui::IsItemEdited(), ImGui::IsItemDeactivated(), ImGui::IsItemDeactivatedAfterChange(), ImGui::IsItemVisible()