mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-19 00:41:43 +00:00
275 lines
8.0 KiB
C++
275 lines
8.0 KiB
C++
// 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 <memory>
|
|
#include <string>
|
|
|
|
#include <GLFW/glfw3.h>
|
|
#include <fmt/format.h>
|
|
#include <imgui.h>
|
|
|
|
#include "wpi/glass/Context.hpp"
|
|
#include "wpi/glass/MainMenuBar.hpp"
|
|
#include "wpi/glass/Model.hpp"
|
|
#include "wpi/glass/Storage.hpp"
|
|
#include "wpi/glass/networktables/NetworkTables.hpp"
|
|
#include "wpi/glass/networktables/NetworkTablesSettings.hpp"
|
|
#include "wpi/glass/other/Log.hpp"
|
|
#include "wpi/gui/wpigui.hpp"
|
|
#include "wpi/gui/wpigui_openurl.hpp"
|
|
#include "wpi/nt/ntcore_cpp.hpp"
|
|
|
|
namespace gui = wpi::gui;
|
|
|
|
const char* GetWPILibVersion();
|
|
|
|
namespace ov {
|
|
std::string_view GetResource_ov_16_png();
|
|
std::string_view GetResource_ov_32_png();
|
|
std::string_view GetResource_ov_48_png();
|
|
std::string_view GetResource_ov_64_png();
|
|
std::string_view GetResource_ov_128_png();
|
|
std::string_view GetResource_ov_256_png();
|
|
std::string_view GetResource_ov_512_png();
|
|
} // namespace ov
|
|
|
|
static std::unique_ptr<wpi::glass::NetworkTablesModel> gModel;
|
|
static std::unique_ptr<wpi::glass::NetworkTablesSettings> gSettings;
|
|
static wpi::glass::LogData gLog;
|
|
static wpi::glass::NetworkTablesFlagsSettings gFlagsSettings;
|
|
static wpi::glass::MainMenuBar gMainMenu;
|
|
static unsigned int gPrevMode = NT_NET_MODE_NONE;
|
|
|
|
/**
|
|
* Generates the proper title bar title based on current instance state and
|
|
* event.
|
|
*/
|
|
static std::string MakeTitle(NT_Inst inst, wpi::nt::Event event) {
|
|
auto mode = wpi::nt::GetNetworkMode(inst);
|
|
if (mode & NT_NET_MODE_SERVER) {
|
|
auto numClients = wpi::nt::GetConnections(inst).size();
|
|
return fmt::format("OutlineViewer - {} Client{} Connected", numClients,
|
|
(numClients == 1 ? "" : "s"));
|
|
} else if (mode & NT_NET_MODE_CLIENT) {
|
|
if (event.Is(NT_EVENT_CONNECTED)) {
|
|
return fmt::format("OutlineViewer - Connected ({})",
|
|
event.GetConnectionInfo()->remote_ip);
|
|
}
|
|
}
|
|
return "OutlineViewer - DISCONNECTED";
|
|
}
|
|
|
|
static void NtInitialize() {
|
|
auto inst = wpi::nt::GetDefaultInstance();
|
|
auto poller = wpi::nt::CreateListenerPoller(inst);
|
|
wpi::nt::AddPolledListener(poller, inst, NT_EVENT_CONNECTION | NT_EVENT_IMMEDIATE);
|
|
wpi::nt::AddPolledLogger(poller, NT_LOG_INFO, 100);
|
|
gui::AddEarlyExecute([inst, poller] {
|
|
auto win = gui::GetSystemWindow();
|
|
if (!win) {
|
|
return;
|
|
}
|
|
bool updateTitle = false;
|
|
wpi::nt::Event connectionEvent;
|
|
if (wpi::nt::GetNetworkMode(inst) != gPrevMode) {
|
|
gPrevMode = wpi::nt::GetNetworkMode(inst);
|
|
updateTitle = true;
|
|
}
|
|
for (auto&& event : wpi::nt::ReadListenerQueue(poller)) {
|
|
if (event.Is(NT_EVENT_CONNECTION)) {
|
|
updateTitle = true;
|
|
connectionEvent = event;
|
|
} else if (auto msg = event.GetLogMessage()) {
|
|
// handle NetworkTables log messages
|
|
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: ";
|
|
}
|
|
gLog.Append(fmt::format("{}{} ({}:{})\n", level, msg->message,
|
|
msg->filename, msg->line));
|
|
}
|
|
}
|
|
|
|
if (updateTitle) {
|
|
glfwSetWindowTitle(win, MakeTitle(inst, connectionEvent).c_str());
|
|
}
|
|
});
|
|
|
|
// NetworkTables table window
|
|
gModel = std::make_unique<wpi::glass::NetworkTablesModel>();
|
|
gui::AddEarlyExecute([] { gModel->Update(); });
|
|
|
|
// NetworkTables settings window
|
|
gSettings = std::make_unique<wpi::glass::NetworkTablesSettings>(
|
|
"outlineviewer",
|
|
wpi::glass::GetStorageRoot().GetChild("NetworkTables Settings"));
|
|
gui::AddEarlyExecute([] { gSettings->Update(); });
|
|
}
|
|
|
|
static void DisplayGui() {
|
|
ImGui::GetStyle().WindowRounding = 0;
|
|
|
|
// fill entire OS window with this window
|
|
ImGui::SetNextWindowPos(ImVec2(0, 0));
|
|
int width, height;
|
|
glfwGetWindowSize(gui::GetSystemWindow(), &width, &height);
|
|
ImGui::SetNextWindowSize(
|
|
ImVec2(static_cast<float>(width), static_cast<float>(height)));
|
|
|
|
ImGui::Begin("Entries", nullptr,
|
|
ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_MenuBar |
|
|
ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove |
|
|
ImGuiWindowFlags_NoCollapse);
|
|
|
|
gFlagsSettings.Update();
|
|
|
|
// can't create popups from within menu, so use flags
|
|
bool settings = false;
|
|
bool log = false;
|
|
bool about = false;
|
|
|
|
// main menu
|
|
ImGui::BeginMenuBar();
|
|
gMainMenu.WorkspaceMenu();
|
|
gui::EmitViewMenu();
|
|
if (ImGui::BeginMenu("View")) {
|
|
gFlagsSettings.DisplayMenu();
|
|
wpi::glass::DisplayNetworkTablesAddMenu(gModel.get());
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (ImGui::BeginMenu("Options")) {
|
|
if (ImGui::MenuItem("Settings")) {
|
|
settings = true;
|
|
}
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (ImGui::BeginMenu("Info")) {
|
|
if (ImGui::MenuItem("Log")) {
|
|
log = true;
|
|
}
|
|
ImGui::Separator();
|
|
if (ImGui::MenuItem("About")) {
|
|
about = true;
|
|
}
|
|
ImGui::EndMenu();
|
|
}
|
|
|
|
if (ImGui::BeginMenu("Docs")) {
|
|
if (ImGui::MenuItem("Online documentation")) {
|
|
wpi::gui::OpenURL(
|
|
"https://docs.wpilib.org/en/stable/docs/software/wpilib-tools/"
|
|
"outlineviewer/");
|
|
}
|
|
ImGui::EndMenu();
|
|
}
|
|
ImGui::EndMenuBar();
|
|
|
|
// settings popup
|
|
if (settings) {
|
|
ImGui::OpenPopup("Settings");
|
|
}
|
|
if (ImGui::BeginPopupModal("Settings", nullptr,
|
|
ImGuiWindowFlags_AlwaysAutoResize)) {
|
|
if (gSettings->Display()) {
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::SameLine();
|
|
if (ImGui::Button("Cancel")) {
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
|
|
// log popup
|
|
if (log) {
|
|
ImGui::OpenPopup("Log");
|
|
}
|
|
if (ImGui::BeginPopupModal("Log", nullptr,
|
|
ImGuiWindowFlags_AlwaysAutoResize)) {
|
|
if (ImGui::Button("Close")) {
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::BeginChild("Lines", ImVec2(width * 0.75f, height * 0.75f));
|
|
wpi::glass::DisplayLog(&gLog, true);
|
|
ImGui::EndChild();
|
|
ImGui::EndPopup();
|
|
}
|
|
|
|
// about popup
|
|
if (about) {
|
|
ImGui::OpenPopup("About");
|
|
}
|
|
if (ImGui::BeginPopupModal("About", nullptr,
|
|
ImGuiWindowFlags_AlwaysAutoResize)) {
|
|
ImGui::Text("OutlineViewer");
|
|
ImGui::Separator();
|
|
ImGui::Text("v%s", GetWPILibVersion());
|
|
ImGui::Separator();
|
|
ImGui::Text("Save location: %s", wpi::glass::GetStorageDir().c_str());
|
|
ImGui::Text("%.3f ms/frame (%.1f FPS)", 1000.0f / ImGui::GetIO().Framerate,
|
|
ImGui::GetIO().Framerate);
|
|
if (ImGui::Button("Close")) {
|
|
ImGui::CloseCurrentPopup();
|
|
}
|
|
ImGui::EndPopup();
|
|
}
|
|
|
|
// display table view
|
|
wpi::glass::DisplayNetworkTablesInfo(gModel.get());
|
|
ImGui::Separator();
|
|
wpi::glass::DisplayNetworkTables(gModel.get(), gFlagsSettings.GetFlags());
|
|
|
|
ImGui::End();
|
|
}
|
|
|
|
#ifdef _WIN32
|
|
int __stdcall WinMain(void* hInstance, void* hPrevInstance, char* pCmdLine,
|
|
int nCmdShow) {
|
|
int argc = __argc;
|
|
char** argv = __argv;
|
|
#else
|
|
int main(int argc, char** argv) {
|
|
#endif
|
|
std::string_view saveDir;
|
|
if (argc == 2) {
|
|
saveDir = argv[1];
|
|
}
|
|
|
|
gui::CreateContext();
|
|
wpi::glass::CreateContext();
|
|
|
|
gui::AddIcon(ov::GetResource_ov_16_png());
|
|
gui::AddIcon(ov::GetResource_ov_32_png());
|
|
gui::AddIcon(ov::GetResource_ov_48_png());
|
|
gui::AddIcon(ov::GetResource_ov_64_png());
|
|
gui::AddIcon(ov::GetResource_ov_128_png());
|
|
gui::AddIcon(ov::GetResource_ov_256_png());
|
|
gui::AddIcon(ov::GetResource_ov_512_png());
|
|
|
|
wpi::glass::SetStorageName("outlineviewer");
|
|
wpi::glass::SetStorageDir(saveDir.empty() ? gui::GetPlatformSaveFileDir()
|
|
: saveDir);
|
|
|
|
gui::AddInit(NtInitialize);
|
|
|
|
gui::AddLateExecute(DisplayGui);
|
|
|
|
gui::Initialize("OutlineViewer - DISCONNECTED", 600, 400);
|
|
gui::Main();
|
|
|
|
gModel.reset();
|
|
gSettings.reset();
|
|
|
|
wpi::glass::DestroyContext();
|
|
gui::DestroyContext();
|
|
|
|
return 0;
|
|
}
|