Gui-builder: Being able to move items inside/outside another items hierarchy

Started by EngineerBread, 17 July 2024, 19:50:07

EngineerBread

Hi I hope you all are doing well.
The title didn't let me put the complete string so here it comes: "Gui-builder: Being able to move items inside/outside another items hierarchy using the hierarchy tree"
So the title pretty much says it all, I want to be able to move items inside/outside of another items hierarchy if they are allowed, like in the example that I show in the image, for example if we have on tgui::TreeView inside of a tgui::ChildWindow and I want to remove that tree from that childWindow to put it inside someone else. I think that could really be useful.
I tried to do that but I don't think its the right approach, here is what I did:

image_2024-07-17_114104568.png

1. I made the tgui::TreeView inherit from tgui::ClickableWidget instead of Widget
2. I created to new internal methods for tgui::TreeView

    std::vector<String> TreeView::getItemAtPosition(const Vector2f & position) const
    {
        Vector2f pos(position);
        const float itemHeight = getItemHeight();

        // Adjust position for the scrollbar
        if (m_verticalScrollbar->isShown())
        {
            pos.y += m_verticalScrollbar->getValue();
        }

        std::vector<String> itemPath;
        float currentY = 0;
        findItemAtPosition(m_nodes, pos, itemHeight, currentY, itemPath);
        return itemPath;
    }

    bool TreeView::findItemAtPosition(const std::vector<std::shared_ptr<Node>> &nodes, Vector2f pos, float itemHeight,
        float &currentY, std::vector<String> &path) const
    {
        for (const auto& node : nodes)
        {
            // Check if the current item is at the mouse position
            if (pos.y >= currentY && pos.y < currentY + itemHeight)
            {
                path.push_back(node->text.getString());
                return true;
            }
            currentY += itemHeight;

            // Check children nodes
            if (!node->nodes.empty())
            {
                if (findItemAtPosition(node->nodes, pos, itemHeight, currentY, path))
                {
                    path.insert(path.begin(), node->text.getString()); // Insert parent at the beginning
                    return true;
                }
            }
        }
        return false;
    }

3. Then I modified GuiBuilder.cpp to add:

    m_widgetHierarchyTree->onMousePress([=, this](const tgui::Vector2f& pos) {
        draggingItem = m_widgetHierarchyTree->getItemAtPosition(pos);
        std::cout<<draggingItem.back().toStdString()<<std::endl;
        if(!draggingItem.empty())
        {
            isDragging = true;
        }
    });

    m_widgetHierarchyTree->onMouseRelease([=, this](const tgui::Vector2f& pos) {
       if(isDragging)
       {
           auto targetItem(m_widgetHierarchyTree->getItemAtPosition(pos));
           if(!targetItem.empty())
           {
               targetItem.push_back(draggingItem.back());
               m_widgetHierarchyTree->removeItem(draggingItem);

               m_widgetHierarchyTree->addItem(targetItem);
               isDragging = false;
           }
       }
    });

It only moves move element from the treeview to another branch of it, and it doesn't even work properly, but Its an example of what I'm proposing. Like it said it would be pretty good to have this feature.

texus

I don't have time to look at this now so I only quickly read your post and I haven't read your code yet, but while what you are trying to do sounds like a very useful feature, it is probably not so simple to do properly.

Note that there actually is already a way to change a widget's parent. You can cut the widget, select the new parent and then paste it.

texus

This functionality has been added to the Gui Builder.
You can drag a widget to move it to a different parent or to change the order within the same parent.