diff --git a/windows/logs.cpp b/windows/logs.cpp index 4bae7d7..7a9c62e 100644 --- a/windows/logs.cpp +++ b/windows/logs.cpp @@ -5,33 +5,46 @@ #include "../log.h" #include "logs.h" -static inline void render_table_item(const LogEntry& log_entry, size_t log_entry_index) { +static inline void render_table_item_context_menu(const LogEntry& log_entry) { struct tm tm; char time_as_str[128] = {0}; strftime(time_as_str, 127 * sizeof(char), "%c", localtime_r(&log_entry.time, &tm)); - auto table_item_popup = [&](unsigned char index) { - // is it safe to use the index as a id? i mean, you can't access the clear button when the popup is active - std::string id = std::to_string(log_entry_index * 10 + index); - if (ImGui::BeginPopupContextItem(id.c_str())) { - ImGui::TextDisabled("[%s] %s", time_as_str, log_entry.message.c_str()); - ImGui::Separator(); - ImGui::PushFont(nullptr); - if (ImGui::Selectable("Copy")) ImGui::SetClipboardText(to_string(log_entry).c_str()); - if (ImGui::Selectable("Copy Time")) ImGui::SetClipboardText(time_as_str); - if (ImGui::Selectable("Copy Message")) ImGui::SetClipboardText(log_entry.message.c_str()); + ImGui::TextDisabled("[%s] %s", time_as_str, log_entry.message.c_str()); + ImGui::Separator(); + ImGui::PushFont(nullptr); - ImGui::PopFont(); - ImGui::EndPopup(); + if (ImGui::Selectable("Copy")) ImGui::SetClipboardText(to_string(log_entry).c_str()); + if (ImGui::Selectable("Copy Time")) ImGui::SetClipboardText(time_as_str); + if (ImGui::Selectable("Copy Message")) ImGui::SetClipboardText(log_entry.message.c_str()); + + ImGui::PopFont(); +} + +static inline void render_table_item(const LogEntry& log_entry, size_t log_entry_index, size_t* copying_entry_index) { + auto table_item_popup = [&]() { + bool popup_was_open = ImGui::IsPopupOpen("copy_popup"); + ImGui::OpenPopupOnItemClick("copy_popup"); + if (!popup_was_open) { + *copying_entry_index = log_entry_index; } }; ImGui::TableNextRow(); - if (ImGui::TableSetColumnIndex(0)) { ImGui::TextUnformatted(time_as_str); table_item_popup(0); } - if (ImGui::TableSetColumnIndex(1)) { ImGui::TextUnformatted(log_entry.message); table_item_popup(1); } + if (ImGui::TableSetColumnIndex(0)) { + struct tm tm; + char time_as_str[128] = {0}; + strftime(time_as_str, 127 * sizeof(char), "%c", localtime_r(&log_entry.time, &tm)); + + ImGui::TextUnformatted(time_as_str); + table_item_popup(); + } + if (ImGui::TableSetColumnIndex(1)) { ImGui::TextUnformatted(log_entry.message); table_item_popup(); } } static inline void render_table(ImFont* monospace_font, bool* autoscrolling) { + static size_t copying_entry_index; + ImGui::TableSetupScrollFreeze(0, 1); ImGui::TableSetupColumn("Time", ImGuiTableColumnFlags_None); ImGui::TableSetupColumn("Message", ImGuiTableColumnFlags_None); @@ -47,11 +60,16 @@ static inline void render_table(ImFont* monospace_font, bool* autoscrolling) { assert(i_u >= 0); size_t i = static_cast(i_u); - render_table_item(log_entries[i], i); + render_table_item(log_entries[i], i, ©ing_entry_index); } } clipper.End(); + if (ImGui::BeginPopup("copy_popup")) { + render_table_item_context_menu(log_entries[copying_entry_index]); + ImGui::EndPopup(); + } + ImGui::PopFont(); if (ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) { diff --git a/windows/main.cpp b/windows/main.cpp index d093dfe..b4f8b78 100644 --- a/windows/main.cpp +++ b/windows/main.cpp @@ -8,51 +8,65 @@ #include "../logcat_thread.h" #include "main.h" -static inline void render_table_item(const LogcatEntry& logcat_entry, size_t logcat_entry_index) { - struct tm tm; - char time_as_str[128] = {0}; - strftime(time_as_str, 127 * sizeof(char), "%c", localtime_r(&logcat_entry.time, &tm)); - auto table_item_popup = [&](unsigned char index) { - // is it safe to use the index as a id? i mean, you can't access the clear button when the popup is active - std::string id = std::to_string(logcat_entry_index * 10 + index); - if (ImGui::BeginPopupContextItem(id.c_str())) { - std::string text = to_string(logcat_entry); - ImGui::TextDisabled("%s", text.c_str()); - ImGui::Separator(); - ImGui::PushFont(nullptr); +static inline void render_table_item_context_menu(const LogcatEntry& logcat_entry) { + std::string text = to_string(logcat_entry); + ImGui::TextDisabled("%s", text.c_str()); + ImGui::Separator(); + ImGui::PushFont(nullptr); - if (ImGui::Selectable("Copy")) ImGui::SetClipboardText(text.c_str()); - if (ImGui::Selectable("Copy Time")) ImGui::SetClipboardText(time_as_str); - if (ImGui::Selectable("Copy User", false, logcat_entry.user ? 0 : ImGuiSelectableFlags_Disabled)) { - ImGui::SetClipboardText(logcat_entry.user->c_str()); - } - if (ImGui::Selectable("Copy PID")) ImGui::SetClipboardText(std::to_string(logcat_entry.pid).c_str()); - if (ImGui::Selectable("Copy TID")) ImGui::SetClipboardText(std::to_string(logcat_entry.tid).c_str()); - if (ImGui::Selectable("Copy Buffer")) ImGui::SetClipboardText(to_string(logcat_entry.buffer)); - if (ImGui::Selectable("Copy Priority")) ImGui::SetClipboardText(to_string(logcat_entry.priority)); - if (ImGui::Selectable("Copy Tag")) ImGui::SetClipboardText(logcat_entry.tag.c_str()); - if (ImGui::Selectable("Copy Message")) ImGui::SetClipboardText(logcat_entry.message.c_str()); + if (ImGui::Selectable("Copy")) ImGui::SetClipboardText(text.c_str()); + if (ImGui::Selectable("Copy Time")) { + struct tm tm; + char time_as_str[128] = {0}; + strftime(time_as_str, 127 * sizeof(char), "%c", localtime_r(&logcat_entry.time, &tm)); + ImGui::SetClipboardText(time_as_str); + } + if (ImGui::Selectable("Copy User", false, logcat_entry.user ? 0 : ImGuiSelectableFlags_Disabled)) { + ImGui::SetClipboardText(logcat_entry.user->c_str()); + } + if (ImGui::Selectable("Copy PID")) ImGui::SetClipboardText(std::to_string(logcat_entry.pid).c_str()); + if (ImGui::Selectable("Copy TID")) ImGui::SetClipboardText(std::to_string(logcat_entry.tid).c_str()); + if (ImGui::Selectable("Copy Buffer")) ImGui::SetClipboardText(to_string(logcat_entry.buffer)); + if (ImGui::Selectable("Copy Priority")) ImGui::SetClipboardText(to_string(logcat_entry.priority)); + if (ImGui::Selectable("Copy Tag")) ImGui::SetClipboardText(logcat_entry.tag.c_str()); + if (ImGui::Selectable("Copy Message")) ImGui::SetClipboardText(logcat_entry.message.c_str()); - ImGui::PopFont(); - ImGui::EndPopup(); + ImGui::PopFont(); +} + +static inline void render_table_item(const LogcatEntry& logcat_entry, size_t logcat_entry_index, size_t* copying_entry_index) { + auto table_item_popup = [&]() { + bool popup_was_open = ImGui::IsPopupOpen("copy_popup"); + ImGui::OpenPopupOnItemClick("copy_popup"); + if (!popup_was_open) { + *copying_entry_index = logcat_entry_index; } }; ImGui::TableNextRow(); - if (ImGui::TableSetColumnIndex(0)) { ImGui::TextUnformatted(time_as_str); table_item_popup(0); } + if (ImGui::TableSetColumnIndex(0)) { + struct tm tm; + char time_as_str[128] = {0}; + strftime(time_as_str, 127 * sizeof(char), "%c", localtime_r(&logcat_entry.time, &tm)); + + ImGui::TextUnformatted(time_as_str); + table_item_popup(); + } if (logcat_entry.user && ImGui::TableSetColumnIndex(1)) { ImGui::TextUnformatted(*logcat_entry.user); - table_item_popup(1); + table_item_popup(); } - if (ImGui::TableSetColumnIndex(2)) { ImGui::Text("%zu", logcat_entry.pid); table_item_popup(2); } - if (ImGui::TableSetColumnIndex(3)) { ImGui::Text("%zu", logcat_entry.tid); table_item_popup(3); } - if (ImGui::TableSetColumnIndex(4)) { ImGui::TextUnformatted(to_string(logcat_entry.buffer)); table_item_popup(4); } - if (ImGui::TableSetColumnIndex(5)) { ImGui::TextUnformatted(to_string(logcat_entry.priority)); table_item_popup(5); } - if (ImGui::TableSetColumnIndex(6)) { ImGui::TextUnformatted(logcat_entry.tag); table_item_popup(6); } - if (ImGui::TableSetColumnIndex(7)) { ImGui::TextUnformatted(logcat_entry.message); table_item_popup(7); } + if (ImGui::TableSetColumnIndex(2)) { ImGui::Text("%zu", logcat_entry.pid); table_item_popup(); } + if (ImGui::TableSetColumnIndex(3)) { ImGui::Text("%zu", logcat_entry.tid); table_item_popup(); } + if (ImGui::TableSetColumnIndex(4)) { ImGui::TextUnformatted(to_string(logcat_entry.buffer)); table_item_popup(); } + if (ImGui::TableSetColumnIndex(5)) { ImGui::TextUnformatted(to_string(logcat_entry.priority)); table_item_popup(); } + if (ImGui::TableSetColumnIndex(6)) { ImGui::TextUnformatted(logcat_entry.tag); table_item_popup(); } + if (ImGui::TableSetColumnIndex(7)) { ImGui::TextUnformatted(logcat_entry.message); table_item_popup(); } } static inline void render_table(ImFont* monospace_font, std::vector& logcat_entries, std::vector& filtered_logcat_entry_offsets) { + static size_t copying_entry_index; + ImGui::TableSetupScrollFreeze(0, 1); ImGui::TableSetupColumn("Time", ImGuiTableColumnFlags_None); ImGui::TableSetupColumn("User", ImGuiTableColumnFlags_None); @@ -74,11 +88,16 @@ static inline void render_table(ImFont* monospace_font, std::vector size_t i = static_cast(i_u); size_t logcat_entry_index = filtered_logcat_entry_offsets[i]; - render_table_item(logcat_entries[logcat_entry_index], logcat_entry_index); + render_table_item(logcat_entries[logcat_entry_index], logcat_entry_index, ©ing_entry_index); } } clipper.End(); + if (ImGui::BeginPopup("copy_popup")) { + render_table_item_context_menu(logcat_entries[copying_entry_index]); + ImGui::EndPopup(); + } + ImGui::PopFont(); if (ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) { ImGui::SetScrollHereY(1.0f);