diff --git a/src/backend/lldb/lldb_backend.cpp b/src/backend/lldb/lldb_backend.cpp index 7d9db97..fd71240 100644 --- a/src/backend/lldb/lldb_backend.cpp +++ b/src/backend/lldb/lldb_backend.cpp @@ -2948,7 +2948,7 @@ std::optional if (_var_cache[*cache_entry].used) { // was already diffed - return *cache_entry; + return *_var_cache[*cache_entry].cached_node; } auto node_idx = *_var_cache[*cache_entry].cached_node; _var_cache[*cache_entry].used = true; diff --git a/src/frontend/window.cpp b/src/frontend/window.cpp index 2239f38..9293cf9 100644 --- a/src/frontend/window.cpp +++ b/src/frontend/window.cpp @@ -1025,7 +1025,8 @@ bool WatchWindow::draw(Frontend &frontend) ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); ImGui::PushID("TTTTTT"); - if (ImGui::TreeNodeEx("Locals", ImGuiTreeNodeFlags_SpanFullWidth)) + if (ImGui::TreeNodeEx("Locals", ImGuiTreeNodeFlags_SpanFullWidth + | ImGuiTreeNodeFlags_DefaultOpen)) { auto locals_idx = frontend.target->data_idx_for_src_id(this->locals_src_id); @@ -1064,60 +1065,65 @@ bool WatchWindow::draw(Frontend &frontend) } ImGui::PopID(); - ImGui::TableNextRow(); - ImGui::TableSetColumnIndex(0); - if (ImGui::InputText("##EXTRASLOT", this->extra_slot_path_buf, - sizeof(this->extra_slot_path_buf), - ImGuiInputTextFlags_AutoSelectAll - | ImGuiInputTextFlags_EnterReturnsTrue) - && ImGui::IsItemDeactivatedAfterEdit()) + for (size_t i = 0; i < extra_slots.size(); ++i) { - if (this->extra_slot_bak != this->extra_slot_path_buf) - { - if (this->extra_slot_id) - { - frontend.target->backend->remove_data_node(*this->extra_slot_id); - this->extra_slot_id = {}; - } - this->extra_slot_bak = this->extra_slot_path_buf; - if (this->extra_slot_bak != "") - { - auto id = frontend.target->data_node_id++; - this->extra_slot_id = id; - - using namespace data::source; - frontend.target->backend->add_data_node( - Node{.id = id, - .type = Node::Type::source, - .data = Source{.type = Source::Type::variable, - .data = Source::Variable{ - .expr_path = this->extra_slot_bak}}}); - } - } - } - if (this->extra_slot_id) - { - auto res_idx = frontend.target->data_idx_for_src_id(*this->extra_slot_id); + auto res_idx = frontend.target->data_idx_for_src_id(extra_slots[i].id); if (res_idx) { const auto &node = *frontend.target->data_res_nodes[*res_idx]; if (!node.success || node.children.size() != 1) { + // TODO: allow edit + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + ImGui::Text("%s", extra_slots[i].bak.c_str()); ImGui::TableNextColumn(); ImGui::TextDisabled(""); } else { - //printf("Extratypeid: %u", node.type_id.type); const auto &child_node = *frontend.target->data_res_nodes[node.children[0]]; - //printf("Child: %u\n", child_node.type_id.type); - this->draw_value(frontend, child_node.type_id, this->extra_slot_bak, + this->draw_value(frontend, child_node.type_id, &extra_slots[i], node.children[0], 0); + + if (extra_slots[i].bak == "") + { + frontend.target->backend->remove_data_node(extra_slots[i].id); + extra_slots.erase(extra_slots.begin() + i); + --i; + continue; + } } } } + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + + if (ImGui::InputText("##EXTRASLOT", this->add_slot_buf, + sizeof(this->add_slot_buf), + ImGuiInputTextFlags_AutoSelectAll + | ImGuiInputTextFlags_EnterReturnsTrue) + && ImGui::IsItemDeactivatedAfterEdit()) + { + if (this->add_slot_buf[0] != '\0') + { + auto id = frontend.target->data_node_id++; + using namespace data::source; + frontend.target->backend->add_data_node(Node{ + .id = id, + .type = Node::Type::source, + .data = + Source{.type = Source::Type::variable, + .data = Source::Variable{.expr_path = this->add_slot_buf}}}); + extra_slots.push_back(ExtraSlot{.id = id, .bak = this->add_slot_buf}); + memcpy(extra_slots.back().buf, this->add_slot_buf, + sizeof(this->add_slot_buf)); + this->add_slot_buf[0] = '\0'; + } + } + ImGui::EndTable(); } @@ -1128,15 +1134,26 @@ bool WatchWindow::draw(Frontend &frontend) void WatchWindow::draw_value(Frontend &frontend, data::type_info::TypeID type_id, - std::string_view name, + std::variant name, data::result::NodeIdx node_idx, size_t off) { ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); + const char *name_begin, *name_end; + if (name.index() == 0) + { + name_begin = std::get(name).begin(); + name_end = std::get(name).end(); + } else + { + name_begin = &*std::get(name)->bak.begin(); + name_end = &*std::get(name)->bak.end(); + } + const auto &node_opt = frontend.target->data_res_nodes[node_idx]; if (!node_opt || !node_opt->success) { - ImGui::TextUnformatted(name.begin(), name.end()); + ImGui::TextUnformatted(name_begin, name_end); ImGui::TableNextColumn(); ImGui::TextDisabled(""); return; @@ -1154,26 +1171,89 @@ void WatchWindow::draw_value(Frontend &frontend, auto pop_id = false; if (type_id.type == Type::complex || type_id.type == Type::array) { - ImGui::PushID(name.begin(), name.end()); + ImGui::PushID(name_begin, name_end); pop_id = true; - tree_open = - ImGui::TreeNodeEx((void *)node_idx, ImGuiTreeNodeFlags_SpanFullWidth, - "%.*s", static_cast(name.size()), name.data()); + char tree_id_buf[128]; + std::snprintf(tree_id_buf, sizeof(tree_id_buf), "%u#off%lu", node_idx, off); + auto is_editing = false; + if (name.index() == 1) + { + auto *slot = std::get(name); + if (slot->is_editing) + { + is_editing = true; + ImGui::BeginDisabled(); + tree_open = ImGui::TreeNodeEx(tree_id_buf, 0, ""); + ImGui::EndDisabled(); + ImGui::SameLine(); + if (slot->edit_was_started) + { + slot->edit_was_started = false; + ImGui::SetKeyboardFocusHere(); + } + if (ImGui::InputText("##dddd", slot->buf, sizeof(slot->buf), + ImGuiInputTextFlags_AutoSelectAll + | ImGuiInputTextFlags_EnterReturnsTrue) + && ImGui::IsItemDeactivatedAfterEdit()) + { + if (slot->buf[0] != '\0') + { + frontend.target->backend->remove_data_node(slot->id); + using namespace data::source; + frontend.target->backend->add_data_node( + Node{.id = slot->id, + .type = Node::Type::source, + .data = + Source{.type = Source::Type::variable, + .data = Source::Variable{.expr_path = slot->buf}}}); + } + + slot->bak = slot->buf; + slot->is_editing = false; + } + if (ImGui::IsItemDeactivated()) + { + slot->is_editing = false; + } + } + } + + if (!is_editing) + { + tree_open = + ImGui::TreeNodeEx(tree_id_buf, ImGuiTreeNodeFlags_SpanFullWidth, "%.*s", + static_cast(name_end - name_begin), name_begin); + if (name.index() == 1 + && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) + && ImGui::IsItemHovered()) + { + auto *slot = std::get(name); + slot->is_editing = true; + slot->edit_was_started = true; + } + } if (tree_open) { if (type_id.type == Type::complex) { + char tree_id_buf[128]; const auto &members = frontend.target->types[type_id.idx].member_vec(); for (size_t i = 0; i < members.size(); ++i) { const auto &member = members[i]; if (member.bitfield_size) { + std::snprintf(tree_id_buf, sizeof(tree_id_buf), "%u#member%lu", + node_idx, i); ImGui::TableNextRow(); ImGui::TableSetColumnIndex(0); - ImGui::Text("%s", member.name.c_str()); + ImGui::TreeNodeEx(tree_id_buf, + ImGuiTreeNodeFlags_SpanFullWidth + | ImGuiTreeNodeFlags_Leaf + | ImGuiTreeNodeFlags_NoTreePushOnOpen, + "%s", member.name.c_str()); ImGui::TableNextColumn(); auto member_type = member.type_id; @@ -1259,7 +1339,67 @@ void WatchWindow::draw_value(Frontend &frontend, ImGui::PopID(); } else { - ImGui::TextUnformatted(name.begin(), name.end()); + auto is_editing = false; + if (name.index() == 1) + { + auto *slot = std::get(name); + if (slot->is_editing) + { + is_editing = true; + if (slot->edit_was_started) + { + slot->edit_was_started = false; + ImGui::SetKeyboardFocusHere(); + } + if (ImGui::InputText("##dddd", slot->buf, sizeof(slot->buf), + ImGuiInputTextFlags_AutoSelectAll + | ImGuiInputTextFlags_EnterReturnsTrue) + && ImGui::IsItemDeactivatedAfterEdit()) + { + if (slot->buf[0] != '\0') + { + frontend.target->backend->remove_data_node(slot->id); + using namespace data::source; + frontend.target->backend->add_data_node( + Node{.id = slot->id, + .type = Node::Type::source, + .data = + Source{.type = Source::Type::variable, + .data = Source::Variable{.expr_path = slot->buf}}}); + } + + slot->bak = slot->buf; + slot->is_editing = false; + } + if (ImGui::IsItemDeactivated()) + { + slot->is_editing = false; + } + } + } + + if (!is_editing) + { + char tree_id_buf[128]; + std::snprintf(tree_id_buf, sizeof(tree_id_buf), "%u#off%lu", node_idx, + off); + // TODO: better id + ImGui::TreeNodeEx( + tree_id_buf, + ImGuiTreeNodeFlags_SpanFullWidth | ImGuiTreeNodeFlags_Leaf + | ImGuiTreeNodeFlags_NoTreePushOnOpen, + "%.*s", static_cast(name_end - name_begin), name_begin); + //ImGui::TextUnformatted(name_begin, name_end); + if (name.index() == 1 + && ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left) + && ImGui::IsItemHovered()) + { + auto *slot = std::get(name); + slot->is_editing = true; + slot->edit_was_started = true; + } + } + ImGui::TableSetColumnIndex(1); switch (type_id.type) { diff --git a/src/frontend/window.h b/src/frontend/window.h index 79d90b3..2f0b6d7 100644 --- a/src/frontend/window.h +++ b/src/frontend/window.h @@ -126,8 +126,18 @@ namespace dbgui::frontend struct WatchWindow { + struct ExtraSlot + { + size_t id; + char buf[256]; + std::string bak; + bool is_editing = false; + bool edit_was_started = false; + }; + bool draw(Frontend &); - void draw_value(Frontend &, data::type_info::TypeID, std::string_view name, + void draw_value(Frontend &, data::type_info::TypeID, + std::variant name, data::result::NodeIdx node_idx, size_t off); // void handle_source_updated(Target& target, size_t id); @@ -136,9 +146,9 @@ namespace dbgui::frontend bool first; size_t locals_src_id; - std::optional extra_slot_id; - char extra_slot_path_buf[256] = {0}; - std::string extra_slot_bak = ""; + + std::vector extra_slots; + char add_slot_buf[256] = {}; }; struct Window