[glass] Add NetworkTables Log window (#2997)

This moves NetworkTable log messages out of the console (which is hidden on some platforms).
This commit is contained in:
Peter Johnson
2020-12-29 20:47:58 -08:00
committed by GitHub
parent 66782e2317
commit 560a850a2b
3 changed files with 149 additions and 0 deletions

View File

@@ -16,6 +16,7 @@
#include "glass/View.h"
#include "glass/networktables/NetworkTables.h"
#include "glass/networktables/NetworkTablesProvider.h"
#include "glass/other/Log.h"
#include "glass/other/Plot.h"
namespace gui = wpi::gui;
@@ -35,8 +36,10 @@ static std::unique_ptr<glass::NetworkTablesProvider> gNtProvider;
static std::unique_ptr<glass::NetworkTablesModel> gNetworkTablesModel;
static std::unique_ptr<NetworkTablesSettings> gNetworkTablesSettings;
static glass::LogData gNetworkTablesLog;
static glass::Window* gNetworkTablesWindow;
static glass::Window* gNetworkTablesSettingsWindow;
static glass::Window* gNetworkTablesLogWindow;
static void NtInitialize() {
// update window title when connection status changes
@@ -62,6 +65,36 @@ static void NtInitialize() {
}
});
// handle NetworkTables log messages
auto logPoller = nt::CreateLoggerPoller(inst);
nt::AddPolledLogger(logPoller, NT_LOG_INFO, 100);
gui::AddEarlyExecute([logPoller] {
bool timedOut;
for (auto&& msg : nt::PollLogger(logPoller, 0, &timedOut)) {
const char* level = "";
if (msg.level >= NT_LOG_CRITICAL) {
level = "CRITICAL: ";
} else if (msg.level >= NT_LOG_ERROR) {
level = "ERROR: ";
} else if (msg.level >= NT_LOG_WARNING) {
level = "WARNING: ";
}
gNetworkTablesLog.Append(
wpi::Twine{level} + msg.message + wpi::Twine{" ("} + msg.filename +
wpi::Twine{':'} + wpi::Twine{msg.line} + wpi::Twine{")\n"});
}
});
gNetworkTablesLogWindow = gNtProvider->AddWindow(
"NetworkTables Log",
std::make_unique<glass::LogView>(&gNetworkTablesLog));
if (gNetworkTablesLogWindow) {
gNetworkTablesLogWindow->SetDefaultPos(250, 615);
gNetworkTablesLogWindow->SetDefaultSize(600, 130);
gNetworkTablesLogWindow->SetVisible(false);
gNetworkTablesLogWindow->DisableRenamePopup();
}
// NetworkTables table window
gNetworkTablesModel = std::make_unique<glass::NetworkTablesModel>();
gui::AddEarlyExecute([] { gNetworkTablesModel->Update(); });
@@ -132,6 +165,9 @@ int main() {
if (gNetworkTablesWindow) {
gNetworkTablesWindow->DisplayMenuItem("NetworkTables View");
}
if (gNetworkTablesLogWindow) {
gNetworkTablesLogWindow->DisplayMenuItem("NetworkTables Log");
}
ImGui::Separator();
gNtProvider->DisplayMenu();
ImGui::EndMenu();

View File

@@ -0,0 +1,70 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#include "glass/other/Log.h"
#include <imgui.h>
#include <wpi/raw_ostream.h>
using namespace glass;
void LogData::Clear() {
m_buf.clear();
m_lineOffsets.clear();
m_lineOffsets.push_back(0);
}
void LogData::Append(const wpi::Twine& msg) {
if (m_lineOffsets.size() >= m_maxLines) {
Clear();
}
size_t oldSize = m_buf.size();
wpi::raw_vector_ostream os{m_buf};
msg.print(os);
for (size_t newSize = m_buf.size(); oldSize < newSize; ++oldSize) {
if (m_buf[oldSize] == '\n') {
m_lineOffsets.push_back(oldSize + 1);
}
}
}
void glass::DisplayLog(LogData* data, bool autoScroll) {
if (data->m_buf.empty()) {
return;
}
ImGui::PushStyleVar(ImGuiStyleVar_ItemSpacing, ImVec2(0, 0));
const char* buf = data->m_buf.data();
const char* bufEnd = buf + data->m_buf.size();
ImGuiListClipper clipper;
clipper.Begin(data->m_lineOffsets.size());
while (clipper.Step()) {
for (size_t lineNum = clipper.DisplayStart;
lineNum < static_cast<size_t>(clipper.DisplayEnd); lineNum++) {
const char* lineStart = buf + data->m_lineOffsets[lineNum];
const char* lineEnd = (lineNum + 1 < data->m_lineOffsets.size())
? (buf + data->m_lineOffsets[lineNum + 1] - 1)
: bufEnd;
ImGui::TextUnformatted(lineStart, lineEnd);
}
}
clipper.End();
ImGui::PopStyleVar();
if (autoScroll && ImGui::GetScrollY() >= ImGui::GetScrollMaxY()) {
ImGui::SetScrollHereY(1.0f);
}
}
void LogView::Display() {
if (ImGui::BeginPopupContextItem()) {
ImGui::Checkbox("Auto-scroll", &m_autoScroll);
if (ImGui::Selectable("Clear")) {
m_data->Clear();
}
ImGui::EndPopup();
}
DisplayLog(m_data, m_autoScroll);
}

View File

@@ -0,0 +1,43 @@
// Copyright (c) FIRST and other WPILib contributors.
// Open Source Software; you can modify and/or share it under the terms of
// the WPILib BSD license file in the root directory of this project.
#pragma once
#include <vector>
#include <wpi/Twine.h>
#include "glass/View.h"
namespace glass {
class LogData {
friend void DisplayLog(LogData*, bool);
public:
explicit LogData(size_t maxLines = 10000) : m_maxLines{maxLines} {}
void Clear();
void Append(const wpi::Twine& msg);
private:
size_t m_maxLines;
std::vector<char> m_buf;
std::vector<size_t> m_lineOffsets{0};
};
void DisplayLog(LogData* data, bool autoScroll);
class LogView : public View {
public:
explicit LogView(LogData* data) : m_data{data} {}
void Display() override;
private:
LogData* m_data;
bool m_autoScroll{true};
};
} // namespace glass