171 lines
4.7 KiB
C++
171 lines
4.7 KiB
C++
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
// Licensed under the MIT License.
|
||
|
|
||
|
// Associated header
|
||
|
//
|
||
|
#include "k4alogdockcontrol.h"
|
||
|
|
||
|
// System headers
|
||
|
//
|
||
|
#include <sstream>
|
||
|
|
||
|
// Library headers
|
||
|
//
|
||
|
|
||
|
// Project headers
|
||
|
//
|
||
|
#include "k4aimguiextensions.h"
|
||
|
|
||
|
using namespace k4aviewer;
|
||
|
|
||
|
namespace
|
||
|
{
|
||
|
// Maximum number of log entries to keep in memory
|
||
|
//
|
||
|
constexpr static size_t MaxLines = 10000;
|
||
|
|
||
|
// clang-format off
|
||
|
|
||
|
// Get a string representation of a log level suitable for printing
|
||
|
// in the log box (fields are fixed-width)
|
||
|
//
|
||
|
const char *LogLevelToString(k4a_log_level_t logLevel)
|
||
|
{
|
||
|
switch(logLevel)
|
||
|
{
|
||
|
case K4A_LOG_LEVEL_CRITICAL: return "critical";
|
||
|
case K4A_LOG_LEVEL_ERROR: return "error ";
|
||
|
case K4A_LOG_LEVEL_WARNING: return "warning ";
|
||
|
case K4A_LOG_LEVEL_INFO: return "info ";
|
||
|
case K4A_LOG_LEVEL_TRACE: return "trace ";
|
||
|
|
||
|
default: return "[unknown]";
|
||
|
}
|
||
|
}
|
||
|
|
||
|
const ImVec4 &LogLevelToColor(k4a_log_level_t logLevel)
|
||
|
{
|
||
|
static const ImVec4 critical = ImVec4(1.f, 0.f, 0.f, 1.f);
|
||
|
static const ImVec4 error = ImVec4(1.f, .3f, 0.f, 1.f);
|
||
|
static const ImVec4 warning = ImVec4(1.f, 1.f, 0.f, 1.f);
|
||
|
static const ImVec4 info = ImVec4(1.f, 1.f, 1.f, 1.f);
|
||
|
static const ImVec4 trace = ImVec4(.5f, .5f, .5f, 1.f);
|
||
|
|
||
|
switch(logLevel)
|
||
|
{
|
||
|
case K4A_LOG_LEVEL_CRITICAL: return critical;
|
||
|
case K4A_LOG_LEVEL_ERROR: return error;
|
||
|
case K4A_LOG_LEVEL_WARNING: return warning;
|
||
|
case K4A_LOG_LEVEL_INFO: return info;
|
||
|
case K4A_LOG_LEVEL_TRACE: return trace;
|
||
|
|
||
|
default: return warning;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// String mappings used for the combo box used to select error levels
|
||
|
//
|
||
|
const std::vector<std::pair<k4a_log_level_t, std::string>> LogLevelLabels = {
|
||
|
{K4A_LOG_LEVEL_CRITICAL, "Critical"},
|
||
|
{K4A_LOG_LEVEL_ERROR, "Error"},
|
||
|
{K4A_LOG_LEVEL_WARNING, "Warning"},
|
||
|
{K4A_LOG_LEVEL_INFO, "Info"},
|
||
|
{K4A_LOG_LEVEL_TRACE, "Trace"}
|
||
|
};
|
||
|
|
||
|
// clang-format on
|
||
|
} // namespace
|
||
|
|
||
|
K4ALogDockControl::K4ALogDockControl() : m_logListener(std::make_shared<LogListener>())
|
||
|
{
|
||
|
K4AViewerLogManager::Instance().RegisterListener(m_logListener);
|
||
|
}
|
||
|
|
||
|
void K4ALogDockControl::LogListener::Log(k4a_log_level_t severity, const char *file, int line, const char *msg)
|
||
|
{
|
||
|
if (severity > m_minSeverity)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||
|
|
||
|
m_entries.emplace_back(severity, file, line, msg);
|
||
|
if (m_entries.size() > MaxLines)
|
||
|
{
|
||
|
m_entries.pop_front();
|
||
|
}
|
||
|
|
||
|
m_updated = true;
|
||
|
}
|
||
|
|
||
|
K4ADockControlStatus K4ALogDockControl::Show()
|
||
|
{
|
||
|
ImGui::BeginGroup();
|
||
|
if (ImGui::Button("Clear Log"))
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(m_logListener->m_mutex);
|
||
|
m_logListener->m_entries.clear();
|
||
|
}
|
||
|
ImGui::SameLine();
|
||
|
const bool copy = ImGui::Button("Copy Log to Clipboard");
|
||
|
|
||
|
m_logListener->m_updated |= ImGuiExtensions::K4AComboBox("Severity",
|
||
|
"",
|
||
|
ImGuiComboFlags_None,
|
||
|
LogLevelLabels,
|
||
|
&m_logListener->m_minSeverity);
|
||
|
m_logListener->m_updated |= ImGui::InputText("Search", &m_filterString[0], m_filterString.size());
|
||
|
m_logListener->m_updated |= ImGui::Checkbox("Show line info", &m_showLineInfo);
|
||
|
ImGui::EndGroup();
|
||
|
|
||
|
ImGui::SameLine();
|
||
|
|
||
|
ImGui::BeginChild("LogTextScrollArea", ImVec2(0, 0), false, ImGuiWindowFlags_HorizontalScrollbar);
|
||
|
|
||
|
if (copy)
|
||
|
{
|
||
|
ImGui::LogToClipboard();
|
||
|
}
|
||
|
|
||
|
bool updated = false;
|
||
|
{
|
||
|
std::lock_guard<std::mutex> lock(m_logListener->m_mutex);
|
||
|
for (const LogEntry &entry : m_logListener->m_entries)
|
||
|
{
|
||
|
std::stringstream lineBuilder;
|
||
|
lineBuilder << "[ " << LogLevelToString(entry.Severity) << " ] ";
|
||
|
|
||
|
if (m_showLineInfo)
|
||
|
{
|
||
|
lineBuilder << "( " << entry.File << ":" << entry.Line << " ) ";
|
||
|
}
|
||
|
|
||
|
lineBuilder << ": " << entry.Msg.c_str();
|
||
|
std::string lineStr = lineBuilder.str();
|
||
|
if (m_filterString[0] != '\0' && lineStr.find(&m_filterString[0]) == std::string::npos)
|
||
|
{
|
||
|
continue;
|
||
|
}
|
||
|
ImGui::TextColored(LogLevelToColor(entry.Severity), "%s", lineStr.c_str());
|
||
|
}
|
||
|
|
||
|
updated = m_logListener->m_updated;
|
||
|
m_logListener->m_updated = false;
|
||
|
}
|
||
|
|
||
|
if (copy)
|
||
|
{
|
||
|
ImGui::LogFinish();
|
||
|
}
|
||
|
|
||
|
if (updated)
|
||
|
{
|
||
|
ImGui::SetScrollHere(1.0f);
|
||
|
}
|
||
|
|
||
|
ImGui::EndChild();
|
||
|
|
||
|
return K4ADockControlStatus::Ok;
|
||
|
}
|