From d81f0668a1f4757b5d02374bdb69d6bb858da4aa Mon Sep 17 00:00:00 2001 From: Goomii <5684215+GoomiiV2@users.noreply.github.com> Date: Sat, 9 Aug 2025 21:07:58 +0100 Subject: [PATCH] feat: Improved usability of the TCP Client/Server tool (#2175) ### Problem description Messages in the TCP tool were only visible as a text string in the messages list and unable to be opened in the hex view. There was also no way to send data other than as a typed in text string in the input field. ### Implementation description * Added the ability to double-click on a message in the messages list to open it in a provider tab. * Added a new button to the client tab to send the current provider to the connected server. * Updated the list look to show the message index in a column ### Screenshots https://github.com/user-attachments/assets/198d78c7-7c94-4f48-ac8c-3581e2ac12e4 --------- Co-authored-by: Nik --- plugins/builtin/romfs/lang/en_US.json | 2 + .../content/tools/tcp_client_server.cpp | 64 ++++++++++++++++++- 2 files changed, 64 insertions(+), 2 deletions(-) diff --git a/plugins/builtin/romfs/lang/en_US.json b/plugins/builtin/romfs/lang/en_US.json index fda92c918..5bbd0fe2e 100644 --- a/plugins/builtin/romfs/lang/en_US.json +++ b/plugins/builtin/romfs/lang/en_US.json @@ -690,6 +690,8 @@ "hex.builtin.tools.tcp_client_server.server": "Server", "hex.builtin.tools.tcp_client_server.messages": "Messages", "hex.builtin.tools.tcp_client_server.settings": "Connection Settings", + "hex.builtin.tools.tcp_client_server.tcp_message": "TCP Message {}", + "hex.builtin.tools.tcp_client_server.send_current_provider": "Send from open data source", "hex.builtin.tools.value": "Value", "hex.builtin.tools.wiki_explain": "Wikipedia term definitions", "hex.builtin.tools.wiki_explain.control": "Control", diff --git a/plugins/builtin/source/content/tools/tcp_client_server.cpp b/plugins/builtin/source/content/tools/tcp_client_server.cpp index 695eab73f..cfd50e83f 100644 --- a/plugins/builtin/source/content/tools/tcp_client_server.cpp +++ b/plugins/builtin/source/content/tools/tcp_client_server.cpp @@ -5,7 +5,10 @@ #include #include +#include #include +#include +#include #include #include @@ -71,19 +74,62 @@ namespace hex::plugin::builtin { } ImGui::PopItemWidth(); + ImGui::SameLine(); + + ImGui::BeginDisabled(!client.isConnected() || !ImHexApi::Provider::isValid()); + { + if (ImGuiExt::IconButton(ICON_VS_SEND, ImGui::GetStyleColorVec4(ImGuiCol_Text))) { + auto provider = ImHexApi::Provider::get(); + if (provider != nullptr) { + std::vector data; + data.resize(provider->getSize()); + provider->readRaw(0, data.data(), provider->getSize()); + client.writeBytes(data); + } + } + if (ImGui::IsItemHovered(ImGuiHoveredFlags_AllowWhenDisabled)) { + if (ImHexApi::Provider::isValid()) { + ImGui::SetTooltip("%s", fmt::format("{} ({})", "hex.builtin.tools.tcp_client_server.send_current_provider"_lang, ImHexApi::Provider::get()->getName()).c_str()); + } + else { + ImGui::SetTooltip("%s", "hex.builtin.tools.tcp_client_server.send_current_provider"_lang.get()); + } + } + } + ImGui::EndDisabled(); + if (port < 1) port = 1; else if (port > 65535) port = 65535; ImGuiExt::Header("hex.builtin.tools.tcp_client_server.messages"_lang); - if (ImGui::BeginTable("##response", 1, ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders, ImVec2(0, 200_scaled))) { + if (ImGui::BeginTable("##response", 2, ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders, ImVec2(0, 200_scaled))) { + ImGui::TableSetupColumn("##ID", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("##Value"); + { std::scoped_lock lock(receiverMutex); + u32 index = 0; for (const auto &message : messages) { ImGui::TableNextRow(); ImGui::TableNextColumn(); + + ImGui::PushID(index); + ImGuiExt::TextFormatted("{}", index); + ImGui::TableNextColumn(); + ImGuiExt::TextFormattedSelectable("{}", message.c_str()); + if (ImGui::TableGetHoveredRow() == (int)index) { + ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, ImGui::GetColorU32(ImGuiCol_Header)); + if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) { + std::vector data(message.begin(), message.end()); + ImHexApi::Provider::add(data, fmt::format("hex.builtin.tools.tcp_client_server.tcp_message"_lang, index)); + } + } + ImGui::PopID(); + + index += 1; } } @@ -166,15 +212,29 @@ namespace hex::plugin::builtin { ImGuiExt::Header("hex.builtin.tools.tcp_client_server.messages"_lang); - if (ImGui::BeginTable("##response", 1, ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders, ImVec2(0, 200_scaled))) { + if (ImGui::BeginTable("##response", 2, ImGuiTableFlags_ScrollY | ImGuiTableFlags_RowBg | ImGuiTableFlags_Borders, ImVec2(0, 200_scaled))) { + ImGui::TableSetupColumn("##ID", ImGuiTableColumnFlags_WidthFixed); + ImGui::TableSetupColumn("##Value"); + { std::scoped_lock lock(receiverMutex); u32 index = 0; for (const auto &message : messages) { ImGui::TableNextRow(); ImGui::TableNextColumn(); + ImGui::PushID(index); + ImGuiExt::TextFormatted("{}", index); + ImGui::TableNextColumn(); + ImGuiExt::TextFormattedSelectable("{}", message.c_str()); + if (ImGui::TableGetHoveredRow() == (int)index) { + ImGui::TableSetBgColor(ImGuiTableBgTarget_RowBg0, ImGui::GetColorU32(ImGuiCol_Header)); + if (ImGui::IsMouseDoubleClicked(ImGuiMouseButton_Left)) { + std::vector data(message.begin(), message.end()); + ImHexApi::Provider::add(data, fmt::format("hex.builtin.tools.tcp_client_server.tcp_message"_lang, index)); + } + } ImGui::PopID(); index += 1;