blob: 947ea434a65786b4bd941d93ce1581d55a05d8a3 [file] [log] [blame]
James Kuszmaulb13e13f2023-11-22 20:44:04 -08001// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5#include <cstdio>
6
7#ifndef RUNNING_SYSID_TESTS
8
9#include <filesystem>
10#include <memory>
11#include <string_view>
12
13#include <fmt/format.h>
14#include <glass/Context.h>
15#include <glass/MainMenuBar.h>
16#include <glass/Storage.h>
17#include <glass/Window.h>
18#include <glass/WindowManager.h>
19#include <glass/other/Log.h>
20#include <imgui.h>
21#include <uv.h>
22#include <wpi/Logger.h>
23#include <wpigui.h>
24#include <wpigui_openurl.h>
25
26#include "sysid/view/Analyzer.h"
27#include "sysid/view/JSONConverter.h"
28#include "sysid/view/Logger.h"
29#include "sysid/view/UILayout.h"
30
31namespace gui = wpi::gui;
32
33static std::unique_ptr<glass::WindowManager> gWindowManager;
34
35glass::Window* gLoggerWindow;
36glass::Window* gAnalyzerWindow;
37glass::Window* gProgramLogWindow;
38static glass::MainMenuBar gMainMenu;
39
40std::unique_ptr<sysid::JSONConverter> gJSONConverter;
41
42glass::LogData gLog;
43wpi::Logger gLogger;
44
45const char* GetWPILibVersion();
46
47namespace sysid {
48std::string_view GetResource_sysid_16_png();
49std::string_view GetResource_sysid_32_png();
50std::string_view GetResource_sysid_48_png();
51std::string_view GetResource_sysid_64_png();
52std::string_view GetResource_sysid_128_png();
53std::string_view GetResource_sysid_256_png();
54std::string_view GetResource_sysid_512_png();
55} // namespace sysid
56
57void Application(std::string_view saveDir) {
58 // Create the wpigui (along with Dear ImGui) and Glass contexts.
59 gui::CreateContext();
60 glass::CreateContext();
61
62 // Add icons
63 gui::AddIcon(sysid::GetResource_sysid_16_png());
64 gui::AddIcon(sysid::GetResource_sysid_32_png());
65 gui::AddIcon(sysid::GetResource_sysid_48_png());
66 gui::AddIcon(sysid::GetResource_sysid_64_png());
67 gui::AddIcon(sysid::GetResource_sysid_128_png());
68 gui::AddIcon(sysid::GetResource_sysid_256_png());
69 gui::AddIcon(sysid::GetResource_sysid_512_png());
70
71 glass::SetStorageName("sysid");
72 glass::SetStorageDir(saveDir.empty() ? gui::GetPlatformSaveFileDir()
73 : saveDir);
74
75 // Add messages from the global sysid logger into the Log window.
76 gLogger.SetLogger([](unsigned int level, const char* file, unsigned int line,
77 const char* msg) {
78 const char* lvl = "";
79 if (level >= wpi::WPI_LOG_CRITICAL) {
80 lvl = "CRITICAL: ";
81 } else if (level >= wpi::WPI_LOG_ERROR) {
82 lvl = "ERROR: ";
83 } else if (level >= wpi::WPI_LOG_WARNING) {
84 lvl = "WARNING: ";
85 } else if (level >= wpi::WPI_LOG_INFO) {
86 lvl = "INFO: ";
87 } else if (level >= wpi::WPI_LOG_DEBUG) {
88 lvl = "DEBUG: ";
89 }
90 std::string filename = std::filesystem::path{file}.filename().string();
91 gLog.Append(fmt::format("{}{} ({}:{})\n", lvl, msg, filename, line));
92#ifndef NDEBUG
93 fmt::print(stderr, "{}{} ({}:{})\n", lvl, msg, filename, line);
94#endif
95 });
96
97 gLogger.set_min_level(wpi::WPI_LOG_DEBUG);
98 // Set the number of workers for the libuv threadpool.
99 uv_os_setenv("UV_THREADPOOL_SIZE", "6");
100
101 // Initialize window manager and add views.
102 auto& storage = glass::GetStorageRoot().GetChild("SysId");
103 gWindowManager = std::make_unique<glass::WindowManager>(storage);
104 gWindowManager->GlobalInit();
105
106 gLoggerWindow = gWindowManager->AddWindow(
107 "Logger", std::make_unique<sysid::Logger>(storage, gLogger));
108
109 gAnalyzerWindow = gWindowManager->AddWindow(
110 "Analyzer", std::make_unique<sysid::Analyzer>(storage, gLogger));
111
112 gProgramLogWindow = gWindowManager->AddWindow(
113 "Program Log", std::make_unique<glass::LogView>(&gLog));
114
115 // Set default positions and sizes for windows.
116
117 // Logger window position/size
118 gLoggerWindow->SetDefaultPos(sysid::kLoggerWindowPos.x,
119 sysid::kLoggerWindowPos.y);
120 gLoggerWindow->SetDefaultSize(sysid::kLoggerWindowSize.x,
121 sysid::kLoggerWindowSize.y);
122
123 // Analyzer window position/size
124 gAnalyzerWindow->SetDefaultPos(sysid::kAnalyzerWindowPos.x,
125 sysid::kAnalyzerWindowPos.y);
126 gAnalyzerWindow->SetDefaultSize(sysid::kAnalyzerWindowSize.x,
127 sysid::kAnalyzerWindowSize.y);
128
129 // Program log window position/size
130 gProgramLogWindow->SetDefaultPos(sysid::kProgramLogWindowPos.x,
131 sysid::kProgramLogWindowPos.y);
132 gProgramLogWindow->SetDefaultSize(sysid::kProgramLogWindowSize.x,
133 sysid::kProgramLogWindowSize.y);
134 gProgramLogWindow->DisableRenamePopup();
135
136 gJSONConverter = std::make_unique<sysid::JSONConverter>(gLogger);
137
138 // Configure save file.
139 gui::ConfigurePlatformSaveFile("sysid.ini");
140
141 // Add menu bar.
142 gui::AddLateExecute([] {
143 ImGui::BeginMainMenuBar();
144 gMainMenu.WorkspaceMenu();
145 gui::EmitViewMenu();
146
147 if (ImGui::BeginMenu("Widgets")) {
148 gWindowManager->DisplayMenu();
149 ImGui::EndMenu();
150 }
151
152 bool about = false;
153 if (ImGui::BeginMenu("Info")) {
154 if (ImGui::MenuItem("About")) {
155 about = true;
156 }
157 ImGui::EndMenu();
158 }
159
160 bool toCSV = false;
161 if (ImGui::BeginMenu("JSON Converters")) {
162 if (ImGui::MenuItem("JSON to CSV Converter")) {
163 toCSV = true;
164 }
165
166 ImGui::EndMenu();
167 }
168
169 if (ImGui::BeginMenu("Docs")) {
170 if (ImGui::MenuItem("Online documentation")) {
171 wpi::gui::OpenURL(
172 "https://docs.wpilib.org/en/stable/docs/software/pathplanning/"
173 "system-identification/");
174 }
175
176 ImGui::EndMenu();
177 }
178
179 ImGui::EndMainMenuBar();
180
181 if (toCSV) {
182 ImGui::OpenPopup("SysId JSON to CSV Converter");
183 toCSV = false;
184 }
185
186 if (ImGui::BeginPopupModal("SysId JSON to CSV Converter")) {
187 gJSONConverter->DisplayCSVConvert();
188 if (ImGui::Button("Close")) {
189 ImGui::CloseCurrentPopup();
190 }
191 ImGui::EndPopup();
192 }
193
194 if (about) {
195 ImGui::OpenPopup("About");
196 about = false;
197 }
198 if (ImGui::BeginPopupModal("About")) {
199 ImGui::Text("SysId: System Identification for Robot Mechanisms");
200 ImGui::Separator();
201 ImGui::Text("v%s", GetWPILibVersion());
202 ImGui::Separator();
203 ImGui::Text("Save location: %s", glass::GetStorageDir().c_str());
204 if (ImGui::Button("Close")) {
205 ImGui::CloseCurrentPopup();
206 }
207 ImGui::EndPopup();
208 }
209 });
210
211 gui::Initialize("System Identification", sysid::kAppWindowSize.x,
212 sysid::kAppWindowSize.y);
213 gui::Main();
214
215 glass::DestroyContext();
216 gui::DestroyContext();
217}
218
219#endif