blob: 037b9bdd2b28222bb29ca3b85029065e09e36d06 [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 "glass/WindowManager.h"
6
7#include <algorithm>
8#include <cstdio>
9
10#include <fmt/format.h>
11#include <wpigui.h>
12
13using namespace glass;
14
15WindowManager::WindowManager(std::string_view iniName)
16 : m_iniSaver{iniName, this} {}
17
18// read/write open state to ini file
19void* WindowManager::IniSaver::IniReadOpen(const char* name) {
20 return m_manager->GetOrAddWindow(name, true);
21}
22
23void WindowManager::IniSaver::IniReadLine(void* entry, const char* lineStr) {
24 static_cast<Window*>(entry)->IniReadLine(lineStr);
25}
26
27void WindowManager::IniSaver::IniWriteAll(ImGuiTextBuffer* out_buf) {
28 const char* typeName = GetTypeName();
29 for (auto&& window : m_manager->m_windows) {
30 window->IniWriteAll(typeName, out_buf);
31 }
32}
33
34Window* WindowManager::AddWindow(std::string_view id,
35 wpi::unique_function<void()> display) {
36 auto win = GetOrAddWindow(id, false);
37 if (!win) {
38 return nullptr;
39 }
40 if (win->HasView()) {
41 fmt::print(stderr, "GUI: ignoring duplicate window '{}'\n", id);
42 return nullptr;
43 }
44 win->SetView(MakeFunctionView(std::move(display)));
45 return win;
46}
47
48Window* WindowManager::AddWindow(std::string_view id,
49 std::unique_ptr<View> view) {
50 auto win = GetOrAddWindow(id, false);
51 if (!win) {
52 return nullptr;
53 }
54 if (win->HasView()) {
55 fmt::print(stderr, "GUI: ignoring duplicate window '{}'\n", id);
56 return nullptr;
57 }
58 win->SetView(std::move(view));
59 return win;
60}
61
62Window* WindowManager::GetOrAddWindow(std::string_view id, bool duplicateOk) {
63 // binary search
64 auto it = std::lower_bound(
65 m_windows.begin(), m_windows.end(), id,
66 [](const auto& elem, std::string_view s) { return elem->GetId() < s; });
67 if (it != m_windows.end() && (*it)->GetId() == id) {
68 if (!duplicateOk) {
69 fmt::print(stderr, "GUI: ignoring duplicate window '{}'\n", id);
70 return nullptr;
71 }
72 return it->get();
73 }
74 // insert before (keeps sort)
75 return m_windows.emplace(it, std::make_unique<Window>(id))->get();
76}
77
78Window* WindowManager::GetWindow(std::string_view id) {
79 // binary search
80 auto it = std::lower_bound(
81 m_windows.begin(), m_windows.end(), id,
82 [](const auto& elem, std::string_view s) { return elem->GetId() < s; });
83 if (it == m_windows.end() || (*it)->GetId() != id) {
84 return nullptr;
85 }
86 return it->get();
87}
88
89void WindowManager::GlobalInit() {
90 wpi::gui::AddInit([this] { m_iniSaver.Initialize(); });
91 wpi::gui::AddWindowScaler([this](float scale) {
92 // scale default window positions
93 for (auto&& window : m_windows) {
94 window->ScaleDefault(scale);
95 }
96 });
97 wpi::gui::AddLateExecute([this] { DisplayWindows(); });
98}
99
100void WindowManager::DisplayMenu() {
101 for (auto&& window : m_windows) {
102 window->DisplayMenuItem();
103 }
104}
105
106void WindowManager::DisplayWindows() {
107 for (auto&& window : m_windows) {
108 window->Display();
109 }
110}