2023-12-31 14:25:56 +01:00

155 lines
3.7 KiB
C++

#include "./crdtnotes_imgui.hpp"
#include <solanaceae/contact/components.hpp>
#include <cstdint>
#include <vector>
#include <imgui.h>
#include <misc/cpp/imgui_stdlib.h>
#include <iostream>
#include <cassert>
namespace detail {
uint8_t nib_from_hex(char c) {
assert((c >= '0' && c <= '9') || (c >= 'a' && c <= 'f'));
if (c >= '0' && c <= '9') {
return static_cast<uint8_t>(c) - '0';
} else if (c >= 'a' && c <= 'f') {
return (static_cast<uint8_t>(c) - 'a') + 10u;
} else {
return 0u;
}
}
char nib_to_hex(uint8_t c) {
assert((c & 0xf0) == 0x00);
if (/*c >= 0x00 &&*/ c <= 0x09) {
return static_cast<char>(c) + '0';
} else if (c >= 0x0a && c <= 0x0f) {
return (static_cast<char>(c) + 'a') - 10u;
} else {
return 0u;
}
}
template<typename Container>
std::string to_hex(const Container& data) {
std::string res;
for (const uint8_t it : data) {
res += nib_to_hex(it >> 4);
res += nib_to_hex(it & 0x0f);
}
return res;
}
} // detail
CRDTNotesImGui::CRDTNotesImGui(CRDTNotesSync& notes_sync, Contact3Registry& cr) : _notes_sync(notes_sync), _cr(cr) {
}
float CRDTNotesImGui::render(void) {
if (_show_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<Contact::Components::TagBig>()) {
if (renderContactListContactSmall(c, false)) {
//const auto& self = _cr.get<Contact::Components::Self>(c).self;
//assert(_cr.all_of<Contact::Components::ID>(self));
//const auto& self_id = _cr.get<Contact::Components::ID>(self);
//assert(!self_id.data.empty());
//CRDTNotes::CRDTAgent self_agent_id;
//// at most agent size, up to self id size
//for (size_t i = 0; i < self_agent_id.size() && i < self_id.data.size(); i++) {
//self_agent_id.at(i) = self_id.data.at(i);
//}
//_notes.addDoc(
//// tox id (id from self)
//self_agent_id
//);
_notes_sync.addNewDoc({_cr, c}, false);
//// and open the doc
}
}
ImGui::EndPopup();
}
ImGui::SeparatorText("Global list");
const auto doclist = _notes_sync.getDocList();
for (const auto& docid : doclist) {
const auto docid_str = detail::to_hex(docid);
//ImGui::TextUnformatted(docid_str.c_str());
if (ImGui::Selectable(docid_str.c_str())) {
// open in editor
_open_docs.emplace(docid);
}
}
}
ImGui::End();
}
{
std::vector<CRDTNotes::DocID> 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<Contact::Components::Name>(c) ? _cr.get<Contact::Components::Name>(c).name.c_str() : "<unk>");
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_sync.getDoc(doc_id);
if (doc == nullptr) {
return false;
}
auto text = doc->getText();
if (renderDocText(text)) {
_notes_sync.merge(doc_id, text);
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);
}