From 267a66dd32ab3c5cd0bea1038754e4abb0a537d3 Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Tue, 7 Apr 2026 14:35:34 +0300 Subject: [PATCH] Fixed issues with tree listing element --- src/Bookmarks/BookmarkManager.cpp | 2 +- src/GUIStuff/Elements/TreeListing.cpp | 104 ++++++++++++++++---------- src/GUIStuff/Elements/TreeListing.hpp | 1 + 3 files changed, 67 insertions(+), 40 deletions(-) diff --git a/src/Bookmarks/BookmarkManager.cpp b/src/Bookmarks/BookmarkManager.cpp index d8c7fce..ca33d30 100644 --- a/src/Bookmarks/BookmarkManager.cpp +++ b/src/Bookmarks/BookmarkManager.cpp @@ -443,7 +443,7 @@ NetworkingObjects::NetObjOrderedListIterator BookmarkManager:: } void BookmarkManager::remove_bookmark(const GUIStuff::TreeListingObjIndexList& objIndex) { - editing_bookmark_check(); + refresh_gui_data(); class DeleteBookmarkWorldUndoAction : public WorldUndoAction { public: diff --git a/src/GUIStuff/Elements/TreeListing.cpp b/src/GUIStuff/Elements/TreeListing.cpp index 867137d..07170d3 100644 --- a/src/GUIStuff/Elements/TreeListing.cpp +++ b/src/GUIStuff/Elements/TreeListing.cpp @@ -66,57 +66,65 @@ void TreeListing::layout(const Clay_ElementId& id, const Data& newDisplayData) { else backgroundColor = gui.io.theme->backColor2; - uint16_t borderWidth = (isDragging && i == dragIndexEnd && dragIndexStart != dragIndexEnd) ? 1 : 0; - CLAY(lId, { .layout = { .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}, .childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER} }, - .backgroundColor = convert_vec4(backgroundColor), - .border = { - .color = convert_vec4(gui.io.theme->frontColor1), - .width = { - .left = 0, - .right = 0, - .top = borderWidth, - .bottom = 0, - .betweenChildren = 0 - } - } + .backgroundColor = convert_vec4(backgroundColor) }) { if(objInfo.objIndex.size() > 1) { CLAY_AUTO_ID({ .layout = {.sizing = {.width = CLAY_SIZING_FIXED((objInfo.objIndex.size() - 1) * ICON_SIZE), .height = CLAY_SIZING_GROW(0)}} }) {} } + + uint16_t topBorderWidth = (isDragging && dragFromTop && i == dragIndexEnd && dragIndexStart != dragIndexEnd) ? 1 : 0; + uint16_t bottomBorderWidth = (isDragging && !dragFromTop && i == dragIndexEnd && dragIndexStart != dragIndexEnd) ? 1 : 0; CLAY_AUTO_ID({ - .layout = {.sizing = {.width = CLAY_SIZING_FIXED(ICON_SIZE), .height = CLAY_SIZING_FIXED(ICON_SIZE)}} - }) { - if(!objInfo.isDirectory) - d.drawNonDirectoryObjIconGUI(objInfo.objIndex); - else { - gui.set_z_index_keep_clipping_region(gui.get_z_index() + 1, [&] { - svg_icon_button(gui, "open dir button", objInfo.isOpen ? "data/icons/droparrow.svg" : "data/icons/droparrowclose.svg", { - .drawType = SelectableButton::DrawType::TRANSPARENT_ALL, - .size = ICON_SIZE, - .onClick = [&] { - d.setDirectoryOpen(objInfo.objIndex, !objInfo.isOpen); - if(d.selectedIndices) { - d.selectedIndices->clear(); - if(d.onSelectChange) d.onSelectChange(); - } - } - }); - }); + .layout = { + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}, + .childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER} + }, + .border = { + .color = convert_vec4(gui.io.theme->frontColor1), + .width = { + .left = 0, + .right = 0, + .top = topBorderWidth, + .bottom = bottomBorderWidth, + .betweenChildren = 0 + } } + }) { + CLAY_AUTO_ID({ + .layout = {.sizing = {.width = CLAY_SIZING_FIXED(ICON_SIZE), .height = CLAY_SIZING_FIXED(ICON_SIZE)}} + }) { + if(!objInfo.isDirectory) + d.drawNonDirectoryObjIconGUI(objInfo.objIndex); + else { + gui.set_z_index_keep_clipping_region(gui.get_z_index() + 1, [&] { + svg_icon_button(gui, "open dir button", objInfo.isOpen ? "data/icons/droparrow.svg" : "data/icons/droparrowclose.svg", { + .drawType = SelectableButton::DrawType::TRANSPARENT_ALL, + .size = ICON_SIZE, + .onClick = [&] { + d.setDirectoryOpen(objInfo.objIndex, !objInfo.isOpen); + if(d.selectedIndices) { + d.selectedIndices->clear(); + if(d.onSelectChange) d.onSelectChange(); + } + } + }); + }); + } + } + d.drawObjGUI(objInfo.objIndex); } - d.drawObjGUI(objInfo.objIndex); } }, LayoutElement::Callbacks { .mouseButton = [&, i] (LayoutElement* l, const InputManager::MouseButtonCallbackArgs& button) { if(l->mouseHovering && button.button == InputManager::MouseButton::LEFT && button.down) { - gui.set_post_callback_func([&, i, buttonClicks = button.clicks]{ + gui.set_post_callback_func([&, i, button, l]{ auto& objIndex = flattenedIndexList[i].objIndex; if(d.selectedIndices) { auto it = d.selectedIndices->find(objIndex); @@ -135,11 +143,11 @@ void TreeListing::layout(const Clay_ElementId& id, const Data& newDisplayData) { d.selectedIndices->erase(it); if(d.onSelectChange) d.onSelectChange(); } - else if(buttonClicks == 2) { + else if(button.clicks == 2) { if(d.onDoubleClick) d.onDoubleClick(objIndex); } else { - if(buttonClicks == 2 && d.onDoubleClick) d.onDoubleClick(objIndex); + if(button.clicks == 2 && d.onDoubleClick) d.onDoubleClick(objIndex); if(!wasSelected) { d.selectedIndices->clear(); d.selectedIndices->emplace(objIndex); @@ -147,18 +155,24 @@ void TreeListing::layout(const Clay_ElementId& id, const Data& newDisplayData) { } isDragging = true; dragIndexStart = dragIndexEnd = i; + dragFromTop = button.pos.y() - l->get_bb().value().min.y() < ENTRY_HEIGHT * 0.5f; } } - else if(buttonClicks == 2) + else if(button.clicks == 2) if(d.onDoubleClick) d.onDoubleClick(objIndex); }); gui.set_to_layout(); } }, .mouseMotion = [&, i] (LayoutElement* l, const InputManager::MouseMotionCallbackArgs& motion) { - if(isDragging && l->mouseHovering && dragIndexEnd != i) { - dragIndexEnd = i; - gui.set_to_layout(); + if(isDragging && l->mouseHovering) { + size_t newDragIndexEnd = i; + bool newDragFromTop = motion.pos.y() - l->get_bb().value().min.y() < ENTRY_HEIGHT * 0.5f; + if(dragIndexEnd != newDragIndexEnd || dragFromTop != newDragFromTop) { + dragIndexEnd = newDragIndexEnd; + dragFromTop = newDragFromTop; + gui.set_to_layout(); + } } } }); @@ -194,6 +208,18 @@ void TreeListing::layout(const Clay_ElementId& id, const Data& newDisplayData) { void TreeListing::move_selected_objects() { if(d.selectedIndices && dragIndexEnd < flattenedIndexList.size()) { TreeListingObjIndexList objIndexToMoveTo = flattenedIndexList[dragIndexEnd].objIndex; + if(!dragFromTop) { + if(flattenedIndexList[dragIndexEnd].isOpen) // Drag into open directory + objIndexToMoveTo.emplace_back(0); + else { + objIndexToMoveTo.back() += 1; + if(dragIndexStart < flattenedIndexList.size()) { + if(objIndexToMoveTo == flattenedIndexList[dragIndexStart].objIndex) + objIndexToMoveTo.back() += 1; + } + } + } + // Check if object is about to move into itself (wrong movement) bool wrongMovement = false; for(const TreeListingObjIndexList& o : *d.selectedIndices) { diff --git a/src/GUIStuff/Elements/TreeListing.hpp b/src/GUIStuff/Elements/TreeListing.hpp index f5da59d..52e4f86 100644 --- a/src/GUIStuff/Elements/TreeListing.hpp +++ b/src/GUIStuff/Elements/TreeListing.hpp @@ -51,6 +51,7 @@ class TreeListing : public Element { bool isDragging = false; size_t dragIndexStart; size_t dragIndexEnd; + bool dragFromTop; std::vector flattenedIndexList; Data d;