13#include <GLFW/glfw3.h>
15#include "imgui_internal.h"
16#include "imgui_impl_glfw.h"
17#include "imgui_impl_opengl3.h"
32void* PanelReadOpen(ImGuiContext*, ImGuiSettingsHandler* handler,
const char* name)
34 if (strcmp(name,
"Panels") == 0)
35 return handler->UserData;
39void PanelReadLine(ImGuiContext*, ImGuiSettingsHandler*,
void* entry,
const char* line)
41 auto* ui =
static_cast<UIState*
>(entry);
42 const char* eq = strchr(line,
'=');
44 std::string key(line, eq);
45 ui->panelOpen[key] = (atoi(eq + 1) != 0);
48void PanelWriteAll(ImGuiContext*, ImGuiSettingsHandler* handler, ImGuiTextBuffer* buf)
50 const auto* ui =
static_cast<const UIState*
>(handler->UserData);
51 buf->appendf(
"[UserData][Panels]\n");
52 for (
const auto& [name, open] : ui->panelOpen)
53 buf->appendf(
"%s=%d\n", name.c_str(), open ? 1 : 0);
64 ImGui::CreateContext();
65 ImGuiIO& io = ImGui::GetIO();
66 io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
67 io.ConfigFlags |= ImGuiConfigFlags_DockingEnable;
71 ImGuiSettingsHandler handler;
72 handler.TypeName =
"UserData";
73 handler.TypeHash = ImHashStr(
"UserData");
74 handler.ReadOpenFn = PanelReadOpen;
75 handler.ReadLineFn = PanelReadLine;
76 handler.WriteAllFn = PanelWriteAll;
77 handler.UserData = uiState;
78 ImGui::GetCurrentContext()->SettingsHandlers.push_back(handler);
83 ImGui::GetStyle().ScaleAllSizes(dpiScale);
85 ImGui_ImplGlfw_InitForOpenGL(window,
true);
86 ImGui_ImplOpenGL3_Init(
"#version 130");
93 ImGui_ImplOpenGL3_Shutdown();
94 ImGui_ImplGlfw_Shutdown();
95 ImGui::DestroyContext();
102 namespace fs = std::filesystem;
104 std::vector<fs::path> searchDirs;
107 wchar_t exePath[MAX_PATH]{};
108 GetModuleFileNameW(
nullptr, exePath, MAX_PATH);
109 searchDirs.push_back(fs::path(exePath).parent_path() /
"fonts");
113 searchDirs.push_back(fs::path(WMV_FONTS_PATH));
115 searchDirs.push_back(fs::current_path() /
"fonts");
117 std::set<std::string> seen;
118 for (
const auto& dir : searchDirs)
120 if (!fs::is_directory(dir))
122 for (
const auto& entry : fs::directory_iterator(dir))
124 if (!entry.is_regular_file())
126 auto ext = entry.path().extension().string();
127 std::transform(ext.begin(), ext.end(), ext.begin(), ::tolower);
128 if (ext !=
".ttf" && ext !=
".otf")
130 std::string stemName = entry.path().stem().string();
131 std::string stemLower = stemName;
132 std::transform(stemLower.begin(), stemLower.end(), stemLower.begin(), ::tolower);
133 if (seen.count(stemLower))
135 seen.insert(stemLower);
136 std::string absPath = fs::canonical(entry.path()).string();
137 fonts.push_back({ stemName, absPath });
141 std::sort(fonts.begin(), fonts.end(),
144 if (selectedFont <= 0)
146 const char* preferred[] = {
"roboto-regular",
"arialn" };
147 for (
const char* target : preferred)
150 for (
int i = 0; i < static_cast<int>(fonts.size()); ++i)
152 std::string lower = fonts[i].name;
153 std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
174 ImGuiIO& io = ImGui::GetIO();
175 const float pixelSize = fontSize * dpiScale;
178 if (selectedFont >= 0 && selectedFont <
static_cast<int>(fonts.size()))
180 const auto& fe = fonts[selectedFont];
181 if (std::filesystem::exists(fe.path))
183 io.Fonts->AddFontFromFileTTF(fe.path.c_str(), pixelSize);
185 LOG_INFO <<
"Loaded font:" << fe.name <<
"at" << pixelSize <<
"px";
189 io.Fonts->AddFontDefault();
192 io.FontGlobalScale = 1.0f;
196 const std::vector<FontEntry>& fonts,
205 ImGuiIO& io = ImGui::GetIO();
208 const float pixelSize = fontSize * dpiScale;
211 if (selectedFont >= 0 && selectedFont <
static_cast<int>(fonts.size()))
213 const auto& fe = fonts[selectedFont];
214 if (std::filesystem::exists(fe.path))
216 io.Fonts->AddFontFromFileTTF(fe.path.c_str(), pixelSize);
221 io.Fonts->AddFontDefault();
224 io.FontGlobalScale = 1.0f;
232 ImGui_ImplOpenGL3_NewFrame();
233 ImGui_ImplGlfw_NewFrame();
243 glViewport(0, 0, w, h);
244 glClearColor(0.1f, 0.1f, 0.12f, 1.0f);
245 glClear(GL_COLOR_BUFFER_BIT);
247 ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
void framebufferSize(int &w, int &h) const
Retrieve the framebuffer size in pixels.
void rebuildFontAtlasIfDirty(bool &fontsDirty, const std::vector< FontEntry > &fonts, int selectedFont, float fontSize, float dpiScale)
If the fontsDirty flag is set, rebuild the atlas and clear the flag.
void shutdown()
Shut down ImGui backends and destroy the context.
void discoverFonts(std::vector< FontEntry > &fonts, int &selectedFont)
void endFrame(const AppWindow &window)
bool init(GLFWwindow *window, float dpiScale, UIState *uiState)
void beginFrame()
Start a new ImGui frame (backend NewFrame + ImGui::NewFrame).
void buildFontAtlas(const std::vector< FontEntry > &fonts, int selectedFont, float fontSize, float dpiScale)
Build (or rebuild) the font atlas from the currently selected font.
void mergeIconFont(float pixelSize)
void apply(Theme theme, GLFWwindow *window)
Theme currentTheme() noexcept
Currently active theme index.
static constexpr const char * imguiIniPath
Font entry for the UI font selector.
Mutable state for the UI layer: dialogs, fonts, log viewer, folder picker.