From 57dc34f4e850c29ba9be7886afc7d07486a7ef59 Mon Sep 17 00:00:00 2001 From: omar Date: Fri, 8 Nov 2019 15:23:34 +0100 Subject: [PATCH] TreeNode: Added IsItemToggledOpen() to explicitly query if item was just open/closed, facilitating interactions with custom multi-selections patterns. (#1896, #1861) --- docs/CHANGELOG.txt | 4 +++- imgui.cpp | 6 ++++++ imgui.h | 1 + imgui_demo.cpp | 9 ++++++--- imgui_internal.h | 5 +++-- imgui_widgets.cpp | 3 ++- 6 files changed, 21 insertions(+), 7 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index a28d9cc9..a45a3b79 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -67,7 +67,9 @@ Other Changes: - TreeNode: Fixed combination of ImGuiTreeNodeFlags_SpanFullWidth and ImGuiTreeNodeFlags_OpenOnArrow incorrectly locating the arrow hit position to the left of the frame. (#2451, #2438, #1897) - TreeNode: The collapsing arrow accepts click even if modifier keys are being held, facilitating - interactions with multi-select patterns. (#2886, #1896, #1861) + interactions with custom multi-selections patterns. (#2886, #1896, #1861) +- TreeNode: Added IsItemToggledOpen() to explicitly query if item was just open/closed, facilitating + interactions with custom multi-selections patterns. (#1896, #1861) - DragScalar, SliderScalar, InputScalar: Added p_ prefix to parameter that are pointers to the data to clarify how they are used, and more comments redirecting to the demo code. (#2844) - Misc: Optimized storage of window settings data (reducing allocation count). diff --git a/imgui.cpp b/imgui.cpp index c15121a3..e21c8a0d 100644 --- a/imgui.cpp +++ b/imgui.cpp @@ -4458,6 +4458,12 @@ bool ImGui::IsItemClicked(int mouse_button) return IsMouseClicked(mouse_button) && IsItemHovered(ImGuiHoveredFlags_None); } +bool ImGui::IsItemToggledOpen() +{ + ImGuiContext& g = *GImGui; + return (g.CurrentWindow->DC.LastItemStatusFlags & ImGuiItemStatusFlags_ToggledOpen) ? true : false; +} + bool ImGui::IsItemToggledSelection() { ImGuiContext& g = *GImGui; diff --git a/imgui.h b/imgui.h index ceac0879..bde32ceb 100644 --- a/imgui.h +++ b/imgui.h @@ -636,6 +636,7 @@ namespace ImGui IMGUI_API bool IsItemActivated(); // was the last item just made active (item was previously inactive). 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 IsItemDeactivatedAfterEdit(); // 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 IsItemToggledOpen(); // was the last item open state toggled? set by TreeNode(). IMGUI_API bool IsAnyItemHovered(); // is any item hovered? IMGUI_API bool IsAnyItemActive(); // is any item active? IMGUI_API bool IsAnyItemFocused(); // is any item focused? diff --git a/imgui_demo.cpp b/imgui_demo.cpp index 3eedda45..b98eb766 100644 --- a/imgui_demo.cpp +++ b/imgui_demo.cpp @@ -1613,7 +1613,7 @@ static void ShowDemoWindowWidgets() { // Submit an item (various types available) so we can query their status in the following block. static int item_type = 1; - ImGui::Combo("Item Type", &item_type, "Text\0Button\0Button (w/ repeat)\0Checkbox\0SliderFloat\0InputText\0InputFloat\0InputFloat3\0ColorEdit4\0MenuItem\0TreeNode (w/ double-click)\0ListBox\0"); + ImGui::Combo("Item Type", &item_type, "Text\0Button\0Button (w/ repeat)\0Checkbox\0SliderFloat\0InputText\0InputFloat\0InputFloat3\0ColorEdit4\0MenuItem\0TreeNode\0TreeNode (w/ double-click)\0ListBox\0", 20); ImGui::SameLine(); HelpMarker("Testing how various types of items are interacting with the IsItemXXX functions."); bool ret = false; @@ -1630,8 +1630,9 @@ static void ShowDemoWindowWidgets() if (item_type == 7) { ret = ImGui::InputFloat3("ITEM: InputFloat3", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) if (item_type == 8) { ret = ImGui::ColorEdit4("ITEM: ColorEdit4", col4f); } // Testing multi-component items (IsItemXXX flags are reported merged) if (item_type == 9) { ret = ImGui::MenuItem("ITEM: MenuItem"); } // Testing menu item (they use ImGuiButtonFlags_PressedOnRelease button policy) - if (item_type == 10){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy. - if (item_type == 11){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } + if (item_type == 10){ ret = ImGui::TreeNode("ITEM: TreeNode"); if (ret) ImGui::TreePop(); } // Testing tree node + if (item_type == 11){ ret = ImGui::TreeNodeEx("ITEM: TreeNode w/ ImGuiTreeNodeFlags_OpenOnDoubleClick", ImGuiTreeNodeFlags_OpenOnDoubleClick | ImGuiTreeNodeFlags_NoTreePushOnOpen); } // Testing tree node with ImGuiButtonFlags_PressedOnDoubleClick button policy. + if (item_type == 12){ const char* items[] = { "Apple", "Banana", "Cherry", "Kiwi" }; static int current = 1; ret = ImGui::ListBox("ITEM: ListBox", ¤t, items, IM_ARRAYSIZE(items), IM_ARRAYSIZE(items)); } // Display the value of IsItemHovered() and other common item state functions. // Note that the ImGuiHoveredFlags_XXX flags can be combined. @@ -1652,6 +1653,7 @@ static void ShowDemoWindowWidgets() "IsItemDeactivatedAfterEdit() = %d\n" "IsItemVisible() = %d\n" "IsItemClicked() = %d\n" + "IsItemToggledOpen() = %d\n" "GetItemRectMin() = (%.1f, %.1f)\n" "GetItemRectMax() = (%.1f, %.1f)\n" "GetItemRectSize() = (%.1f, %.1f)", @@ -1669,6 +1671,7 @@ static void ShowDemoWindowWidgets() ImGui::IsItemDeactivatedAfterEdit(), ImGui::IsItemVisible(), ImGui::IsItemClicked(), + ImGui::IsItemToggledOpen(), ImGui::GetItemRectMin().x, ImGui::GetItemRectMin().y, ImGui::GetItemRectMax().x, ImGui::GetItemRectMax().y, ImGui::GetItemRectSize().x, ImGui::GetItemRectSize().y diff --git a/imgui_internal.h b/imgui_internal.h index 63357cea..42d296db 100644 --- a/imgui_internal.h +++ b/imgui_internal.h @@ -444,8 +444,9 @@ enum ImGuiItemStatusFlags_ ImGuiItemStatusFlags_HasDisplayRect = 1 << 1, ImGuiItemStatusFlags_Edited = 1 << 2, // Value exposed by item was edited in the current frame (should match the bool return value of most widgets) ImGuiItemStatusFlags_ToggledSelection = 1 << 3, // Set when Selectable(), TreeNode() reports toggling a selection. We can't report "Selected" because reporting the change allows us to handle clipping with less issues. - ImGuiItemStatusFlags_HasDeactivated = 1 << 4, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag. - ImGuiItemStatusFlags_Deactivated = 1 << 5 // Only valid if ImGuiItemStatusFlags_HasDeactivated is set. + ImGuiItemStatusFlags_ToggledOpen = 1 << 4, // Set when TreeNode() reports toggling their open state. + ImGuiItemStatusFlags_HasDeactivated = 1 << 5, // Set if the widget/group is able to provide data for the ImGuiItemStatusFlags_Deactivated flag. + ImGuiItemStatusFlags_Deactivated = 1 << 6 // Only valid if ImGuiItemStatusFlags_HasDeactivated is set. #ifdef IMGUI_ENABLE_TEST_ENGINE , // [imgui_tests only] diff --git a/imgui_widgets.cpp b/imgui_widgets.cpp index d5968315..2757ac6f 100644 --- a/imgui_widgets.cpp +++ b/imgui_widgets.cpp @@ -5291,9 +5291,9 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l bool hovered, held; bool pressed = ButtonBehavior(interact_bb, id, &hovered, &held, button_flags); - bool toggled = false; if (!is_leaf) { + bool toggled = false; if (pressed) { if ((flags & (ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick)) == 0 || (g.NavActivateId == id)) @@ -5321,6 +5321,7 @@ bool ImGui::TreeNodeBehavior(ImGuiID id, ImGuiTreeNodeFlags flags, const char* l { is_open = !is_open; window->DC.StateStorage->SetInt(id, is_open); + window->DC.LastItemStatusFlags |= ImGuiItemStatusFlags_ToggledOpen; } } if (flags & ImGuiTreeNodeFlags_AllowItemOverlap)