From 180c930474eb5b365e2b6cb8403e4150b65330d7 Mon Sep 17 00:00:00 2001 From: Yousef Khadadeh Date: Sat, 20 Dec 2025 16:38:51 +0300 Subject: [PATCH] Started working on tree listing --- CMakeLists.txt | 3 +- data/icons/droparrowclose.svg | 64 +++++++++++ .../NetworkingObjects/NetObjManager.hpp | 8 +- src/BookmarkManager.cpp | 40 ------- src/BookmarkManager.hpp | 47 -------- src/Bookmarks/BookmarkListItem.cpp | 31 ++++-- src/Bookmarks/BookmarkListItem.hpp | 9 +- src/Bookmarks/BookmarkManager.cpp | 55 ++++++++++ src/Bookmarks/BookmarkManager.hpp | 24 +++++ src/GUIStuff/Elements/CheckBox.cpp | 1 - src/GUIStuff/Elements/TreeListing.cpp | 102 ++++++++++++++++++ src/GUIStuff/Elements/TreeListing.hpp | 19 ++++ src/GUIStuff/GUIManager.cpp | 6 ++ src/GUIStuff/GUIManager.hpp | 3 + src/Toolbar.cpp | 59 +--------- src/Toolbar.hpp | 2 - src/World.cpp | 8 +- src/World.hpp | 2 +- 18 files changed, 315 insertions(+), 168 deletions(-) create mode 100644 data/icons/droparrowclose.svg delete mode 100644 src/BookmarkManager.cpp delete mode 100644 src/BookmarkManager.hpp create mode 100644 src/Bookmarks/BookmarkManager.cpp create mode 100644 src/Bookmarks/BookmarkManager.hpp create mode 100644 src/GUIStuff/Elements/TreeListing.cpp create mode 100644 src/GUIStuff/Elements/TreeListing.hpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 851557e..e8af6db 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -48,9 +48,9 @@ set(sources "src/main.cpp" "src/Toolbar.cpp" "src/World.cpp" "src/FileHelpers.cpp" - "src/BookmarkManager.cpp" "src/VersionConstants.cpp" "src/Bookmarks/BookmarkListItem.cpp" + "src/Bookmarks/BookmarkManager.cpp" "src/ResourceDisplay/ResourceDisplay.cpp" "src/ResourceDisplay/SvgResourceDisplay.cpp" "src/ResourceDisplay/ImageResourceDisplay.cpp" @@ -101,6 +101,7 @@ set(sources "src/main.cpp" "src/GUIStuff/Elements/RotateWheel.cpp" "src/GUIStuff/Elements/TextParagraph.cpp" "src/GUIStuff/Elements/FontPicker.cpp" + "src/GUIStuff/Elements/TreeListing.cpp" "include/sago/platform_folders.cpp" "include/Helpers/Networking/NetLibrary.cpp" "include/Helpers/Networking/NetServer.cpp" diff --git a/data/icons/droparrowclose.svg b/data/icons/droparrowclose.svg new file mode 100644 index 0000000..6720237 --- /dev/null +++ b/data/icons/droparrowclose.svg @@ -0,0 +1,64 @@ + + + + + + + + + + + + diff --git a/include/Helpers/NetworkingObjects/NetObjManager.hpp b/include/Helpers/NetworkingObjects/NetObjManager.hpp index 4d0db06..805bb73 100644 --- a/include/Helpers/NetworkingObjects/NetObjManager.hpp +++ b/include/Helpers/NetworkingObjects/NetObjManager.hpp @@ -35,7 +35,7 @@ namespace NetworkingObjects { typeList.get_type_index_data(isServer).readConstructorFunc(NetObjTemporaryPtr(newPtr).template cast(), a, clientReceivedFrom); return newPtr; } - template NetObjTemporaryPtr read_get_obj_ref_from_message(cereal::PortableBinaryInputArchive& a) { + template NetObjTemporaryPtr read_get_obj_temporary_ref_from_message(cereal::PortableBinaryInputArchive& a) { NetObjID id; a(id); auto it = objectData.find(id); @@ -62,12 +62,6 @@ namespace NetworkingObjects { template NetObjOwnerPtr make_obj_from_ptr(T* p) { return emplace_raw_ptr(NetObjID::random_gen(), p); } - template NetObjOwnerPtr get_obj_from_id(NetObjID id) { - auto it = objectData.find(id); - if(it == objectData.end()) - throw std::runtime_error("[NetObjManager::get_obj_from_id] ID doesn't exist"); - return NetObjOwnerPtr(this, id, static_cast(it->second.p)); - } template NetObjTemporaryPtr get_obj_temporary_ref_from_id(NetObjID id) { auto it = objectData.find(id); if(it == objectData.end()) diff --git a/src/BookmarkManager.cpp b/src/BookmarkManager.cpp deleted file mode 100644 index 15ee453..0000000 --- a/src/BookmarkManager.cpp +++ /dev/null @@ -1,40 +0,0 @@ -#include "BookmarkManager.hpp" -#include "Helpers/Networking/NetLibrary.hpp" -#include "Helpers/NetworkingObjects/NetObjOrderedList.hpp" -#include "World.hpp" -#include "MainProgram.hpp" -#include - -void Bookmark::scale_up(const WorldScalar& scaleUpAmount) { - coords.scale_about(WorldVec{0, 0}, scaleUpAmount, true); -} - -BookmarkManager::BookmarkManager(World& w): - world(w) -{} - -void BookmarkManager::init() { - // NOTE: Should find a way for bookmarks added from the network to take into account the client's canvasScale - // Have the canvasScale variable come with the ClientData object, and the grid scale commands can be part of - // the client data class - if(world.netObjMan.is_server()) - bookmarks = world.netObjMan.make_obj>(); -} - -void BookmarkManager::add_bookmark(const std::string& name) { - bookmarks->emplace_back_direct(bookmarks, Bookmark{name, world.drawData.cam.c, world.main.window.size.cast()}); -} - -void BookmarkManager::remove_bookmark(uint32_t bookmarkIndex) { - bookmarks->erase(bookmarks, bookmarkIndex); -} - -void BookmarkManager::jump_to_bookmark(uint32_t bookmarkIndex) { - auto& b = bookmarks->at(bookmarkIndex); - world.drawData.cam.smooth_move_to(world, b->obj->coords, b->obj->windowSize.cast()); -} - -void BookmarkManager::scale_up(const WorldScalar& scaleUpAmount) { - for(uint32_t i = 0; i < bookmarks->size(); i++) - bookmarks->at(i)->obj->scale_up(scaleUpAmount); -} diff --git a/src/BookmarkManager.hpp b/src/BookmarkManager.hpp deleted file mode 100644 index 389a8bd..0000000 --- a/src/BookmarkManager.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#pragma once -#include -#include -#include -#include "SharedTypes.hpp" -#include "CoordSpaceHelper.hpp" - -struct Bookmark { - std::string name; - CoordSpaceHelper coords; - Vector windowSize; - template void serialize(Archive& a) { - a(name, coords, windowSize); - } - void scale_up(const WorldScalar& scaleUpAmount); -}; - -class World; - -class BookmarkManager { - public: - BookmarkManager(World& w); - void init(); - void add_bookmark(const std::string& name); - void remove_bookmark(uint32_t bookmarkIndex); - void jump_to_bookmark(uint32_t bookmarkIndex); - void scale_up(const WorldScalar& scaleUpAmount); - - template void save(Archive& a) const { - a(bookmarks->size()); - for(uint32_t i = 0; i < bookmarks->size(); i++) - a(*bookmarks->at(i)); - } - - template void load(Archive& a) { - uint32_t newSize = bookmarks->size(); - for(uint32_t i = 0; i < newSize; i++) { - Bookmark b; - a(b); - bookmarks->emplace_back_direct(bookmarks, b); - } - } - - NetworkingObjects::NetObjOwnerPtr> bookmarks; - private: - World& world; -}; diff --git a/src/Bookmarks/BookmarkListItem.cpp b/src/Bookmarks/BookmarkListItem.cpp index 6b4a907..83d95cb 100644 --- a/src/Bookmarks/BookmarkListItem.cpp +++ b/src/Bookmarks/BookmarkListItem.cpp @@ -1,20 +1,27 @@ #include "BookmarkListItem.hpp" #include +#include "../World.hpp" using namespace NetworkingObjects; +void BookmarkData::jump_to(World& world) { + world.drawData.cam.smooth_move_to(world, coords, windowSize.cast()); +} + BookmarkListItem::BookmarkListItem() {} BookmarkListItem::BookmarkListItem(NetworkingObjects::NetObjManager& netObjMan, const std::string& initName, bool isFolder, const BookmarkData& initBookmarkData) { name = initName; - if(isFolder) - folderList = netObjMan.make_obj>(); + if(isFolder) { + folderData = std::make_unique(); + folderData->folderList = netObjMan.make_obj>(); + } else bookmarkData = std::make_unique(initBookmarkData); } bool BookmarkListItem::is_folder() const { - return folderList; + return folderData != nullptr; } const BookmarkData& BookmarkListItem::get_bookmark_data() const { @@ -22,13 +29,21 @@ const BookmarkData& BookmarkListItem::get_bookmark_data() const { } const NetObjOwnerPtr>& BookmarkListItem::get_folder_list() const { - return folderList; + return folderData->folderList; } const std::string& BookmarkListItem::get_name() const { return name; } +bool BookmarkListItem::is_folder_open() const { + return folderData->isFolderOpen; +} + +void BookmarkListItem::set_folder_open(bool newIsFolderOpen) { + folderData->isFolderOpen = newIsFolderOpen; +} + void BookmarkListItem::set_name(const NetworkingObjects::NetObjTemporaryPtr& o, const std::string& newName) { o->name = newName; o.send_update_to_all(RELIABLE_COMMAND_CHANNEL, [](const NetObjTemporaryPtr& o, cereal::PortableBinaryOutputArchive& a) { @@ -57,7 +72,7 @@ void BookmarkListItem::register_class(NetObjManager& netObjMan) { void BookmarkListItem::write_constructor_data(const NetObjTemporaryPtr& o, cereal::PortableBinaryOutputArchive& a) { a(o->name, o->is_folder()); if(o->is_folder()) - o->folderList.write_create_message(a); + o->folderData->folderList.write_create_message(a); else a(*o->bookmarkData); } @@ -66,8 +81,10 @@ void BookmarkListItem::read_constructor_data(const NetworkingObjects::NetObjTemp a(o->name); bool isFolder; a(isFolder); - if(isFolder) - o->folderList = o.get_obj_man()->read_create_message>(a, c); + if(isFolder) { + o->folderData = std::make_unique(); + o->folderData->folderList = o.get_obj_man()->read_create_message>(a, c); + } else { o->bookmarkData = std::make_unique(); a(*o->bookmarkData); diff --git a/src/Bookmarks/BookmarkListItem.hpp b/src/Bookmarks/BookmarkListItem.hpp index 9e5e680..8292a29 100644 --- a/src/Bookmarks/BookmarkListItem.hpp +++ b/src/Bookmarks/BookmarkListItem.hpp @@ -10,6 +10,7 @@ struct BookmarkData { template void serialize(Archive& a) { a(coords, windowSize); } + void jump_to(World& world); }; class BookmarkListItem { @@ -19,13 +20,19 @@ class BookmarkListItem { bool is_folder() const; const BookmarkData& get_bookmark_data() const; const NetworkingObjects::NetObjOwnerPtr>& get_folder_list() const; + bool is_folder_open() const; + void set_folder_open(bool newIsFolderOpen); const std::string& get_name() const; static void register_class(NetworkingObjects::NetObjManager& netObjMan); static void set_name(const NetworkingObjects::NetObjTemporaryPtr& o, const std::string& newName); // Set once after editing is finished private: + struct BookmarkFolderData { + NetworkingObjects::NetObjOwnerPtr> folderList; + bool isFolderOpen = false; + }; static void write_constructor_data(const NetworkingObjects::NetObjTemporaryPtr& o, cereal::PortableBinaryOutputArchive& a); static void read_constructor_data(const NetworkingObjects::NetObjTemporaryPtr& o, cereal::PortableBinaryInputArchive& a, const std::shared_ptr& c); - NetworkingObjects::NetObjOwnerPtr> folderList; + std::unique_ptr folderData; std::unique_ptr bookmarkData; std::string name; }; diff --git a/src/Bookmarks/BookmarkManager.cpp b/src/Bookmarks/BookmarkManager.cpp new file mode 100644 index 0000000..7071a20 --- /dev/null +++ b/src/Bookmarks/BookmarkManager.cpp @@ -0,0 +1,55 @@ +#include "BookmarkManager.hpp" +#include "../World.hpp" +#include "../MainProgram.hpp" + +BookmarkManager::BookmarkManager(World& w): + world(w) +{} + +void BookmarkManager::init() { + // NOTE: Should find a way for bookmarks added from the network to take into account the client's canvasScale + // Have the canvasScale variable come with the ClientData object, and the grid scale commands can be part of + // the client data class + if(world.netObjMan.is_server()) { + bookmarkListRoot = world.netObjMan.make_obj_from_ptr(new BookmarkListItem(world.netObjMan, "ROOT", true, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 1", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 2", false, {})); + auto folder1Ptr = bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Folder 1", true, {})); + folder1Ptr->obj->get_folder_list()->push_back_and_send_create(folder1Ptr->obj->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark A", false, {})); + folder1Ptr->obj->get_folder_list()->push_back_and_send_create(folder1Ptr->obj->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark B", false, {})); + folder1Ptr->obj->get_folder_list()->push_back_and_send_create(folder1Ptr->obj->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark C", false, {})); + folder1Ptr->obj->get_folder_list()->push_back_and_send_create(folder1Ptr->obj->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark D", false, {})); + folder1Ptr->obj->get_folder_list()->push_back_and_send_create(folder1Ptr->obj->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark E", false, {})); + auto folderAPtr = folder1Ptr->obj->get_folder_list()->push_back_and_send_create(folder1Ptr->obj->get_folder_list(), new BookmarkListItem(world.netObjMan, "Folder A", true, {})); + folderAPtr->obj->get_folder_list()->push_back_and_send_create(folderAPtr->obj->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 1", false, {})); + folderAPtr->obj->get_folder_list()->push_back_and_send_create(folderAPtr->obj->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 2", false, {})); + folderAPtr->obj->get_folder_list()->push_back_and_send_create(folderAPtr->obj->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 3", false, {})); + folderAPtr->obj->get_folder_list()->push_back_and_send_create(folderAPtr->obj->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 4", false, {})); + folderAPtr->obj->get_folder_list()->push_back_and_send_create(folderAPtr->obj->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 5", false, {})); + folderAPtr->obj->get_folder_list()->push_back_and_send_create(folderAPtr->obj->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 6", false, {})); + folderAPtr->obj->get_folder_list()->push_back_and_send_create(folderAPtr->obj->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 7", false, {})); + folder1Ptr->obj->get_folder_list()->push_back_and_send_create(folder1Ptr->obj->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark F", false, {})); + folder1Ptr->obj->get_folder_list()->push_back_and_send_create(folder1Ptr->obj->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark G", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 3", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 4", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 5", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 6", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 7", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 8", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 9", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 10", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 11", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 12", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 13", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 14", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 15", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 16", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 17", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 18", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 19", false, {})); + bookmarkListRoot->get_folder_list()->push_back_and_send_create(bookmarkListRoot->get_folder_list(), new BookmarkListItem(world.netObjMan, "Bookmark 20", false, {})); + } +} + +void BookmarkManager::scale_up(const WorldScalar& scaleUpAmount) { +} diff --git a/src/Bookmarks/BookmarkManager.hpp b/src/Bookmarks/BookmarkManager.hpp new file mode 100644 index 0000000..15eb674 --- /dev/null +++ b/src/Bookmarks/BookmarkManager.hpp @@ -0,0 +1,24 @@ +#pragma once +#include +#include +#include +#include "BookmarkListItem.hpp" + +class World; + +class BookmarkManager { + public: + BookmarkManager(World& w); + void init(); + void scale_up(const WorldScalar& scaleUpAmount); + + template void save(Archive& a) const { + } + + template void load(Archive& a) { + } + + NetworkingObjects::NetObjOwnerPtr bookmarkListRoot; + private: + World& world; +}; diff --git a/src/GUIStuff/Elements/CheckBox.cpp b/src/GUIStuff/Elements/CheckBox.cpp index c000bf1..565d959 100644 --- a/src/GUIStuff/Elements/CheckBox.cpp +++ b/src/GUIStuff/Elements/CheckBox.cpp @@ -1,7 +1,6 @@ #include "CheckBox.hpp" #include #include -#include namespace GUIStuff { diff --git a/src/GUIStuff/Elements/TreeListing.cpp b/src/GUIStuff/Elements/TreeListing.cpp new file mode 100644 index 0000000..2203ac0 --- /dev/null +++ b/src/GUIStuff/Elements/TreeListing.cpp @@ -0,0 +1,102 @@ +#include "TreeListing.hpp" +#include "../GUIManager.hpp" +#include "Helpers/ConvertVec.hpp" + +constexpr float ENTRY_HEIGHT = 25.0f; + +namespace GUIStuff { + +void TreeListing::update(UpdateInputData& io, GUIManager& gui, const NetworkingObjects::NetObjTemporaryPtr>& bookmarkList) { + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)} + } + }) { + gui.scroll_bar_area("scroll area", true, [&](float scrollContentHeight, float containerHeight, float& scrollAmount) { + size_t itemCount = 0; + size_t itemCountToStartAt = -scrollAmount / ENTRY_HEIGHT; + size_t itemCountToEndAt = (containerHeight - scrollAmount) / ENTRY_HEIGHT; + itemCountToEndAt++; + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(ENTRY_HEIGHT * itemCountToStartAt)} + } + }) {} + recursive_gui(io, gui, bookmarkList, itemCount, itemCountToStartAt, itemCountToEndAt, 0); + if(itemCount > itemCountToEndAt) { + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(ENTRY_HEIGHT * (itemCount - itemCountToEndAt))} + } + }) {} + } + }); + } +} + +void TreeListing::recursive_gui(UpdateInputData& io, GUIManager& gui, const NetworkingObjects::NetObjTemporaryPtr>& bookmarkList, size_t& itemCount, size_t itemCountToStartAt, size_t itemCountToEndAt, size_t listDepth) { + std::optional toDelete; + for(auto& bookmarkItem : bookmarkList->get_data()) { + if(itemCount >= itemCountToStartAt && itemCount < itemCountToEndAt) { + gui.push_id(itemCount); + bool buttonClicked = false; + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(ENTRY_HEIGHT)}, + .childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER} + }, + .backgroundColor = convert_vec4((objSelected.has_value() && objSelected.value() == bookmarkItem->obj.get_net_id()) ? io.theme->backColor1 : io.theme->backColor2), + }) { + if(listDepth != 0) { + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_FIXED(ENTRY_HEIGHT * listDepth), .height = CLAY_SIZING_FIXED(ENTRY_HEIGHT)} + }, + }) {} + } + if(bookmarkItem->obj->is_folder()) { + if(gui.svg_icon_button_transparent("ico", bookmarkItem->obj->is_folder_open() ? "data/icons/droparrow.svg" : "data/icons/droparrowclose.svg", false, ENTRY_HEIGHT)) { + bookmarkItem->obj->set_folder_open(!bookmarkItem->obj->is_folder_open()); + buttonClicked = true; + } + } + else { + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_FIXED(ENTRY_HEIGHT), .height = CLAY_SIZING_FIXED(ENTRY_HEIGHT)}, + .padding = CLAY_PADDING_ALL(2) + } + }) { + gui.svg_icon("ico", "data/icons/bookmark.svg"); + } + } + CLAY_AUTO_ID({ + .layout = { + .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}, + .childAlignment = {.x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER} + } + }) { + gui.text_label(bookmarkItem->obj->get_name()); + } + if(gui.svg_icon_button_transparent("delete", "data/icons/trash.svg", false, ENTRY_HEIGHT)) { + toDelete = bookmarkItem->obj.get_net_id(); + buttonClicked = true; + } + if(Clay_Hovered() && io.mouse.leftClick && !buttonClicked) + objSelected = bookmarkItem->obj.get_net_id(); + } + gui.pop_id(); + } + + itemCount++; + if(bookmarkItem->obj->is_folder() && bookmarkItem->obj->is_folder_open()) + recursive_gui(io, gui, bookmarkItem->obj->get_folder_list(), itemCount, itemCountToStartAt, itemCountToEndAt, listDepth + 1); + } + if(toDelete.has_value()) + bookmarkList->erase(bookmarkList, toDelete.value()); +} + +void TreeListing::clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) { +} + +} diff --git a/src/GUIStuff/Elements/TreeListing.hpp b/src/GUIStuff/Elements/TreeListing.hpp new file mode 100644 index 0000000..5d72805 --- /dev/null +++ b/src/GUIStuff/Elements/TreeListing.hpp @@ -0,0 +1,19 @@ +#pragma once +#include "Element.hpp" +#include "../../Bookmarks/BookmarkListItem.hpp" +#include + +namespace GUIStuff { + +class GUIManager; + +class TreeListing : public Element { + public: + void update(UpdateInputData& io, GUIManager& gui, const NetworkingObjects::NetObjTemporaryPtr>& bookmarkList); + virtual void clay_draw(SkCanvas* canvas, UpdateInputData& io, Clay_RenderCommand* command) override; + private: + void recursive_gui(UpdateInputData& io, GUIManager& gui, const NetworkingObjects::NetObjTemporaryPtr>& bookmarkList, size_t& itemCount, size_t itemCountToStartAt, size_t itemCountToEndAt, size_t listDepth); + std::optional objSelected; +}; + +} diff --git a/src/GUIStuff/GUIManager.cpp b/src/GUIStuff/GUIManager.cpp index 408e0d3..56584ee 100644 --- a/src/GUIStuff/GUIManager.cpp +++ b/src/GUIStuff/GUIManager.cpp @@ -897,6 +897,12 @@ void GUIManager::list_popup_menu(const std::string& id, Vector2f popupPos, const } } +void GUIManager::tree_listing(const std::string& id, const NetworkingObjects::NetObjTemporaryPtr>& bookmarkList) { + push_id(id); + insert_element()->update(*io, *this, bookmarkList); + pop_id(); +} + void GUIManager::obstructing_window() { if(Clay_Hovered()) io->hoverObstructed = true; diff --git a/src/GUIStuff/GUIManager.hpp b/src/GUIStuff/GUIManager.hpp index 43822a8..c15a7f0 100644 --- a/src/GUIStuff/GUIManager.hpp +++ b/src/GUIStuff/GUIManager.hpp @@ -9,6 +9,7 @@ #include "Elements/ColorPicker.hpp" #include "Elements/SelectableButton.hpp" #include "Elements/TextBox.hpp" +#include "Elements/TreeListing.hpp" #include #include "GUIManagerID.hpp" #include @@ -101,6 +102,8 @@ class GUIManager { void paint_circle_popup_menu(const std::string& id, const Vector2f& centerPos, const PaintCircleMenu::Data& val, const std::function& elemUpdate = nullptr); void list_popup_menu(const std::string& id, Vector2f popupPos, const std::function& elemUpdate); + void tree_listing(const std::string& id, const NetworkingObjects::NetObjTemporaryPtr>& bookmarkList); + void obstructing_window(); template NewElement* insert_element() { diff --git a/src/Toolbar.cpp b/src/Toolbar.cpp index 96927c3..a88467c 100644 --- a/src/Toolbar.cpp +++ b/src/Toolbar.cpp @@ -800,65 +800,10 @@ void Toolbar::bookmark_menu(bool justOpened) { .floating = {.offset = {.x = 0, .y = static_cast(io->theme->padding1)}, .attachPoints = {.element = CLAY_ATTACH_POINT_RIGHT_TOP, .parent = CLAY_ATTACH_POINT_RIGHT_BOTTOM}, .attachTo = CLAY_ATTACH_TO_PARENT} }) { gui.obstructing_window(); - float entryHeight = 25.0f; gui.text_label_centered("Bookmarks"); - if(main.world->bMan.bookmarks->empty()) - gui.text_label_centered("No bookmarks yet..."); - uint32_t toDelete = std::numeric_limits::max(); - gui.scroll_bar_many_entries_area("bookmark menu entries", entryHeight, main.world->bMan.bookmarks->size(), true, [&](size_t i, bool isListHovered) { - const Bookmark& bookmark = *main.world->bMan.bookmarks->at(i)->obj; - bool selectedEntry = i == bookMenu.selectedBookmark; - CLAY_AUTO_ID({ - .layout = { - .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_FIXED(entryHeight)}, - .childGap = 2, - .childAlignment = { .x = CLAY_ALIGN_X_LEFT, .y = CLAY_ALIGN_Y_CENTER}, - .layoutDirection = CLAY_LEFT_TO_RIGHT - }, - .backgroundColor = selectedEntry ? convert_vec4(io->theme->backColor1) : convert_vec4(io->theme->backColor2) - }) { - gui.text_label(bookmark.name); - bool miniButtonClicked = false; - CLAY_AUTO_ID({ - .layout = { - .sizing = {.width = CLAY_SIZING_GROW(0), .height = CLAY_SIZING_GROW(0)}, - .childGap = 1, - .childAlignment = {.x = CLAY_ALIGN_X_RIGHT, .y = CLAY_ALIGN_Y_CENTER}, - .layoutDirection = CLAY_LEFT_TO_RIGHT - } - }) { - if(gui.svg_icon_button_transparent("bookmark jump button", "data/icons/jump.svg", false, entryHeight, false)) { - miniButtonClicked = true; - main.world->bMan.jump_to_bookmark(i); - } - if(gui.svg_icon_button_transparent("delete trash", "data/icons/trash.svg", false, entryHeight, false)) { - miniButtonClicked = true; - toDelete = i; - } - } - if(Clay_Hovered() && io->mouse.leftClick && isListHovered && !miniButtonClicked) { - bookMenu.newName = bookmark.name; - bookMenu.selectedBookmark = i; - if(io->mouse.leftClick >= 2) - main.world->bMan.jump_to_bookmark(i); - } - } - }); - if(toDelete != std::numeric_limits::max()) - main.world->bMan.remove_bookmark(toDelete); - gui.left_to_right_line_layout([&]() { - bool addByEnter = false; - gui.input_text("bookmark text input", &bookMenu.newName, true, [&](GUIStuff::SelectionHelper& s) { - addByEnter = s.selected && io->key.enter; - }); - if((gui.svg_icon_button("bookmark add button", "data/icons/plus.svg", false, GUIStuff::GUIManager::SMALL_BUTTON_SIZE) || addByEnter) && !bookMenu.newName.empty()) - main.world->bMan.add_bookmark(bookMenu.newName); - }); - if(io->mouse.leftClick && !Clay_Hovered() && !justOpened) { - bookMenu.newName.clear(); + gui.tree_listing("bookmark listing", main.world->bMan.bookmarkListRoot->get_folder_list()); + if(io->mouse.leftClick && !Clay_Hovered() && !justOpened) bookMenu.popupOpen = false; - bookMenu.selectedBookmark = std::numeric_limits::max(); - } } gui.pop_id(); } diff --git a/src/Toolbar.hpp b/src/Toolbar.hpp index a0810b6..8b17bf3 100644 --- a/src/Toolbar.hpp +++ b/src/Toolbar.hpp @@ -190,8 +190,6 @@ class Toolbar { struct BookmarkMenu { bool popupOpen = false; - std::string newName; - uint32_t selectedBookmark = std::numeric_limits::max(); } bookMenu; struct GridMenu { diff --git a/src/World.cpp b/src/World.cpp index 51f60d3..af6ca1e 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -110,8 +110,8 @@ void World::init_client_data_list_callbacks() { } void World::init_net_obj_type_list() { - NetworkingObjects::register_generic_serialized_class(netObjMan); - NetworkingObjects::register_ordered_list_class(netObjMan); + BookmarkListItem::register_class(netObjMan); + NetworkingObjects::register_ordered_list_class(netObjMan); delayedUpdateObjectManager.register_class(netObjMan); NetworkingObjects::register_ordered_list_class(netObjMan); CanvasComponentAllocator::register_class(*this, netObjMan); @@ -139,7 +139,7 @@ void World::init_server_callbacks() { { cereal::PortableBinaryOutputArchive a(*ss); a(CLIENT_INITIAL_DATA, name, clientDataObjPtr.get_net_id()); - bMan.bookmarks.write_create_message(a); + //bMan.bookmarks.write_create_message(a); gridMan.grids.write_create_message(a); drawProg.write_components_server(a); canvasTheme.write_create_message(a); @@ -170,7 +170,7 @@ void World::init_client_callbacks() { NetworkingObjects::NetObjID clientDataObjID; message(fileDisplayName, clientDataObjID); set_name(fileDisplayName); - bMan.bookmarks = netObjMan.read_create_message>(message, nullptr); + //bMan.bookmarks = netObjMan.read_create_message>(message, nullptr); gridMan.grids = netObjMan.read_create_message>(message, nullptr); drawProg.read_components_client(message); canvasTheme.read_create_message(message); diff --git a/src/World.hpp b/src/World.hpp index b3f315e..b303b51 100644 --- a/src/World.hpp +++ b/src/World.hpp @@ -3,7 +3,7 @@ #include #include "Helpers/NetworkingObjects/NetObjUnorderedSet.hpp" #include "UndoManager.hpp" -#include "BookmarkManager.hpp" +#include "Bookmarks/BookmarkManager.hpp" #include "ResourceManager.hpp" #include "ConnectionManager.hpp" #include "DrawingProgram/DrawingProgram.hpp"