ui: Add follow system theme option
This commit is contained in:
parent
e1f410ceff
commit
bf493c5763
@ -31,6 +31,7 @@ namespace hex::plugin::builtin {
|
||||
static int selection = static_cast<int>(setting);
|
||||
|
||||
const char* themes[] = {
|
||||
"hex.builtin.setting.interface.color.system"_lang,
|
||||
"hex.builtin.setting.interface.color.dark"_lang,
|
||||
"hex.builtin.setting.interface.color.light"_lang,
|
||||
"hex.builtin.setting.interface.color.classic"_lang
|
||||
|
@ -583,6 +583,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.setting.general.show_tips", "Tipps beim start anzeigen" },
|
||||
{ "hex.builtin.setting.interface", "Aussehen" },
|
||||
{ "hex.builtin.setting.interface.color", "Farbthema" },
|
||||
{ "hex.builtin.setting.interface.color.system", "System" },
|
||||
{ "hex.builtin.setting.interface.color.dark", "Dunkel" },
|
||||
{ "hex.builtin.setting.interface.color.light", "Hell" },
|
||||
{ "hex.builtin.setting.interface.color.classic", "Klassisch" },
|
||||
|
@ -584,6 +584,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.setting.general.show_tips", "Show tips on startup" },
|
||||
{ "hex.builtin.setting.interface", "Interface" },
|
||||
{ "hex.builtin.setting.interface.color", "Color theme" },
|
||||
{ "hex.builtin.setting.interface.color.system", "System" },
|
||||
{ "hex.builtin.setting.interface.color.dark", "Dark" },
|
||||
{ "hex.builtin.setting.interface.color.light", "Light" },
|
||||
{ "hex.builtin.setting.interface.color.classic", "Classic" },
|
||||
|
@ -582,6 +582,7 @@ namespace hex::plugin::builtin {
|
||||
{ "hex.builtin.setting.general.show_tips", "Mostra consigli all'avvio" },
|
||||
{ "hex.builtin.setting.interface", "Interfaccia" },
|
||||
{ "hex.builtin.setting.interface.color", "Colore del Tema" },
|
||||
{ "hex.builtin.setting.interface.color.system", "Sistema" },
|
||||
{ "hex.builtin.setting.interface.color.dark", "Scuro" },
|
||||
{ "hex.builtin.setting.interface.color.light", "Chiaro" },
|
||||
{ "hex.builtin.setting.interface.color.classic", "Classico" },
|
||||
|
@ -106,6 +106,7 @@ namespace hex {
|
||||
EVENT_DEF(EventProjectFileLoad);
|
||||
EVENT_DEF(EventSettingsChanged);
|
||||
EVENT_DEF(EventAbnormalTermination, int);
|
||||
EVENT_DEF(EventOSThemeChanged);
|
||||
|
||||
EVENT_DEF(RequestOpenWindow, std::string);
|
||||
EVENT_DEF(RequestSelectionChange, Region);
|
||||
@ -114,6 +115,7 @@ namespace hex {
|
||||
EVENT_DEF(RequestChangeWindowTitle, std::string);
|
||||
EVENT_DEF(RequestCloseImHex, bool);
|
||||
EVENT_DEF(RequestOpenFile, std::string);
|
||||
EVENT_DEF(RequestChangeTheme, u32);
|
||||
|
||||
EVENT_DEF(QuerySelection, Region&);
|
||||
|
||||
|
@ -8,6 +8,7 @@
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
@ -9,25 +9,21 @@
|
||||
namespace hex {
|
||||
|
||||
ViewDataProcessor::ViewDataProcessor() : View("hex.view.data_processor.name") {
|
||||
EventManager::subscribe<EventSettingsChanged>(this, [] {
|
||||
auto theme = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color");
|
||||
|
||||
if (theme.is_number()) {
|
||||
switch (static_cast<int>(theme)) {
|
||||
default:
|
||||
case 0: /* Dark theme */
|
||||
ImNodes::StyleColorsDark();
|
||||
break;
|
||||
case 1: /* Light theme */
|
||||
ImNodes::StyleColorsLight();
|
||||
break;
|
||||
case 2: /* Classic theme */
|
||||
ImNodes::StyleColorsClassic();
|
||||
break;
|
||||
}
|
||||
|
||||
ImNodes::GetStyle().Flags = ImNodesStyleFlags_NodeOutline | ImNodesStyleFlags_GridLines;
|
||||
EventManager::subscribe<RequestChangeTheme>(this, [](u32 theme) {
|
||||
switch (theme) {
|
||||
default:
|
||||
case 1: /* Dark theme */
|
||||
ImNodes::StyleColorsDark();
|
||||
break;
|
||||
case 2: /* Light theme */
|
||||
ImNodes::StyleColorsLight();
|
||||
break;
|
||||
case 3: /* Classic theme */
|
||||
ImNodes::StyleColorsClassic();
|
||||
break;
|
||||
}
|
||||
|
||||
ImNodes::GetStyle().Flags = ImNodesStyleFlags_NodeOutline | ImNodesStyleFlags_GridLines;
|
||||
});
|
||||
|
||||
EventManager::subscribe<EventProjectFileStore>(this, [this] {
|
||||
@ -50,7 +46,7 @@ namespace hex {
|
||||
for (auto &node : this->m_nodes)
|
||||
delete node;
|
||||
|
||||
EventManager::unsubscribe<EventSettingsChanged>(this);
|
||||
EventManager::unsubscribe<RequestChangeTheme>(this);
|
||||
EventManager::unsubscribe<EventFileLoaded>(this);
|
||||
EventManager::unsubscribe<EventProjectFileStore>(this);
|
||||
EventManager::unsubscribe<EventProjectFileLoad>(this);
|
||||
|
@ -152,22 +152,18 @@ namespace hex {
|
||||
/* Settings */
|
||||
{
|
||||
|
||||
EventManager::subscribe<EventSettingsChanged>(this, [this]() {
|
||||
auto theme = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color");
|
||||
|
||||
if (theme.is_number()) {
|
||||
switch (static_cast<int>(theme)) {
|
||||
default:
|
||||
case 0: /* Dark theme */
|
||||
this->m_textEditor.SetPalette(TextEditor::GetDarkPalette());
|
||||
break;
|
||||
case 1: /* Light theme */
|
||||
this->m_textEditor.SetPalette(TextEditor::GetLightPalette());
|
||||
break;
|
||||
case 2: /* Classic theme */
|
||||
this->m_textEditor.SetPalette(TextEditor::GetRetroBluePalette());
|
||||
break;
|
||||
}
|
||||
EventManager::subscribe<RequestChangeTheme>(this, [this](u32 theme) {
|
||||
switch (theme) {
|
||||
default:
|
||||
case 1: /* Dark theme */
|
||||
this->m_textEditor.SetPalette(TextEditor::GetDarkPalette());
|
||||
break;
|
||||
case 2: /* Light theme */
|
||||
this->m_textEditor.SetPalette(TextEditor::GetLightPalette());
|
||||
break;
|
||||
case 3: /* Classic theme */
|
||||
this->m_textEditor.SetPalette(TextEditor::GetRetroBluePalette());
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
@ -181,7 +177,7 @@ namespace hex {
|
||||
EventManager::unsubscribe<EventProjectFileLoad>(this);
|
||||
EventManager::unsubscribe<RequestAppendPatternLanguageCode>(this);
|
||||
EventManager::unsubscribe<EventFileLoaded>(this);
|
||||
EventManager::unsubscribe<EventSettingsChanged>(this);
|
||||
EventManager::unsubscribe<RequestChangeTheme>(this);
|
||||
}
|
||||
|
||||
void ViewPatternEditor::drawMenu() {
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
#if defined(OS_LINUX)
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
#include <sys/wait.h>
|
||||
|
||||
namespace hex {
|
||||
|
||||
void Window::initNative() {
|
||||
@ -9,7 +12,28 @@
|
||||
}
|
||||
|
||||
void Window::setupNativeWindow() {
|
||||
bool themeFollowSystem = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color") == 0;
|
||||
EventManager::subscribe<EventOSThemeChanged>(this, [themeFollowSystem]{
|
||||
if (!themeFollowSystem) return;
|
||||
|
||||
std::array<char, 128> buffer = { 0 };
|
||||
std::string result;
|
||||
|
||||
// TODO: In the future maybe support more DEs instead of just GNOME
|
||||
FILE* pipe = popen("gsettings get org.gnome.desktop.interface gtk-theme 2>&1", "r");
|
||||
if (pipe == nullptr) return;
|
||||
|
||||
while (fgets(buffer.data(), buffer.size(), pipe) != nullptr)
|
||||
result += buffer.data();
|
||||
|
||||
auto exitCode = WEXITSTATUS(pclose(pipe));
|
||||
if (exitCode != 0) return;
|
||||
|
||||
EventManager::post<RequestChangeTheme>(hex::containsIgnoreCase(result, "dark") ? 1 : 2);
|
||||
});
|
||||
|
||||
if (themeFollowSystem)
|
||||
EventManager::post<EventOSThemeChanged>();
|
||||
}
|
||||
|
||||
void Window::updateNativeWindow() {
|
||||
|
@ -2,6 +2,8 @@
|
||||
|
||||
#if defined(OS_MACOS)
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace hex {
|
||||
|
||||
void Window::initNative() {
|
||||
@ -9,7 +11,16 @@
|
||||
}
|
||||
|
||||
void Window::setupNativeWindow() {
|
||||
bool themeFollowSystem = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color") == 0;
|
||||
EventManager::subscribe<EventOSThemeChanged>(this, [themeFollowSystem]{
|
||||
if (!themeFollowSystem) return;
|
||||
|
||||
// TODO: Implement this when MacOS build is working again
|
||||
EventManager::post<RequestChangeTheme>(1);
|
||||
});
|
||||
|
||||
if (themeFollowSystem)
|
||||
EventManager::post<EventOSThemeChanged>();
|
||||
}
|
||||
|
||||
void Window::updateNativeWindow() {
|
||||
|
@ -4,11 +4,14 @@
|
||||
#if defined(OS_WINDOWS)
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <imgui_internal.h>
|
||||
#include <codicons_font.h>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#include <GLFW/glfw3.h>
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#include <GLFW/glfw3native.h>
|
||||
@ -140,6 +143,15 @@
|
||||
return HTCAPTION;
|
||||
else break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case WM_SETTINGCHANGE:
|
||||
{
|
||||
if (LPCTSTR(lParam) == std::string_view("ImmersiveColorSet")) {
|
||||
EventManager::post<EventOSThemeChanged>();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default: break;
|
||||
}
|
||||
@ -172,6 +184,25 @@
|
||||
|
||||
::SetWindowPos(hwnd, nullptr, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED | SWP_ASYNCWINDOWPOS | SWP_NOSIZE | SWP_NOMOVE);
|
||||
::SetWindowLong(hwnd, GWL_STYLE, GetWindowLong(hwnd, GWL_STYLE) | WS_POPUP | WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_CAPTION | WS_SYSMENU);
|
||||
|
||||
bool themeFollowSystem = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color") == 0;
|
||||
EventManager::subscribe<EventOSThemeChanged>(this, [themeFollowSystem]{
|
||||
if (!themeFollowSystem) return;
|
||||
|
||||
HKEY hkey;
|
||||
if (RegOpenKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize", &hkey) == ERROR_SUCCESS) {
|
||||
DWORD value = 0;
|
||||
DWORD size = sizeof(DWORD);
|
||||
|
||||
auto error = RegQueryValueEx(hkey, "AppsUseLightTheme", nullptr, nullptr, reinterpret_cast<LPBYTE>(&value), &size);
|
||||
if (error == ERROR_SUCCESS) {
|
||||
EventManager::post<RequestChangeTheme>(value == 0 ? 1 : 2);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (themeFollowSystem)
|
||||
EventManager::post<EventOSThemeChanged>();
|
||||
}
|
||||
|
||||
void Window::updateNativeWindow() {
|
||||
|
@ -85,47 +85,12 @@ namespace hex {
|
||||
|
||||
this->initGLFW();
|
||||
this->initImGui();
|
||||
this->setupNativeWindow();
|
||||
|
||||
EventManager::subscribe<EventSettingsChanged>(this, [this]() {
|
||||
{
|
||||
auto theme = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color");
|
||||
|
||||
if (this->m_bannerTexture.valid())
|
||||
ImGui::UnloadImage(this->m_bannerTexture);
|
||||
|
||||
if (theme.is_number()) {
|
||||
switch (static_cast<int>(theme)) {
|
||||
default:
|
||||
case 0: /* Dark theme */
|
||||
ImGui::StyleColorsDark();
|
||||
ImGui::StyleCustomColorsDark();
|
||||
ImPlot::StyleColorsDark();
|
||||
this->m_bannerTexture = ImGui::LoadImageFromMemory(banner_dark, banner_dark_size);
|
||||
break;
|
||||
case 1: /* Light theme */
|
||||
ImGui::StyleColorsLight();
|
||||
ImGui::StyleCustomColorsLight();
|
||||
ImPlot::StyleColorsLight();
|
||||
this->m_bannerTexture = ImGui::LoadImageFromMemory(banner_light, banner_light_size);
|
||||
break;
|
||||
case 2: /* Classic theme */
|
||||
ImGui::StyleColorsClassic();
|
||||
ImGui::StyleCustomColorsClassic();
|
||||
ImPlot::StyleColorsClassic();
|
||||
this->m_bannerTexture = ImGui::LoadImageFromMemory(banner_dark, banner_dark_size);
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::GetStyle().Colors[ImGuiCol_DockingEmptyBg] = ImGui::GetStyle().Colors[ImGuiCol_WindowBg];
|
||||
ImGui::GetStyle().Colors[ImGuiCol_TitleBg] = ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg];
|
||||
ImGui::GetStyle().Colors[ImGuiCol_TitleBgActive] = ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg];
|
||||
ImGui::GetStyle().Colors[ImGuiCol_TitleBgCollapsed] = ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg];
|
||||
|
||||
if (!this->m_bannerTexture.valid()) {
|
||||
log::fatal("Failed to load banner texture!");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
EventManager::post<RequestChangeTheme>(theme.get<int>());
|
||||
}
|
||||
|
||||
{
|
||||
@ -154,6 +119,43 @@ namespace hex {
|
||||
}
|
||||
});
|
||||
|
||||
EventManager::subscribe<RequestChangeTheme>(this, [this](u32 theme) {
|
||||
if (this->m_bannerTexture.valid())
|
||||
ImGui::UnloadImage(this->m_bannerTexture);
|
||||
|
||||
switch (theme) {
|
||||
default:
|
||||
case 1: /* Dark theme */
|
||||
ImGui::StyleColorsDark();
|
||||
ImGui::StyleCustomColorsDark();
|
||||
ImPlot::StyleColorsDark();
|
||||
this->m_bannerTexture = ImGui::LoadImageFromMemory(banner_dark, banner_dark_size);
|
||||
break;
|
||||
case 2: /* Light theme */
|
||||
ImGui::StyleColorsLight();
|
||||
ImGui::StyleCustomColorsLight();
|
||||
ImPlot::StyleColorsLight();
|
||||
this->m_bannerTexture = ImGui::LoadImageFromMemory(banner_light, banner_light_size);
|
||||
break;
|
||||
case 3: /* Classic theme */
|
||||
ImGui::StyleColorsClassic();
|
||||
ImGui::StyleCustomColorsClassic();
|
||||
ImPlot::StyleColorsClassic();
|
||||
this->m_bannerTexture = ImGui::LoadImageFromMemory(banner_dark, banner_dark_size);
|
||||
break;
|
||||
}
|
||||
|
||||
ImGui::GetStyle().Colors[ImGuiCol_DockingEmptyBg] = ImGui::GetStyle().Colors[ImGuiCol_WindowBg];
|
||||
ImGui::GetStyle().Colors[ImGuiCol_TitleBg] = ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg];
|
||||
ImGui::GetStyle().Colors[ImGuiCol_TitleBgActive] = ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg];
|
||||
ImGui::GetStyle().Colors[ImGuiCol_TitleBgCollapsed] = ImGui::GetStyle().Colors[ImGuiCol_MenuBarBg];
|
||||
|
||||
if (!this->m_bannerTexture.valid()) {
|
||||
log::fatal("Failed to load banner texture!");
|
||||
std::abort();
|
||||
}
|
||||
});
|
||||
|
||||
EventManager::subscribe<EventFileLoaded>(this, [](const std::string &path){
|
||||
SharedData::recentFilePaths.push_front(path);
|
||||
|
||||
@ -262,6 +264,7 @@ namespace hex {
|
||||
EventManager::unsubscribe<RequestCloseImHex>(this);
|
||||
EventManager::unsubscribe<RequestChangeWindowTitle>(this);
|
||||
EventManager::unsubscribe<EventAbnormalTermination>(this);
|
||||
EventManager::unsubscribe<RequestChangeTheme>(this);
|
||||
|
||||
ImGui::UnloadImage(this->m_bannerTexture);
|
||||
ImGui::UnloadImage(this->m_logoTexture);
|
||||
@ -691,8 +694,6 @@ namespace hex {
|
||||
this->m_windowTitle = "ImHex";
|
||||
this->m_window = glfwCreateWindow(1280 * SharedData::globalScale, 720 * SharedData::globalScale, this->m_windowTitle.c_str(), nullptr, nullptr);
|
||||
|
||||
this->setupNativeWindow();
|
||||
|
||||
glfwSetWindowUserPointer(this->m_window, this);
|
||||
|
||||
if (this->m_window == nullptr)
|
||||
|
Loading…
x
Reference in New Issue
Block a user