ocornut / imgui

Dear ImGui: Bloat-free Graphical User interface for C++ with minimal dependencies
MIT License
61.11k stars 10.3k forks source link

Recommended way to expand / collapse tree nodes with keyboard shortcuts? #7553

Open sodamouse opened 6 months ago

sodamouse commented 6 months ago

Version/Branch of Dear ImGui:

Version 1.89.8, Branch: master

Back-ends:

imgui_impl_glfw.cpp + imgui_impl_opengl3.cpp

Compiler, OS:

Windows 11 + MSVC 2022

Full config/build information:

No response

Details:

My Issue/Question:

Hi, I am trying to figure out the best way to control expanding / collapsing a tree node using a keyboard shortcut. Currently, I use a simple bool flag + ImGuiTreeNodeFlag_DefaultOpen the to do this (see example).

I know this is very hacky, but it works fine until I start to also use the mouse to expand / collapse the node, after which the keyboard shortcut stops working. I'm sure that there is a recommended way to do this already, but I did not manage to find it.

Any suggestions?

Screenshots/Video:

No response

Minimal, Complete and Verifiable Example code:

    ImGuiTreeNodeFlags filterNodeFlags  = 0;

    if (filterNodeOpen) filterNodeFlags = ImGuiTreeNodeFlags_DefaultOpen;

    if (ImGui::TreeNodeEx("Filter", filterNodeFlags))
    {
        // ...
        ImGui::TreePop();
    }
// somewhere else in code
    if (!showTagsPopup && ImGui::IsKeyDown(ImGuiKey_LeftCtrl) && ImGui::IsKeyPressed(ImGuiKey_G)) filterNodeOpen = !filterNodeOpen;
GamingMinds-DanielC commented 6 months ago

Maintain a flag as you do now, toggle it with your keyboard shortcut. Then you can set the state reliably with ImGui::SetNextItemOpen() before calling ImGui::TreeNodeEx(). As a last step you need to update your flag with the result of TreeNodeEx().

ocornut commented 6 months ago

It may be easier to access the storage directly in this case, assuming you can compute the ID of your tree node.

if (ImGui::Shortcut(ImGuiMod_Ctrl | ImGuiKey_G))
{
    ImGuiStorage* storage = ImGui::GetStateStorage();
    (*storage->GetBoolRef(id_of_tree_node)) ^= 1; // toggle
}
ocornut commented 6 months ago

There's a named wrapper called ImGui::TreeNodeSetOpen() but it's signature is not ideal for a toggle (read followed by write).

...but if you store/defer your request until the item is submitted and call SetNextItemOpen() before it (as suggested by Daniel) you may likely in a better position to e.g. request scrolling or some other associated desirable behavior. Both ways are possible.

sodamouse commented 4 months ago

Thanks, all of these approaches work fine. I ended up going with GamingMinds-DanielC's suggestion as it required the least amount of rewrite.

This issue can be closed.

ocornut commented 4 months ago

Good to hear. I’ll keep the issue open because i’ve been trying to work on this topic too.