mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-07-02 02:51:42 +00:00
[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:
@@ -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();
|
||||
|
||||
70
glass/src/lib/native/cpp/other/Log.cpp
Normal file
70
glass/src/lib/native/cpp/other/Log.cpp
Normal 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);
|
||||
}
|
||||
43
glass/src/lib/native/include/glass/other/Log.h
Normal file
43
glass/src/lib/native/include/glass/other/Log.h
Normal 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
|
||||
Reference in New Issue
Block a user