ocornut / imgui

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

Rename tree nodes #3730

Open dgregorius opened 3 years ago

dgregorius commented 3 years ago

Version/Branch of Dear ImGui:

Version: 1.79 Branch: Viewport

Back-end/Renderer/Compiler/OS

Back-ends: imgui_impl_opengl3.cpp + imgui_impl_glfw.cpp Compiler: VS 2019 Operating System: Windows 10

My Issue/Question:

I want to be able to rename the nodes in a tree view. What is the recommend way to do this? Do I need to re-implement the tree using selectables and editable text widgets?

Thanks!

twaritwaikar commented 3 years ago

You provide the name for the node in Dear ImGui, so just change the string which you pass in?

dgregorius commented 3 years ago

I mean renaming like in press F2 and type a new name into the widget.

ocornut commented 3 years ago

Since eg pressing F2 is a stateful action I imagine you would want your selected treenode to stop submitting its label and switch to using AllowOverlap mode + display an InputText in the same location, but without visible frame, when renaming.

Treenode should preserve a constant ID while doing, so ID shouldn’t be derived from the label value.

I haven’t tried this but I see no specific issue going forward, apart from the fact that currently to access the F2 key you need to use backend specific defines (GLFW_KEY_F2).

dgregorius commented 3 years ago

Great, this makes a lot of sense and sounds easy enough!

dgregorius commented 3 years ago

Ok, this is nearly working. The only thing I am missing is how to correctly align the input text item. How do I get the current text offset of the tree node?

ocornut commented 3 years ago

There’s literally a function to do that.

dgregorius commented 3 years ago

Found it, thanks! Works great now.

One final question regarding the constant tree node id. Can I just push the transform pointer onto the Id stack and then have the label be ignored for Id hashing. I looked for this in the FAQ, but couldn't find a syntax for this. So it seems I would need to do something like label = name###transform_address for example. What is the preferred way to do this?

ocornut commented 3 years ago

You can encode that data into the string after ###, but simpler or if your id key can’t be naturally expressed as a string, push whatever you need into the stack, and then the TreeNode id part of the label doesn’t matter, so PushID(whatever) and then use “some text###”. You might even just an empty string, use row spanning and display the text separately too.

caxapexac commented 2 years ago

@ocornut I hope you can give an advice, I'm making unity-like hierarchy rename behaviour where name is replaced to input field and vice versa

What I need:

  1. m_nodeRename became not null (any way)
  2. keyboard is automatically focused into appeared inputfield
  3. enter press or lose focus finish editing (make m_nodeRename = nullptr)

What I have: Strange focus behaviour, input field isn't selectable under treenode

        bool opened = ImGui::TreeNodeEx(node, flags, "");

        // TreeNode logic
        if (ImGui::IsItemClicked())
        {
            m_selectedNode = node;
        }

        // TreeNode render
        ImGui::SameLine();
        if (m_nodeToRename == node)
        {
            std::string buffer = std::string(node->getName());
            if (ImGui::InputText("###rename", buffer.data(), buffer.size(), ImGuiInputTextFlags_AutoSelectAll))
            {
                node->setName(buffer);
            }

            if (ImGui::IsItemFocused())
            {
                // What to do here?
                // ImGui::SetKeyboardFocusHere(); 
            }
            else
            {
                // What to do here?
                // m_nodeToRename = nullptr;
            }
        }
        else
        {
            ImGui::Text("%s", node->getName().c_str());
        }

        // TreeNode children
        if (opened)
        {
            int index = 0;
            node->foreachChildren([=, &index] (Node& child)
            {
                ImGui::PushID(index);
                // etc
                index++;
            });
            ImGui::TreePop();
        }
caxapexac commented 2 years ago

hierarchy

This is about selection under tree node, as you can see it almost fully covers input field click zone

caxapexac commented 2 years ago

UPD: solved by added

if (node != m_nodeToRename) flags |= ImGuiTreeNodeFlags_SpanAvailWidth | ImGuiTreeNodeFlags_SpanFullWidth;

So only not renaming nodes are clickable at full width

Shadowblitz16 commented 9 months ago

I get getting different sizes for InputText and Text image

ocornut commented 9 months ago

InputText and all framed widget use FramePadding.y. You can use PushStyleVar() to set FramePadding.y to 0.

Shadowblitz16 commented 9 months ago

InputText and all framed widget use FramePadding.y. You can use PushStyleVar() to set FramePadding.y to 0.

Thankyou Is there a way to keep the same framePadding x?