blob: b1569b836cbb2d38ef466a37e3721bde1010d400 [file] [log] [blame]
Austin Schuh812d0d12021-11-04 20:16:48 -07001// 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 <memory>
6
7#include <GLFW/glfw3.h>
8#include <fmt/format.h>
9#include <imgui.h>
10#include <ntcore_cpp.h>
11#include <wpigui.h>
12
13#include "glass/Context.h"
Austin Schuh75263e32022-02-22 18:05:32 -080014#include "glass/MainMenuBar.h"
Austin Schuh812d0d12021-11-04 20:16:48 -070015#include "glass/Model.h"
Austin Schuh75263e32022-02-22 18:05:32 -080016#include "glass/Storage.h"
Austin Schuh812d0d12021-11-04 20:16:48 -070017#include "glass/View.h"
18#include "glass/networktables/NetworkTables.h"
19#include "glass/networktables/NetworkTablesProvider.h"
20#include "glass/networktables/NetworkTablesSettings.h"
21#include "glass/other/Log.h"
22#include "glass/other/Plot.h"
23
24namespace gui = wpi::gui;
25
26const char* GetWPILibVersion();
27
28namespace glass {
29std::string_view GetResource_glass_16_png();
30std::string_view GetResource_glass_32_png();
31std::string_view GetResource_glass_48_png();
32std::string_view GetResource_glass_64_png();
33std::string_view GetResource_glass_128_png();
34std::string_view GetResource_glass_256_png();
35std::string_view GetResource_glass_512_png();
36} // namespace glass
37
38static std::unique_ptr<glass::PlotProvider> gPlotProvider;
39static std::unique_ptr<glass::NetworkTablesProvider> gNtProvider;
40
41static std::unique_ptr<glass::NetworkTablesModel> gNetworkTablesModel;
42static std::unique_ptr<glass::NetworkTablesSettings> gNetworkTablesSettings;
43static glass::LogData gNetworkTablesLog;
Austin Schuh75263e32022-02-22 18:05:32 -080044static std::unique_ptr<glass::Window> gNetworkTablesWindow;
45static std::unique_ptr<glass::Window> gNetworkTablesSettingsWindow;
46static std::unique_ptr<glass::Window> gNetworkTablesLogWindow;
47
48static glass::MainMenuBar gMainMenu;
49static bool gAbout = false;
50static bool gSetEnterKey = false;
51static bool gKeyEdit = false;
Austin Schuh812d0d12021-11-04 20:16:48 -070052
53static void NtInitialize() {
54 // update window title when connection status changes
55 auto inst = nt::GetDefaultInstance();
56 auto poller = nt::CreateConnectionListenerPoller(inst);
57 nt::AddPolledConnectionListener(poller, true);
58 gui::AddEarlyExecute([poller] {
59 auto win = gui::GetSystemWindow();
60 if (!win) {
61 return;
62 }
63 bool timedOut;
64 for (auto&& event : nt::PollConnectionListener(poller, 0, &timedOut)) {
65 if (event.connected) {
66 glfwSetWindowTitle(
67 win, fmt::format("Glass - Connected ({})", event.conn.remote_ip)
68 .c_str());
69 } else {
70 glfwSetWindowTitle(win, "Glass - DISCONNECTED");
71 }
72 }
73 });
74
75 // handle NetworkTables log messages
76 auto logPoller = nt::CreateLoggerPoller(inst);
77 nt::AddPolledLogger(logPoller, NT_LOG_INFO, 100);
78 gui::AddEarlyExecute([logPoller] {
79 bool timedOut;
80 for (auto&& msg : nt::PollLogger(logPoller, 0, &timedOut)) {
81 const char* level = "";
82 if (msg.level >= NT_LOG_CRITICAL) {
83 level = "CRITICAL: ";
84 } else if (msg.level >= NT_LOG_ERROR) {
85 level = "ERROR: ";
86 } else if (msg.level >= NT_LOG_WARNING) {
87 level = "WARNING: ";
88 }
89 gNetworkTablesLog.Append(fmt::format("{}{} ({}:{})\n", level, msg.message,
90 msg.filename, msg.line));
91 }
92 });
93
Austin Schuh75263e32022-02-22 18:05:32 -080094 gNetworkTablesLogWindow = std::make_unique<glass::Window>(
95 glass::GetStorageRoot().GetChild("NetworkTables Log"),
96 "NetworkTables Log", glass::Window::kHide);
97 gNetworkTablesLogWindow->SetView(
Austin Schuh812d0d12021-11-04 20:16:48 -070098 std::make_unique<glass::LogView>(&gNetworkTablesLog));
Austin Schuh75263e32022-02-22 18:05:32 -080099 gNetworkTablesLogWindow->SetDefaultPos(250, 615);
100 gNetworkTablesLogWindow->SetDefaultSize(600, 130);
101 gNetworkTablesLogWindow->DisableRenamePopup();
102 gui::AddLateExecute([] { gNetworkTablesLogWindow->Display(); });
Austin Schuh812d0d12021-11-04 20:16:48 -0700103
104 // NetworkTables table window
105 gNetworkTablesModel = std::make_unique<glass::NetworkTablesModel>();
106 gui::AddEarlyExecute([] { gNetworkTablesModel->Update(); });
107
Austin Schuh75263e32022-02-22 18:05:32 -0800108 gNetworkTablesWindow = std::make_unique<glass::Window>(
109 glass::GetStorageRoot().GetChild("NetworkTables View"), "NetworkTables");
110 gNetworkTablesWindow->SetView(
Austin Schuh812d0d12021-11-04 20:16:48 -0700111 std::make_unique<glass::NetworkTablesView>(gNetworkTablesModel.get()));
Austin Schuh75263e32022-02-22 18:05:32 -0800112 gNetworkTablesWindow->SetDefaultPos(250, 277);
113 gNetworkTablesWindow->SetDefaultSize(750, 185);
114 gNetworkTablesWindow->DisableRenamePopup();
115 gui::AddLateExecute([] { gNetworkTablesWindow->Display(); });
Austin Schuh812d0d12021-11-04 20:16:48 -0700116
117 // NetworkTables settings window
Austin Schuh75263e32022-02-22 18:05:32 -0800118 gNetworkTablesSettings = std::make_unique<glass::NetworkTablesSettings>(
119 glass::GetStorageRoot().GetChild("NetworkTables Settings"));
Austin Schuh812d0d12021-11-04 20:16:48 -0700120 gui::AddEarlyExecute([] { gNetworkTablesSettings->Update(); });
121
Austin Schuh75263e32022-02-22 18:05:32 -0800122 gNetworkTablesSettingsWindow = std::make_unique<glass::Window>(
123 glass::GetStorageRoot().GetChild("NetworkTables Settings"),
124 "NetworkTables Settings");
125 gNetworkTablesSettingsWindow->SetView(
126 glass::MakeFunctionView([] { gNetworkTablesSettings->Display(); }));
127 gNetworkTablesSettingsWindow->SetDefaultPos(30, 30);
128 gNetworkTablesSettingsWindow->SetFlags(ImGuiWindowFlags_AlwaysAutoResize);
129 gNetworkTablesSettingsWindow->DisableRenamePopup();
130 gui::AddLateExecute([] { gNetworkTablesSettingsWindow->Display(); });
131
132 gui::AddWindowScaler([](float scale) {
133 // scale default window positions
134 gNetworkTablesLogWindow->ScaleDefault(scale);
135 gNetworkTablesWindow->ScaleDefault(scale);
136 gNetworkTablesSettingsWindow->ScaleDefault(scale);
137 });
Austin Schuh812d0d12021-11-04 20:16:48 -0700138}
139
140#ifdef _WIN32
141int __stdcall WinMain(void* hInstance, void* hPrevInstance, char* pCmdLine,
142 int nCmdShow) {
Austin Schuh75263e32022-02-22 18:05:32 -0800143 int argc = __argc;
144 char** argv = __argv;
Austin Schuh812d0d12021-11-04 20:16:48 -0700145#else
Austin Schuh75263e32022-02-22 18:05:32 -0800146int main(int argc, char** argv) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700147#endif
Austin Schuh75263e32022-02-22 18:05:32 -0800148 std::string_view saveDir;
149 if (argc == 2) {
150 saveDir = argv[1];
151 }
152
Austin Schuh812d0d12021-11-04 20:16:48 -0700153 gui::CreateContext();
154 glass::CreateContext();
155
156 gui::AddIcon(glass::GetResource_glass_16_png());
157 gui::AddIcon(glass::GetResource_glass_32_png());
158 gui::AddIcon(glass::GetResource_glass_48_png());
159 gui::AddIcon(glass::GetResource_glass_64_png());
160 gui::AddIcon(glass::GetResource_glass_128_png());
161 gui::AddIcon(glass::GetResource_glass_256_png());
162 gui::AddIcon(glass::GetResource_glass_512_png());
163
Austin Schuh75263e32022-02-22 18:05:32 -0800164 gPlotProvider = std::make_unique<glass::PlotProvider>(
165 glass::GetStorageRoot().GetChild("Plots"));
166 gNtProvider = std::make_unique<glass::NetworkTablesProvider>(
167 glass::GetStorageRoot().GetChild("NetworkTables"));
Austin Schuh812d0d12021-11-04 20:16:48 -0700168
Austin Schuh75263e32022-02-22 18:05:32 -0800169 glass::SetStorageName("glass");
170 glass::SetStorageDir(saveDir.empty() ? gui::GetPlatformSaveFileDir()
171 : saveDir);
Austin Schuh812d0d12021-11-04 20:16:48 -0700172 gPlotProvider->GlobalInit();
173 gui::AddInit([] { glass::ResetTime(); });
174 gNtProvider->GlobalInit();
Austin Schuh75263e32022-02-22 18:05:32 -0800175 NtInitialize();
Austin Schuh812d0d12021-11-04 20:16:48 -0700176
177 glass::AddStandardNetworkTablesViews(*gNtProvider);
178
Austin Schuh75263e32022-02-22 18:05:32 -0800179 gui::AddLateExecute([] { gMainMenu.Display(); });
180
181 gMainMenu.AddMainMenu([] {
Austin Schuh812d0d12021-11-04 20:16:48 -0700182 if (ImGui::BeginMenu("View")) {
Austin Schuh75263e32022-02-22 18:05:32 -0800183 if (ImGui::MenuItem("Set Enter Key")) {
184 gSetEnterKey = true;
185 }
Austin Schuh812d0d12021-11-04 20:16:48 -0700186 if (ImGui::MenuItem("Reset Time")) {
187 glass::ResetTime();
188 }
189 ImGui::EndMenu();
190 }
191 if (ImGui::BeginMenu("NetworkTables")) {
192 if (gNetworkTablesSettingsWindow) {
193 gNetworkTablesSettingsWindow->DisplayMenuItem("NetworkTables Settings");
194 }
195 if (gNetworkTablesWindow) {
196 gNetworkTablesWindow->DisplayMenuItem("NetworkTables View");
197 }
198 if (gNetworkTablesLogWindow) {
199 gNetworkTablesLogWindow->DisplayMenuItem("NetworkTables Log");
200 }
201 ImGui::Separator();
202 gNtProvider->DisplayMenu();
203 ImGui::EndMenu();
204 }
205 if (ImGui::BeginMenu("Plot")) {
206 bool paused = gPlotProvider->IsPaused();
207 if (ImGui::MenuItem("Pause All Plots", nullptr, &paused)) {
208 gPlotProvider->SetPaused(paused);
209 }
210 ImGui::Separator();
211 gPlotProvider->DisplayMenu();
212 ImGui::EndMenu();
213 }
214
Austin Schuh812d0d12021-11-04 20:16:48 -0700215 if (ImGui::BeginMenu("Info")) {
216 if (ImGui::MenuItem("About")) {
Austin Schuh75263e32022-02-22 18:05:32 -0800217 gAbout = true;
Austin Schuh812d0d12021-11-04 20:16:48 -0700218 }
219 ImGui::EndMenu();
220 }
Austin Schuh75263e32022-02-22 18:05:32 -0800221 });
Austin Schuh812d0d12021-11-04 20:16:48 -0700222
Austin Schuh75263e32022-02-22 18:05:32 -0800223 gui::AddLateExecute([] {
224 if (gAbout) {
Austin Schuh812d0d12021-11-04 20:16:48 -0700225 ImGui::OpenPopup("About");
Austin Schuh75263e32022-02-22 18:05:32 -0800226 gAbout = false;
Austin Schuh812d0d12021-11-04 20:16:48 -0700227 }
228 if (ImGui::BeginPopupModal("About")) {
229 ImGui::Text("Glass: A different kind of dashboard");
230 ImGui::Separator();
231 ImGui::Text("v%s", GetWPILibVersion());
Austin Schuh75263e32022-02-22 18:05:32 -0800232 ImGui::Separator();
233 ImGui::Text("Save location: %s", glass::GetStorageDir().c_str());
Austin Schuh812d0d12021-11-04 20:16:48 -0700234 if (ImGui::Button("Close")) {
235 ImGui::CloseCurrentPopup();
236 }
237 ImGui::EndPopup();
238 }
Austin Schuh75263e32022-02-22 18:05:32 -0800239
240 int& enterKey = glass::GetStorageRoot().GetInt("enterKey", GLFW_KEY_ENTER);
241
242 ImGuiIO& io = ImGui::GetIO();
243 io.KeyMap[ImGuiKey_Enter] = enterKey;
244
245 if (gSetEnterKey) {
246 ImGui::OpenPopup("Set Enter Key");
247 gSetEnterKey = false;
248 }
249 if (ImGui::BeginPopupModal("Set Enter Key")) {
250 ImGui::Text("Set the key to use to mean 'Enter'");
251 ImGui::Text("This is useful to edit values without the DS disabling");
252 ImGui::Separator();
253
254 if (gKeyEdit) {
255 for (int i = 0; i < IM_ARRAYSIZE(io.KeysDown); ++i) {
256 if (io.KeysDown[i]) {
257 // remove all other uses
258 enterKey = i;
259 gKeyEdit = false;
260 break;
261 }
262 }
263 }
264
265 ImGui::Text("Key:");
266 ImGui::SameLine();
267 char editLabel[40];
268 char nameBuf[32];
269 const char* name = glfwGetKeyName(enterKey, 0);
270 if (!name) {
271 std::snprintf(nameBuf, sizeof(nameBuf), "%d", enterKey);
272 name = nameBuf;
273 }
274 std::snprintf(editLabel, sizeof(editLabel), "%s###edit",
275 gKeyEdit ? "(press key)" : name);
276 if (ImGui::SmallButton(editLabel)) {
277 gKeyEdit = true;
278 }
279 ImGui::SameLine();
280 if (ImGui::SmallButton("Reset")) {
281 enterKey = GLFW_KEY_ENTER;
282 }
283
284 if (ImGui::Button("Close")) {
285 ImGui::CloseCurrentPopup();
286 gKeyEdit = false;
287 }
288 ImGui::EndPopup();
289 }
Austin Schuh812d0d12021-11-04 20:16:48 -0700290 });
291
292 gui::Initialize("Glass - DISCONNECTED", 1024, 768);
293 gui::Main();
294
Austin Schuh75263e32022-02-22 18:05:32 -0800295 gNetworkTablesSettingsWindow.reset();
296 gNetworkTablesLogWindow.reset();
297 gNetworkTablesWindow.reset();
Austin Schuh812d0d12021-11-04 20:16:48 -0700298 gNetworkTablesModel.reset();
Austin Schuh812d0d12021-11-04 20:16:48 -0700299 gNtProvider.reset();
300 gPlotProvider.reset();
301
302 glass::DestroyContext();
303 gui::DestroyContext();
Austin Schuh75263e32022-02-22 18:05:32 -0800304
305 return 0;
Austin Schuh812d0d12021-11-04 20:16:48 -0700306}