diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index e7d526d..e60289e 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -52,6 +52,23 @@ if (NOT TARGET imgui) #FetchContent_MakeAvailable(imgui) endif() +# TODO: move entt dep into solanaceae_contact +if (NOT TARGET EnTT::EnTT) + FetchContent_Declare(EnTT + GIT_REPOSITORY https://github.com/skypjack/entt.git + GIT_TAG v3.12.2 + ) + FetchContent_MakeAvailable(EnTT) +endif() + +if (NOT TARGET solanaceae_contact) + FetchContent_Declare(solanaceae_contact + GIT_REPOSITORY https://github.com/Green-Sky/solanaceae_contact.git + GIT_TAG master + ) + FetchContent_MakeAvailable(solanaceae_contact) +endif() + if (NOT TARGET solanaceae_plugin) FetchContent_Declare(solanaceae_plugin GIT_REPOSITORY https://github.com/Green-Sky/solanaceae_plugin.git diff --git a/plugins/plugin_crdtnotes_imgui.cpp b/plugins/plugin_crdtnotes_imgui.cpp index 66ee6a8..7337e4b 100644 --- a/plugins/plugin_crdtnotes_imgui.cpp +++ b/plugins/plugin_crdtnotes_imgui.cpp @@ -31,11 +31,13 @@ SOLANA_PLUGIN_EXPORT uint32_t solana_plugin_start(struct SolanaAPI* solana_api) //ConfigModelI* conf = nullptr; CRDTNotes* crdtn = nullptr; + Contact3Registry* cr = nullptr; ImGuiContext* imguic = nullptr; { // make sure required types are loaded //conf = RESOLVE_INSTANCE(ConfigModelI); crdtn = RESOLVE_INSTANCE(CRDTNotes); + cr = RESOLVE_INSTANCE(Contact3Registry); imguic = RESOLVE_INSTANCE(ImGuiContext); //if (conf == nullptr) { @@ -48,6 +50,11 @@ SOLANA_PLUGIN_EXPORT uint32_t solana_plugin_start(struct SolanaAPI* solana_api) return 2; } + if (cr == nullptr) { + std::cerr << "PLUGIN CRDTNIMGUI missing Contact3Registry\n"; + return 2; + } + if (imguic == nullptr) { std::cerr << "PLUGIN CRDTNIMGUI missing ImGuiContext\n"; return 2; @@ -58,7 +65,7 @@ SOLANA_PLUGIN_EXPORT uint32_t solana_plugin_start(struct SolanaAPI* solana_api) // static store, could be anywhere tho // construct with fetched dependencies - g_crdtn_imgui = std::make_unique(*crdtn); + g_crdtn_imgui = std::make_unique(*crdtn, *cr); // register types PROVIDE_INSTANCE(CRDTNotesImGui, "CRDTNotesImGui", g_crdtn_imgui.get()); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d71be19..ab874ae 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -24,6 +24,7 @@ target_link_libraries(solanaceae_crdtnotes_imgui PUBLIC #imgui_interface imgui #solanaceae_util + solanaceae_contact ) ######################################## diff --git a/src/solanaceae/crdtnotes/crdtnotes.hpp b/src/solanaceae/crdtnotes/crdtnotes.hpp index 876f0d1..d1a88ba 100644 --- a/src/solanaceae/crdtnotes/crdtnotes.hpp +++ b/src/solanaceae/crdtnotes/crdtnotes.hpp @@ -28,14 +28,17 @@ struct std::hash { }; class CRDTNotes { - using CRDTAgent = ID32; - using DocID = ID32; - using Doc = GreenCRDT::V3::TextDocument; + public: + using CRDTAgent = ID32; + using DocID = ID32; + using Doc = GreenCRDT::V3::TextDocument; - // TODO: add metadata to docs - std::unordered_map _docs; + private: + // TODO: add metadata to docs + std::unordered_map _docs; public: + // config? CRDTNotes(void); ~CRDTNotes(void); diff --git a/src/solanaceae/crdtnotes_imgui/crdtnotes_imgui.cpp b/src/solanaceae/crdtnotes_imgui/crdtnotes_imgui.cpp index 083eb5f..4ad8e89 100644 --- a/src/solanaceae/crdtnotes_imgui/crdtnotes_imgui.cpp +++ b/src/solanaceae/crdtnotes_imgui/crdtnotes_imgui.cpp @@ -1,8 +1,14 @@ #include "./crdtnotes_imgui.hpp" +#include + #include +#include #include +#include + +#include namespace detail { uint8_t nib_from_hex(char c) { @@ -40,21 +46,101 @@ namespace detail { } // detail -CRDTNotesImGui::CRDTNotesImGui(CRDTNotes& notes) : _notes(notes) { +CRDTNotesImGui::CRDTNotesImGui(CRDTNotes& notes, Contact3Registry& cr) : _notes(notes), _cr(cr) { } float CRDTNotesImGui::render(void) { if (_show_global_list) { - if (ImGui::Begin("CRDTNotes - Global list")) { + if (ImGui::Begin("CRDTNotes")) { + if (ImGui::Button("Create New Doc")) { + ImGui::OpenPopup("create new doc contact"); + } + + if (ImGui::BeginPopup("create new doc contact")) { + for (const auto& c : _cr.view()) { + if (renderContactListContactSmall(c, false)) { + const auto& self = _cr.get(c).self; + + _notes.addDoc( + // tox id (id from self) + {}, + // random 32bytes? + {} + ); + + // and open the doc + } + } + ImGui::EndPopup(); + } + + + ImGui::SeparatorText("Global list"); const auto doclist = _notes.getDocList(); for (const auto& docid : doclist) { const auto docid_str = detail::to_hex(docid); - ImGui::TextUnformatted(docid_str.c_str()); + //ImGui::TextUnformatted(docid_str.c_str()); + if (ImGui::Selectable(docid_str.c_str())) { + // open in editor + _open_docs.emplace(docid); + } } } ImGui::End(); } + { + std::vector to_remove; + for (const auto& docid : _open_docs) { + const std::string docid_str = "Doc " + detail::to_hex(docid); + bool open = true; + + if (ImGui::Begin(docid_str.c_str(), &open)) { + renderDoc(docid); + } + ImGui::End(); + + if (!open) { + to_remove.push_back(docid); + } + } + for (const auto& docid : to_remove) { + _open_docs.erase(docid); + } + } + return 1.f; } +bool CRDTNotesImGui::renderContactListContactSmall(const Contact3 c, const bool selected) const { + std::string label; + + label += (_cr.all_of(c) ? _cr.get(c).name.c_str() : ""); + label += "###"; + label += std::to_string(entt::to_integral(c)); + + return ImGui::Selectable(label.c_str(), selected); +} + +bool CRDTNotesImGui::renderDoc(const CRDTNotes::DocID& doc_id) { + auto* doc = _notes.getDoc(doc_id); + if (doc == nullptr) { + return false; + } + + auto text = doc->getText(); + if (renderDocText(text)) { + auto op_vec = doc->merge(text); + std::cout << "doc changed " << op_vec.size() << " ops generated\n"; + // ... uh? + return true; + } + + return false; +} + +bool CRDTNotesImGui::renderDocText(std::string& text) const { + // TODO: replace with text editor (zep) or visualize stuff?? + return ImGui::InputTextMultiline("##doc", &text, {-1,-1}, ImGuiInputTextFlags_AllowTabInput); +} + diff --git a/src/solanaceae/crdtnotes_imgui/crdtnotes_imgui.hpp b/src/solanaceae/crdtnotes_imgui/crdtnotes_imgui.hpp index 8a6422d..f81884d 100644 --- a/src/solanaceae/crdtnotes_imgui/crdtnotes_imgui.hpp +++ b/src/solanaceae/crdtnotes_imgui/crdtnotes_imgui.hpp @@ -1,15 +1,26 @@ #pragma once #include +#include + +#include class CRDTNotesImGui { CRDTNotes& _notes; + Contact3Registry& _cr; bool _show_global_list {true}; + std::set _open_docs; + public: - CRDTNotesImGui(CRDTNotes& notes); + CRDTNotesImGui(CRDTNotes& notes, Contact3Registry& cr); float render(void); + + bool renderContactListContactSmall(const Contact3 c, const bool selected) const; + + bool renderDoc(const CRDTNotes::DocID& doc_id); + bool renderDocText(std::string& text) const; };