feat: Added native custom theme support
This commit is contained in:
parent
696d8d1d54
commit
7859a9bb1f
6
lib/external/imgui/include/TextEditor.h
vendored
6
lib/external/imgui/include/TextEditor.h
vendored
@ -188,8 +188,8 @@ public:
|
||||
void SetLanguageDefinition(const LanguageDefinition& aLanguageDef);
|
||||
const LanguageDefinition& GetLanguageDefinition() const { return mLanguageDefinition; }
|
||||
|
||||
const Palette& GetPalette() const { return mPaletteBase; }
|
||||
void SetPalette(const Palette& aValue);
|
||||
static const Palette& GetPalette() { return sPaletteBase; }
|
||||
static void SetPalette(const Palette& aValue);
|
||||
|
||||
void SetErrorMarkers(const ErrorMarkers& aMarkers) { mErrorMarkers = aMarkers; }
|
||||
void SetBreakpoints(const Breakpoints& aMarkers) { mBreakpoints = aMarkers; }
|
||||
@ -372,7 +372,7 @@ private:
|
||||
bool mIgnoreImGuiChild;
|
||||
bool mShowWhitespaces;
|
||||
|
||||
Palette mPaletteBase;
|
||||
static Palette sPaletteBase;
|
||||
Palette mPalette;
|
||||
LanguageDefinition mLanguageDefinition;
|
||||
RegexList mRegexList;
|
||||
|
7
lib/external/imgui/source/TextEditor.cpp
vendored
7
lib/external/imgui/source/TextEditor.cpp
vendored
@ -21,9 +21,10 @@ bool equals(InputIt1 first1, InputIt1 last1, InputIt2 first2, InputIt2 last2, Bi
|
||||
return first1 == last1 && first2 == last2;
|
||||
}
|
||||
|
||||
TextEditor::Palette TextEditor::sPaletteBase = TextEditor::GetDarkPalette();
|
||||
|
||||
TextEditor::TextEditor()
|
||||
: mLineSpacing(1.0f), mUndoIndex(0), mTabSize(4), mOverwrite(false), mReadOnly(false), mWithinRender(false), mScrollToCursor(false), mScrollToTop(false), mTextChanged(false), mColorizerEnabled(true), mTextStart(20.0f), mLeftMargin(10), mCursorPositionChanged(false), mColorRangeMin(0), mColorRangeMax(0), mSelectionMode(SelectionMode::Normal), mCheckComments(true), mLastClick(-1.0f), mHandleKeyboardInputs(true), mHandleMouseInputs(true), mIgnoreImGuiChild(false), mShowWhitespaces(true), mStartTime(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()) {
|
||||
SetPalette(GetDarkPalette());
|
||||
SetLanguageDefinition(LanguageDefinition::HLSL());
|
||||
mLines.push_back(Line());
|
||||
}
|
||||
@ -42,7 +43,7 @@ void TextEditor::SetLanguageDefinition(const LanguageDefinition &aLanguageDef) {
|
||||
}
|
||||
|
||||
void TextEditor::SetPalette(const Palette &aValue) {
|
||||
mPaletteBase = aValue;
|
||||
sPaletteBase = aValue;
|
||||
}
|
||||
|
||||
std::string TextEditor::GetText(const Coordinates &aStart, const Coordinates &aEnd) const {
|
||||
@ -740,7 +741,7 @@ void TextEditor::Render() {
|
||||
|
||||
/* Update palette with the current alpha from style */
|
||||
for (int i = 0; i < (int)PaletteIndex::Max; ++i) {
|
||||
auto color = ImGui::ColorConvertU32ToFloat4(mPaletteBase[i]);
|
||||
auto color = ImGui::ColorConvertU32ToFloat4(sPaletteBase[i]);
|
||||
color.w *= ImGui::GetStyle().Alpha;
|
||||
mPalette[i] = ImGui::ColorConvertFloat4ToU32(color);
|
||||
}
|
||||
|
@ -116,6 +116,7 @@ set(LIBIMHEX_SOURCES
|
||||
source/api/plugin_manager.cpp
|
||||
source/api/localization.cpp
|
||||
source/api/project_file_manager.cpp
|
||||
source/api/theme_manager.cpp
|
||||
|
||||
source/data_processor/attribute.cpp
|
||||
source/data_processor/link.cpp
|
||||
|
@ -128,7 +128,7 @@ namespace hex {
|
||||
EVENT_DEF(RequestCloseImHex, bool);
|
||||
EVENT_DEF(RequestRestartImHex);
|
||||
EVENT_DEF(RequestOpenFile, std::fs::path);
|
||||
EVENT_DEF(RequestChangeTheme, u32);
|
||||
EVENT_DEF(RequestChangeTheme, std::string);
|
||||
EVENT_DEF(RequestOpenPopup, std::string);
|
||||
EVENT_DEF(RequestCreateProvider, std::string, bool, hex::prv::Provider **);
|
||||
|
||||
|
@ -191,12 +191,6 @@ namespace hex {
|
||||
char **envp;
|
||||
};
|
||||
|
||||
enum class Theme {
|
||||
Dark = 1,
|
||||
Light = 2,
|
||||
Classic = 3
|
||||
};
|
||||
|
||||
const ProgramArguments &getProgramArguments();
|
||||
std::optional<std::u8string> getProgramArgument(int index);
|
||||
|
||||
@ -218,9 +212,6 @@ namespace hex {
|
||||
const std::filesystem::path &getCustomFontPath();
|
||||
float getFontSize();
|
||||
|
||||
void setTheme(Theme theme);
|
||||
Theme getTheme();
|
||||
|
||||
void enableSystemThemeDetection(bool enabled);
|
||||
bool usesSystemThemeDetection();
|
||||
|
||||
|
35
lib/libimhex/include/hex/api/theme_manager.hpp
Normal file
35
lib/libimhex/include/hex/api/theme_manager.hpp
Normal file
@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include <hex.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include <nlohmann/json_fwd.hpp>
|
||||
#include <imgui.h>
|
||||
|
||||
namespace hex::api {
|
||||
|
||||
class ThemeManager {
|
||||
public:
|
||||
constexpr static auto NativeTheme = "Native";
|
||||
|
||||
static void changeTheme(std::string name);
|
||||
|
||||
static void addTheme(const std::string &content);
|
||||
static void addThemeHandler(const std::string &name, const std::function<void(std::string, std::string)> &handler);
|
||||
static void addStyleHandler(const std::string &name, const std::function<void(std::string, std::string)> &handler);
|
||||
|
||||
static std::vector<std::string> getThemeNames();
|
||||
static const std::string &getThemeImagePostfix();
|
||||
|
||||
static std::optional<ImColor> parseColorString(const std::string &colorString);
|
||||
private:
|
||||
ThemeManager() = default;
|
||||
|
||||
static std::map<std::string, nlohmann::json> s_themes;
|
||||
static std::map<std::string, std::function<void(std::string, std::string)>> s_themeHandlers, s_styleHandlers;
|
||||
static std::string s_imagePostfix;
|
||||
};
|
||||
|
||||
}
|
@ -101,6 +101,7 @@ namespace hex::fs {
|
||||
Recent,
|
||||
Scripts,
|
||||
Inspectors,
|
||||
Themes,
|
||||
|
||||
END
|
||||
};
|
||||
|
@ -480,19 +480,8 @@ namespace hex {
|
||||
}
|
||||
|
||||
|
||||
static Theme s_theme;
|
||||
static bool s_systemThemeDetection;
|
||||
|
||||
void setTheme(Theme theme) {
|
||||
s_theme = theme;
|
||||
|
||||
EventManager::post<EventSettingsChanged>();
|
||||
}
|
||||
|
||||
Theme getTheme() {
|
||||
return s_theme;
|
||||
}
|
||||
|
||||
|
||||
void enableSystemThemeDetection(bool enabled) {
|
||||
s_systemThemeDetection = enabled;
|
||||
|
118
lib/libimhex/source/api/theme_manager.cpp
Normal file
118
lib/libimhex/source/api/theme_manager.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
#include <hex/api/theme_manager.hpp>
|
||||
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
namespace hex::api {
|
||||
|
||||
std::map<std::string, nlohmann::json> ThemeManager::s_themes;
|
||||
std::map<std::string, std::function<void(std::string, std::string)>> ThemeManager::s_themeHandlers, ThemeManager::s_styleHandlers;
|
||||
std::string ThemeManager::s_imagePostfix;
|
||||
|
||||
void ThemeManager::addThemeHandler(const std::string &name, const std::function<void(std::string, std::string)> &handler) {
|
||||
s_themeHandlers[name] = handler;
|
||||
}
|
||||
|
||||
void ThemeManager::addStyleHandler(const std::string &name, const std::function<void(std::string, std::string)> &handler) {
|
||||
s_styleHandlers[name] = handler;
|
||||
}
|
||||
|
||||
void ThemeManager::addTheme(const std::string &content) {
|
||||
auto theme = nlohmann::json::parse(content);
|
||||
if (theme.contains("name") && theme.contains("colors")) {
|
||||
s_themes[theme["name"].get<std::string>()] = theme;
|
||||
} else {
|
||||
hex::log::error("Invalid theme file");
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<ImColor> ThemeManager::parseColorString(const std::string &colorString) {
|
||||
if (colorString.length() != 9 || colorString[0] != '#')
|
||||
return std::nullopt;
|
||||
|
||||
u32 color = 0;
|
||||
|
||||
for (u32 i = 1; i < 9; i++) {
|
||||
color <<= 4;
|
||||
if (colorString[i] >= '0' && colorString[i] <= '9')
|
||||
color |= colorString[i] - '0';
|
||||
else if (colorString[i] >= 'A' && colorString[i] <= 'F')
|
||||
color |= colorString[i] - 'A' + 10;
|
||||
else if (colorString[i] >= 'a' && colorString[i] <= 'f')
|
||||
color |= colorString[i] - 'a' + 10;
|
||||
else
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return ImColor(hex::changeEndianess(color, std::endian::big));
|
||||
}
|
||||
|
||||
void ThemeManager::changeTheme(std::string name) {
|
||||
if (!s_themes.contains(name)) {
|
||||
if (s_themes.empty()) {
|
||||
hex::log::error("Theme '{}' does not exist and no other themes are available!", name);
|
||||
return;
|
||||
} else {
|
||||
const std::string &defaultTheme = s_themes.begin()->first;
|
||||
hex::log::error("Theme '{}' does not exist, using default theme '{}' instead!", name, defaultTheme);
|
||||
name = defaultTheme;
|
||||
}
|
||||
}
|
||||
|
||||
const auto &theme = s_themes[name];
|
||||
|
||||
if (theme.contains("base")) {
|
||||
if (theme["base"].is_string()) {
|
||||
changeTheme(theme["base"].get<std::string>());
|
||||
} else {
|
||||
hex::log::error("Theme '{}' has invalid base theme!", name);
|
||||
}
|
||||
}
|
||||
|
||||
if (theme.contains("colors")) {
|
||||
for (const auto&[type, content] : theme["colors"].items()) {
|
||||
if (!s_themeHandlers.contains(type)) {
|
||||
log::warn("No theme handler found for '{}'", type);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const auto &[key, value] : content.items())
|
||||
s_themeHandlers[type](key, value.get<std::string>());
|
||||
}
|
||||
}
|
||||
|
||||
if (theme.contains("styles")) {
|
||||
for (const auto&[key, value] : theme["styles"].items()) {
|
||||
if (!s_styleHandlers.contains(key)) {
|
||||
log::warn("No style handler found for '{}'", key);
|
||||
continue;
|
||||
}
|
||||
|
||||
s_styleHandlers[key](name, value.get<std::string>());
|
||||
}
|
||||
}
|
||||
|
||||
if (theme.contains("image_postfix")) {
|
||||
if (theme["image_postfix"].is_string()) {
|
||||
s_imagePostfix = theme["image_postfix"].get<std::string>();
|
||||
} else {
|
||||
hex::log::error("Theme '{}' has invalid image postfix!", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const std::string &ThemeManager::getThemeImagePostfix() {
|
||||
return s_imagePostfix;
|
||||
}
|
||||
|
||||
std::vector<std::string> ThemeManager::getThemeNames() {
|
||||
std::vector<std::string> themeNames;
|
||||
for (const auto &[name, theme] : s_themes)
|
||||
themeNames.push_back(name);
|
||||
|
||||
return themeNames;
|
||||
}
|
||||
|
||||
}
|
@ -253,6 +253,9 @@ namespace hex::fs {
|
||||
case ImHexPath::Inspectors:
|
||||
result = appendPath(getDefaultPaths(ImHexPath::Scripts), "inspectors");
|
||||
break;
|
||||
case ImHexPath::Themes:
|
||||
result = appendPath(getDataPaths(), "themes");
|
||||
break;
|
||||
}
|
||||
|
||||
if (!listNonExisting) {
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
#include <hex/api/theme_manager.hpp>
|
||||
|
||||
#include "window.hpp"
|
||||
|
||||
|
@ -43,7 +43,7 @@ namespace hex {
|
||||
auto exitCode = WEXITSTATUS(pclose(pipe));
|
||||
if (exitCode != 0) return;
|
||||
|
||||
EventManager::post<RequestChangeTheme>(hex::containsIgnoreCase(result, "light") ? 2 : 1);
|
||||
EventManager::post<RequestChangeTheme>(hex::containsIgnoreCase(result, "light") ? "Light" : "Dark");
|
||||
});
|
||||
|
||||
if (themeFollowSystem)
|
||||
|
@ -30,9 +30,9 @@ namespace hex {
|
||||
if (!themeFollowSystem) return;
|
||||
|
||||
if (!isMacosSystemDarkModeEnabled())
|
||||
EventManager::post<RequestChangeTheme>(2);
|
||||
EventManager::post<RequestChangeTheme>("Light");
|
||||
else
|
||||
EventManager::post<RequestChangeTheme>(1);
|
||||
EventManager::post<RequestChangeTheme>("Dark");
|
||||
});
|
||||
|
||||
if (themeFollowSystem)
|
||||
|
@ -106,7 +106,7 @@ namespace hex {
|
||||
this->setupNativeWindow();
|
||||
|
||||
// Initialize default theme
|
||||
EventManager::post<RequestChangeTheme>(1);
|
||||
EventManager::post<RequestChangeTheme>("Dark");
|
||||
|
||||
EventManager::subscribe<RequestCloseImHex>(this, [this](bool noQuestions) {
|
||||
glfwSetWindowShouldClose(this->m_window, GLFW_TRUE);
|
||||
@ -688,6 +688,8 @@ namespace hex {
|
||||
style.Alpha = 1.0F;
|
||||
style.WindowRounding = 0.0F;
|
||||
|
||||
ImNodes::GetStyle().Flags = ImNodesStyleFlags_NodeOutline | ImNodesStyleFlags_GridLines;
|
||||
|
||||
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable | ImGuiConfigFlags_NavEnableKeyboard;
|
||||
io.ConfigWindowsMoveFromTitleBarOnly = true;
|
||||
io.FontGlobalScale = 1.0F;
|
||||
|
@ -25,6 +25,7 @@ add_library(${PROJECT_NAME} SHARED
|
||||
source/content/hashes.cpp
|
||||
source/content/shortcuts.cpp
|
||||
source/content/global_actions.cpp
|
||||
source/content/themes.cpp
|
||||
|
||||
source/content/providers/file_provider.cpp
|
||||
source/content/providers/gdb_provider.cpp
|
||||
|
@ -372,10 +372,6 @@
|
||||
"hex.builtin.setting.imhex.recent_files": "Zuletzt geöffnete Dateien",
|
||||
"hex.builtin.setting.interface": "Aussehen",
|
||||
"hex.builtin.setting.interface.color": "Farbdesign",
|
||||
"hex.builtin.setting.interface.color.classic": "Klassisch",
|
||||
"hex.builtin.setting.interface.color.dark": "Dunkel",
|
||||
"hex.builtin.setting.interface.color.light": "Hell",
|
||||
"hex.builtin.setting.interface.color.system": "System",
|
||||
"hex.builtin.setting.interface.fps": "FPS Limit",
|
||||
"hex.builtin.setting.interface.fps.unlocked": "Unbegrenzt",
|
||||
"hex.builtin.setting.interface.language": "Sprache",
|
||||
|
@ -373,10 +373,6 @@
|
||||
"hex.builtin.setting.imhex.recent_files": "Recent Files",
|
||||
"hex.builtin.setting.interface": "Interface",
|
||||
"hex.builtin.setting.interface.color": "Color theme",
|
||||
"hex.builtin.setting.interface.color.classic": "Classic",
|
||||
"hex.builtin.setting.interface.color.dark": "Dark",
|
||||
"hex.builtin.setting.interface.color.light": "Light",
|
||||
"hex.builtin.setting.interface.color.system": "System",
|
||||
"hex.builtin.setting.interface.fps": "FPS Limit",
|
||||
"hex.builtin.setting.interface.fps.unlocked": "Unlocked",
|
||||
"hex.builtin.setting.interface.language": "Language",
|
||||
|
@ -371,10 +371,6 @@
|
||||
"hex.builtin.setting.imhex.recent_files": "File recenti",
|
||||
"hex.builtin.setting.interface": "Interfaccia",
|
||||
"hex.builtin.setting.interface.color": "Colore del Tema",
|
||||
"hex.builtin.setting.interface.color.classic": "Classico",
|
||||
"hex.builtin.setting.interface.color.dark": "Scuro",
|
||||
"hex.builtin.setting.interface.color.light": "Chiaro",
|
||||
"hex.builtin.setting.interface.color.system": "Sistema",
|
||||
"hex.builtin.setting.interface.fps": "Limite FPS",
|
||||
"hex.builtin.setting.interface.fps.unlocked": "Unblocca",
|
||||
"hex.builtin.setting.interface.language": "Lingua",
|
||||
|
@ -371,10 +371,6 @@
|
||||
"hex.builtin.setting.imhex.recent_files": "最近開いたファイル",
|
||||
"hex.builtin.setting.interface": "UI",
|
||||
"hex.builtin.setting.interface.color": "カラーテーマ",
|
||||
"hex.builtin.setting.interface.color.classic": "クラシック",
|
||||
"hex.builtin.setting.interface.color.dark": "ダーク",
|
||||
"hex.builtin.setting.interface.color.light": "ライト",
|
||||
"hex.builtin.setting.interface.color.system": "システム設定に従う",
|
||||
"hex.builtin.setting.interface.fps": "FPS制限",
|
||||
"hex.builtin.setting.interface.fps.unlocked": "無制限",
|
||||
"hex.builtin.setting.interface.language": "言語",
|
||||
|
@ -371,10 +371,6 @@
|
||||
"hex.builtin.setting.imhex.recent_files": "최근 파일",
|
||||
"hex.builtin.setting.interface": "인터페이스",
|
||||
"hex.builtin.setting.interface.color": "색상 테마",
|
||||
"hex.builtin.setting.interface.color.classic": "클래식",
|
||||
"hex.builtin.setting.interface.color.dark": "다크",
|
||||
"hex.builtin.setting.interface.color.light": "라이트",
|
||||
"hex.builtin.setting.interface.color.system": "시스템",
|
||||
"hex.builtin.setting.interface.fps": "FPS 제한",
|
||||
"hex.builtin.setting.interface.fps.unlocked": "제한 없음",
|
||||
"hex.builtin.setting.interface.language": "언어",
|
||||
|
@ -371,10 +371,6 @@
|
||||
"hex.builtin.setting.imhex.recent_files": "Arquivos Recentes",
|
||||
"hex.builtin.setting.interface": "Interface",
|
||||
"hex.builtin.setting.interface.color": "Color theme",
|
||||
"hex.builtin.setting.interface.color.classic": "Classico",
|
||||
"hex.builtin.setting.interface.color.dark": "Escuro",
|
||||
"hex.builtin.setting.interface.color.light": "Claro",
|
||||
"hex.builtin.setting.interface.color.system": "Sistema",
|
||||
"hex.builtin.setting.interface.fps": "FPS Limit",
|
||||
"hex.builtin.setting.interface.fps.unlocked": "Destravado",
|
||||
"hex.builtin.setting.interface.language": "Idioma",
|
||||
|
@ -370,11 +370,6 @@
|
||||
"hex.builtin.setting.imhex": "ImHex",
|
||||
"hex.builtin.setting.imhex.recent_files": "最近文件",
|
||||
"hex.builtin.setting.interface": "界面",
|
||||
"hex.builtin.setting.interface.color": "颜色主题",
|
||||
"hex.builtin.setting.interface.color.classic": "经典",
|
||||
"hex.builtin.setting.interface.color.dark": "暗",
|
||||
"hex.builtin.setting.interface.color.light": "亮",
|
||||
"hex.builtin.setting.interface.color.system": "跟随系统",
|
||||
"hex.builtin.setting.interface.fps": "FPS 限制",
|
||||
"hex.builtin.setting.interface.fps.unlocked": "无限制",
|
||||
"hex.builtin.setting.interface.language": "语言",
|
||||
|
@ -371,10 +371,6 @@
|
||||
"hex.builtin.setting.imhex.recent_files": "近期檔案",
|
||||
"hex.builtin.setting.interface": "介面",
|
||||
"hex.builtin.setting.interface.color": "顏色主題",
|
||||
"hex.builtin.setting.interface.color.classic": "經典",
|
||||
"hex.builtin.setting.interface.color.dark": "暗色",
|
||||
"hex.builtin.setting.interface.color.light": "亮色",
|
||||
"hex.builtin.setting.interface.color.system": "系統",
|
||||
"hex.builtin.setting.interface.fps": "FPS 限制",
|
||||
"hex.builtin.setting.interface.fps.unlocked": "解鎖",
|
||||
"hex.builtin.setting.interface.language": "語言",
|
||||
|
153
plugins/builtin/romfs/themes/classic.json
Normal file
153
plugins/builtin/romfs/themes/classic.json
Normal file
@ -0,0 +1,153 @@
|
||||
{
|
||||
"name": "Classic",
|
||||
"image_postfix": "_dark",
|
||||
"colors": {
|
||||
"imgui": {
|
||||
"border": "#7F7F7F7F",
|
||||
"border-shadow": "#00000000",
|
||||
"button": "#59669B9E",
|
||||
"button-active": "#7589CCFF",
|
||||
"button-hovered": "#667AB5C9",
|
||||
"check-mark": "#E5E5E57F",
|
||||
"child-background": "#00000000",
|
||||
"docking-empty-background": "#000000D8",
|
||||
"docking-preview": "#6666E550",
|
||||
"drag-drop-target": "#FFFF00E5",
|
||||
"frame-background": "#6D6D6D63",
|
||||
"frame-background-active": "#6B68A3AF",
|
||||
"frame-background-hovered": "#7777AF66",
|
||||
"header": "#6666E572",
|
||||
"header-active": "#8787DDCC",
|
||||
"header-hovered": "#7272E5CC",
|
||||
"menu-bar-background": "#66668CCC",
|
||||
"modal-window-dim-background": "#33333359",
|
||||
"nav-highlight": "#7272E5CC",
|
||||
"nav-windowing-background": "#CCCCCC33",
|
||||
"nav-windowing-highlight": "#FFFFFFB2",
|
||||
"plot-histogram": "#E5B200FF",
|
||||
"plot-histogram-hovered": "#FF9900FF",
|
||||
"plot-lines": "#FFFFFFFF",
|
||||
"plot-lines-hovered": "#E5B200FF",
|
||||
"popup-background": "#1C1C23EA",
|
||||
"resize-grip": "#FFFFFF19",
|
||||
"resize-grip-active": "#C6D1FFE5",
|
||||
"resize-grip-hovered": "#C6D1FF99",
|
||||
"scrollbar-background": "#333F4C99",
|
||||
"scrollbar-grab": "#6666CC4C",
|
||||
"scrollbar-grab-active": "#6863CC99",
|
||||
"scrollbar-grab-hovered": "#6666CC66",
|
||||
"separator": "#7F7F7F99",
|
||||
"separator-active": "#B2B2E5FF",
|
||||
"separator-hovered": "#9999B2FF",
|
||||
"slider-grab": "#FFFFFF4C",
|
||||
"slider-grab-active": "#6863CC99",
|
||||
"tab": "#5555AEC8",
|
||||
"tab-active": "#6767B9D6",
|
||||
"tab-hovered": "#7272E5CC",
|
||||
"tab-unfocused": "#484891D1",
|
||||
"tab-unfocused-active": "#5959A6D5",
|
||||
"table-border-light": "#424247FF",
|
||||
"table-border-strong": "#4F4F72FF",
|
||||
"table-header-background": "#444460FF",
|
||||
"table-row-background": "#00000000",
|
||||
"table-row-background-alt": "#FFFFFF11",
|
||||
"text": "#E5E5E5FF",
|
||||
"text-disabled": "#999999FF",
|
||||
"text-selected-background": "#0000FF59",
|
||||
"title-background": "#66668CCC",
|
||||
"title-background-active": "#66668CCC",
|
||||
"title-background-collapse": "#66668CCC",
|
||||
"window-background": "#000000D8"
|
||||
},
|
||||
"implot": {
|
||||
"axis-bg": "#00000001",
|
||||
"axis-bg-active": "#00000001",
|
||||
"axis-bg-hovered": "#00000001",
|
||||
"axis-grid": "#E5E5E53F",
|
||||
"axis-text": "#E5E5E5FF",
|
||||
"axis-tick": "#00000001",
|
||||
"crosshairs": "#7F7F7FBF",
|
||||
"error-bar": "#E5E5E5FF",
|
||||
"fill": "#00000001",
|
||||
"frame-bg": "#6D6D6D63",
|
||||
"inlay-text": "#E5E5E5FF",
|
||||
"legend-bg": "#1C1C23EA",
|
||||
"legend-border": "#7F7F7F7F",
|
||||
"legend-text": "#E5E5E5FF",
|
||||
"line": "#00000001",
|
||||
"marker-fill": "#00000001",
|
||||
"marker-outline": "#00000001",
|
||||
"plot-bg": "#00000059",
|
||||
"plot-border": "#7F7F7F7F",
|
||||
"selection": "#F7F763FF",
|
||||
"title-text": "#E5E5E5FF"
|
||||
},
|
||||
"imnodes": {
|
||||
"box-selector": "#00000000",
|
||||
"box-selector-outline": "#00E50000",
|
||||
"grid-background": "#00000000",
|
||||
"grid-line": "#00000000",
|
||||
"grid-line-primary": "#00000000",
|
||||
"link": "#06539BFF",
|
||||
"link-hovered": "#672A78FF",
|
||||
"link-selected": "#DBB377FF",
|
||||
"mini-map-background": "#00000000",
|
||||
"mini-map-background-hovered": "#0000FB90",
|
||||
"mini-map-canvas": "#00000000",
|
||||
"mini-map-canvas-outline": "#00000000",
|
||||
"mini-map-link": "#00000000",
|
||||
"mini-map-link-selected": "#00000000",
|
||||
"mini-map-node-background": "#00000000",
|
||||
"mini-map-node-background-hovered": "#00000000",
|
||||
"mini-map-node-background-selected": "#00000000",
|
||||
"mini-map-node-outline": "#00000000",
|
||||
"mini-map-outline": "#00000000",
|
||||
"mini-map-outline-hovered": "#00000000",
|
||||
"node-background": "#282850FF",
|
||||
"node-background-hovered": "#3C3C64FF",
|
||||
"node-background-selected": "#505078FF",
|
||||
"node-outline": "#E6E6E6FF",
|
||||
"pin": "#4DC69BFF",
|
||||
"pin-hovered": "#00000000",
|
||||
"title-bar": "#E74C3CFF",
|
||||
"title-bar-hovered": "#F1C40FFF",
|
||||
"title-bar-selected": "#388B42FF"
|
||||
},
|
||||
"imhex": {
|
||||
"desc-button": "#282850FF",
|
||||
"desc-button-active": "#505078FF",
|
||||
"desc-button-hovered": "#3C3C64FF",
|
||||
"highlight": "#4DC69BFF",
|
||||
"toolbar-blue": "#06539BFF",
|
||||
"toolbar-brown": "#DBB377FF",
|
||||
"toolbar-gray": "#E6E6E6FF",
|
||||
"toolbar-green": "#388B42FF",
|
||||
"toolbar-purple": "#672A78FF",
|
||||
"toolbar-red": "#E74C3CFF",
|
||||
"toolbar-yellow": "#F1C40FFF"
|
||||
},
|
||||
"text-editor": {
|
||||
"background": "#000080FF",
|
||||
"breakpoint": "#0080FF80",
|
||||
"char-literal": "#008080FF",
|
||||
"comment": "#808080FF",
|
||||
"current-line-edge": "#00000040",
|
||||
"current-line-fill": "#00000040",
|
||||
"current-line-fill-inactive": "#80808040",
|
||||
"cursor": "#FF8000FF",
|
||||
"default": "#FFFF00FF",
|
||||
"error-marker": "#FF0000A0",
|
||||
"identifier": "#FFFF00FF",
|
||||
"keyword": "#00FFFFFF",
|
||||
"known-identifier": "#FFFFFFFF",
|
||||
"line-number": "#008080FF",
|
||||
"multi-line-comment": "#404040FF",
|
||||
"number": "#00FF00FF",
|
||||
"preproc-identifier": "#FF00FFFF",
|
||||
"preprocessor": "#008000FF",
|
||||
"punctuation": "#FFFFFFFF",
|
||||
"selection": "#00FFFF80",
|
||||
"string": "#008080FF"
|
||||
}
|
||||
}
|
||||
}
|
153
plugins/builtin/romfs/themes/dark.json
Normal file
153
plugins/builtin/romfs/themes/dark.json
Normal file
@ -0,0 +1,153 @@
|
||||
{
|
||||
"name": "Dark",
|
||||
"image_postfix": "_dark",
|
||||
"colors": {
|
||||
"imgui": {
|
||||
"border": "#6D6D7F7F",
|
||||
"border-shadow": "#00000000",
|
||||
"button": "#4296F966",
|
||||
"button-active": "#0F87F9FF",
|
||||
"button-hovered": "#4296F9FF",
|
||||
"check-mark": "#4296F9FF",
|
||||
"child-background": "#00000000",
|
||||
"docking-empty-background": "#0F0F0FEF",
|
||||
"docking-preview": "#4296F9B2",
|
||||
"drag-drop-target": "#FFFF00E5",
|
||||
"frame-background": "#28497A89",
|
||||
"frame-background-active": "#4296F9AA",
|
||||
"frame-background-hovered": "#4296F966",
|
||||
"header": "#4296F94F",
|
||||
"header-active": "#4296F9FF",
|
||||
"header-hovered": "#4296F9CC",
|
||||
"menu-bar-background": "#232323FF",
|
||||
"modal-window-dim-background": "#CCCCCC59",
|
||||
"nav-highlight": "#4296F9FF",
|
||||
"nav-windowing-background": "#CCCCCC33",
|
||||
"nav-windowing-highlight": "#FFFFFFB2",
|
||||
"plot-histogram": "#E5B200FF",
|
||||
"plot-histogram-hovered": "#FF9900FF",
|
||||
"plot-lines": "#9B9B9BFF",
|
||||
"plot-lines-hovered": "#FF6D59FF",
|
||||
"popup-background": "#141414EF",
|
||||
"resize-grip": "#4296F933",
|
||||
"resize-grip-active": "#4296F9F2",
|
||||
"resize-grip-hovered": "#4296F9AA",
|
||||
"scrollbar-background": "#05050587",
|
||||
"scrollbar-grab": "#4F4F4FFF",
|
||||
"scrollbar-grab-active": "#828282FF",
|
||||
"scrollbar-grab-hovered": "#686868FF",
|
||||
"separator": "#6D6D7F7F",
|
||||
"separator-active": "#1966BFFF",
|
||||
"separator-hovered": "#1966BFC6",
|
||||
"slider-grab": "#3D84E0FF",
|
||||
"slider-grab-active": "#4296F9FF",
|
||||
"tab": "#2D5993DB",
|
||||
"tab-active": "#3268ADFF",
|
||||
"tab-hovered": "#4296F9CC",
|
||||
"tab-unfocused": "#111A25F7",
|
||||
"tab-unfocused-active": "#22426CFF",
|
||||
"table-border-light": "#3A3A3FFF",
|
||||
"table-border-strong": "#4F4F59FF",
|
||||
"table-header-background": "#303033FF",
|
||||
"table-row-background": "#00000000",
|
||||
"table-row-background-alt": "#FFFFFF0F",
|
||||
"text": "#FFFFFFFF",
|
||||
"text-disabled": "#7F7F7FFF",
|
||||
"text-selected-background": "#4296F959",
|
||||
"title-background": "#232323FF",
|
||||
"title-background-active": "#232323FF",
|
||||
"title-background-collapse": "#232323FF",
|
||||
"window-background": "#0F0F0FEF"
|
||||
},
|
||||
"implot": {
|
||||
"axis-bg": "#00000001",
|
||||
"axis-bg-active": "#00000001",
|
||||
"axis-bg-hovered": "#00000001",
|
||||
"axis-grid": "#FFFFFF3F",
|
||||
"axis-text": "#FFFFFFFF",
|
||||
"axis-tick": "#00000001",
|
||||
"crosshairs": "#FFFFFF7F",
|
||||
"error-bar": "#00000001",
|
||||
"fill": "#00000001",
|
||||
"frame-bg": "#FFFFFF11",
|
||||
"inlay-text": "#FFFFFFFF",
|
||||
"legend-bg": "#141414EF",
|
||||
"legend-border": "#6D6D7F7F",
|
||||
"legend-text": "#FFFFFFFF",
|
||||
"line": "#00000001",
|
||||
"marker-fill": "#00000001",
|
||||
"marker-outline": "#00000001",
|
||||
"plot-bg": "#0000007F",
|
||||
"plot-border": "#6D6D7F7F",
|
||||
"selection": "#FF9900FF",
|
||||
"title-text": "#FFFFFFFF"
|
||||
},
|
||||
"imnodes": {
|
||||
"box-selector": "#AB000000",
|
||||
"box-selector-outline": "#00E20000",
|
||||
"grid-background": "#42009900",
|
||||
"grid-line": "#63008100",
|
||||
"grid-line-primary": "#EA005B00",
|
||||
"link": "#06539BFF",
|
||||
"link-hovered": "#672A78FF",
|
||||
"link-selected": "#DBB377FF",
|
||||
"mini-map-background": "#69001B00",
|
||||
"mini-map-background-hovered": "#7100B5A6",
|
||||
"mini-map-canvas": "#00000000",
|
||||
"mini-map-canvas-outline": "#00000000",
|
||||
"mini-map-link": "#00000000",
|
||||
"mini-map-link-selected": "#00000000",
|
||||
"mini-map-node-background": "#00000000",
|
||||
"mini-map-node-background-hovered": "#00000000",
|
||||
"mini-map-node-background-selected": "#00000000",
|
||||
"mini-map-node-outline": "#00000000",
|
||||
"mini-map-outline": "#00000000",
|
||||
"mini-map-outline-hovered": "#00000000",
|
||||
"node-background": "#282850FF",
|
||||
"node-background-hovered": "#3C3C64FF",
|
||||
"node-background-selected": "#505078FF",
|
||||
"node-outline": "#E6E6E6FF",
|
||||
"pin": "#4DC69BFF",
|
||||
"pin-hovered": "#00000000",
|
||||
"title-bar": "#E74C3CFF",
|
||||
"title-bar-hovered": "#F1C40FFF",
|
||||
"title-bar-selected": "#388B42FF"
|
||||
},
|
||||
"imhex": {
|
||||
"desc-button": "#141414FF",
|
||||
"desc-button-active": "#3C3C3CFF",
|
||||
"desc-button-hovered": "#282828FF",
|
||||
"highlight": "#4DC69BFF",
|
||||
"toolbar-blue": "#06539BFF",
|
||||
"toolbar-brown": "#DBB377FF",
|
||||
"toolbar-gray": "#E6E6E6FF",
|
||||
"toolbar-green": "#388B42FF",
|
||||
"toolbar-purple": "#672A78FF",
|
||||
"toolbar-red": "#E74C3CFF",
|
||||
"toolbar-yellow": "#F1C40FFF"
|
||||
},
|
||||
"text-editor": {
|
||||
"background": "#101010FF",
|
||||
"breakpoint": "#0080F040",
|
||||
"char-literal": "#E0A070FF",
|
||||
"comment": "#206020FF",
|
||||
"current-line-edge": "#A0A0A040",
|
||||
"current-line-fill": "#00000040",
|
||||
"current-line-fill-inactive": "#80808040",
|
||||
"cursor": "#E0E0E0FF",
|
||||
"default": "#7F7F7FFF",
|
||||
"error-marker": "#FF200080",
|
||||
"identifier": "#AAAAAAFF",
|
||||
"keyword": "#569CD6FF",
|
||||
"known-identifier": "#4DC69BFF",
|
||||
"line-number": "#007070FF",
|
||||
"multi-line-comment": "#206040FF",
|
||||
"number": "#00FF00FF",
|
||||
"preproc-identifier": "#A040C0FF",
|
||||
"preprocessor": "#808040FF",
|
||||
"punctuation": "#FFFFFFFF",
|
||||
"selection": "#2060A080",
|
||||
"string": "#E07070FF"
|
||||
}
|
||||
}
|
||||
}
|
153
plugins/builtin/romfs/themes/light.json
Normal file
153
plugins/builtin/romfs/themes/light.json
Normal file
@ -0,0 +1,153 @@
|
||||
{
|
||||
"name": "Light",
|
||||
"image_postfix": "_light",
|
||||
"colors": {
|
||||
"imgui": {
|
||||
"border": "#0000004C",
|
||||
"border-shadow": "#00000000",
|
||||
"button": "#4296F966",
|
||||
"button-active": "#0F87F9FF",
|
||||
"button-hovered": "#4296F9FF",
|
||||
"check-mark": "#4296F9FF",
|
||||
"child-background": "#00000000",
|
||||
"docking-empty-background": "#EFEFEFFF",
|
||||
"docking-preview": "#4296F937",
|
||||
"drag-drop-target": "#4296F9F2",
|
||||
"frame-background": "#FFFFFFFF",
|
||||
"frame-background-active": "#4296F9AA",
|
||||
"frame-background-hovered": "#4296F966",
|
||||
"header": "#4296F94F",
|
||||
"header-active": "#4296F9FF",
|
||||
"header-hovered": "#4296F9CC",
|
||||
"menu-bar-background": "#DBDBDBFF",
|
||||
"modal-window-dim-background": "#33333359",
|
||||
"nav-highlight": "#4296F9CC",
|
||||
"nav-windowing-background": "#33333333",
|
||||
"nav-windowing-highlight": "#B2B2B2B2",
|
||||
"plot-histogram": "#E5B200FF",
|
||||
"plot-histogram-hovered": "#FF7200FF",
|
||||
"plot-lines": "#636363FF",
|
||||
"plot-lines-hovered": "#FF6D59FF",
|
||||
"popup-background": "#FFFFFFF9",
|
||||
"resize-grip": "#5959592B",
|
||||
"resize-grip-active": "#4296F9F2",
|
||||
"resize-grip-hovered": "#4296F9AA",
|
||||
"scrollbar-background": "#F9F9F987",
|
||||
"scrollbar-grab": "#AFAFAFCC",
|
||||
"scrollbar-grab-active": "#7C7C7CFF",
|
||||
"scrollbar-grab-hovered": "#7C7C7CCC",
|
||||
"separator": "#6363639E",
|
||||
"separator-active": "#2370CCFF",
|
||||
"separator-hovered": "#2370CCC6",
|
||||
"slider-grab": "#4296F9C6",
|
||||
"slider-grab-active": "#7589CC99",
|
||||
"tab": "#C2CBD5ED",
|
||||
"tab-active": "#97B9E1FF",
|
||||
"tab-hovered": "#4296F9CC",
|
||||
"tab-unfocused": "#EAECEEFB",
|
||||
"tab-unfocused-active": "#BDD1E9FF",
|
||||
"table-border-light": "#ADADBCFF",
|
||||
"table-border-strong": "#9191A3FF",
|
||||
"table-header-background": "#C6DDF9FF",
|
||||
"table-row-background": "#00000000",
|
||||
"table-row-background-alt": "#4C4C4C16",
|
||||
"text": "#000000FF",
|
||||
"text-disabled": "#999999FF",
|
||||
"text-selected-background": "#4296F959",
|
||||
"title-background": "#DBDBDBFF",
|
||||
"title-background-active": "#DBDBDBFF",
|
||||
"title-background-collapse": "#DBDBDBFF",
|
||||
"window-background": "#EFEFEFFF"
|
||||
},
|
||||
"implot": {
|
||||
"axis-bg": "#00000001",
|
||||
"axis-bg-active": "#00000001",
|
||||
"axis-bg-hovered": "#00000001",
|
||||
"axis-grid": "#FFFFFFFF",
|
||||
"axis-text": "#000000FF",
|
||||
"axis-tick": "#0000003F",
|
||||
"crosshairs": "#0000007F",
|
||||
"error-bar": "#00000001",
|
||||
"fill": "#00000001",
|
||||
"frame-bg": "#FFFFFFFF",
|
||||
"inlay-text": "#000000FF",
|
||||
"legend-bg": "#FFFFFFF9",
|
||||
"legend-border": "#D1D1D1CC",
|
||||
"legend-text": "#000000FF",
|
||||
"line": "#00000001",
|
||||
"marker-fill": "#00000001",
|
||||
"marker-outline": "#00000001",
|
||||
"plot-bg": "#6B91FF21",
|
||||
"plot-border": "#00000000",
|
||||
"selection": "#D1A307FF",
|
||||
"title-text": "#000000FF"
|
||||
},
|
||||
"imnodes": {
|
||||
"box-selector": "#00000000",
|
||||
"box-selector-outline": "#00E20000",
|
||||
"grid-background": "#00000000",
|
||||
"grid-line": "#00000000",
|
||||
"grid-line-primary": "#00000000",
|
||||
"link": "#06539BFF",
|
||||
"link-hovered": "#672A78FF",
|
||||
"link-selected": "#DBB377FF",
|
||||
"mini-map-background": "#00000000",
|
||||
"mini-map-background-hovered": "#0000B00C",
|
||||
"mini-map-canvas": "#00000000",
|
||||
"mini-map-canvas-outline": "#00000000",
|
||||
"mini-map-link": "#00000000",
|
||||
"mini-map-link-selected": "#00000000",
|
||||
"mini-map-node-background": "#00000000",
|
||||
"mini-map-node-background-hovered": "#00000000",
|
||||
"mini-map-node-background-selected": "#00000000",
|
||||
"mini-map-node-outline": "#00000000",
|
||||
"mini-map-outline": "#00000000",
|
||||
"mini-map-outline-hovered": "#00000000",
|
||||
"node-background": "#282850FF",
|
||||
"node-background-hovered": "#3C3C64FF",
|
||||
"node-background-selected": "#505078FF",
|
||||
"node-outline": "#E6E6E6FF",
|
||||
"pin": "#4DC69BFF",
|
||||
"pin-hovered": "#00000000",
|
||||
"title-bar": "#E74C3CFF",
|
||||
"title-bar-hovered": "#F1C40FFF",
|
||||
"title-bar-selected": "#388B42FF"
|
||||
},
|
||||
"imhex": {
|
||||
"desc-button": "#E6E6E6FF",
|
||||
"desc-button-active": "#BEBEBEFF",
|
||||
"desc-button-hovered": "#D2D2D2FF",
|
||||
"highlight": "#299770FF",
|
||||
"toolbar-blue": "#06539BFF",
|
||||
"toolbar-brown": "#DBB377FF",
|
||||
"toolbar-gray": "#191919FF",
|
||||
"toolbar-green": "#388B42FF",
|
||||
"toolbar-purple": "#672A78FF",
|
||||
"toolbar-red": "#E74C3CFF",
|
||||
"toolbar-yellow": "#F1C40FFF"
|
||||
},
|
||||
"text-editor": {
|
||||
"background": "#FFFFFFFF",
|
||||
"breakpoint": "#0080F080",
|
||||
"char-literal": "#704030FF",
|
||||
"comment": "#205020FF",
|
||||
"current-line-edge": "#00000040",
|
||||
"current-line-fill": "#00000040",
|
||||
"current-line-fill-inactive": "#80808040",
|
||||
"cursor": "#000000FF",
|
||||
"default": "#7F7F7FFF",
|
||||
"error-marker": "#FF1000A0",
|
||||
"identifier": "#404040FF",
|
||||
"keyword": "#060CFFFF",
|
||||
"known-identifier": "#106060FF",
|
||||
"line-number": "#005050FF",
|
||||
"multi-line-comment": "#205040FF",
|
||||
"number": "#008000FF",
|
||||
"preproc-identifier": "#A040C0FF",
|
||||
"preprocessor": "#606040FF",
|
||||
"punctuation": "#000000FF",
|
||||
"selection": "#00006080",
|
||||
"string": "#A02020FF"
|
||||
}
|
||||
}
|
||||
}
|
@ -2,6 +2,7 @@
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/imhex_api.hpp>
|
||||
#include <hex/api/localization.hpp>
|
||||
#include <hex/api/theme_manager.hpp>
|
||||
|
||||
#include <hex/helpers/net.hpp>
|
||||
#include <hex/helpers/utils.hpp>
|
||||
@ -97,27 +98,34 @@ namespace hex::plugin::builtin {
|
||||
|
||||
/* Interface */
|
||||
|
||||
ContentRegistry::Settings::add("hex.builtin.setting.interface", "hex.builtin.setting.interface.color", 0, [](auto name, nlohmann::json &setting) {
|
||||
static int selection = static_cast<int>(setting);
|
||||
ContentRegistry::Settings::add("hex.builtin.setting.interface", "hex.builtin.setting.interface.color", "Dark", [](auto name, nlohmann::json &setting) {
|
||||
static auto selection = static_cast<std::string>(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
|
||||
};
|
||||
const auto themeNames = hex::api::ThemeManager::getThemeNames();
|
||||
bool changed = false;
|
||||
|
||||
if (ImGui::Combo(name.data(), &selection, themes, IM_ARRAYSIZE(themes))) {
|
||||
setting = selection;
|
||||
if (ImGui::BeginCombo(name.data(), selection.c_str())) {
|
||||
if (ImGui::Selectable(api::ThemeManager::NativeTheme, selection == api::ThemeManager::NativeTheme)) {
|
||||
selection = api::ThemeManager::NativeTheme;
|
||||
setting = selection;
|
||||
ImHexApi::System::enableSystemThemeDetection(true);
|
||||
changed = true;
|
||||
}
|
||||
|
||||
ImHexApi::System::enableSystemThemeDetection(selection == 0);
|
||||
if (selection != 0)
|
||||
ImHexApi::System::setTheme(static_cast<ImHexApi::System::Theme>(selection));
|
||||
for (const auto &themeName : themeNames) {
|
||||
if (ImGui::Selectable(themeName.c_str(), selection == themeName)) {
|
||||
selection = themeName;
|
||||
setting = selection;
|
||||
ImHexApi::System::enableSystemThemeDetection(false);
|
||||
api::ThemeManager::changeTheme(selection);
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
ImGui::EndCombo();
|
||||
}
|
||||
|
||||
return false;
|
||||
return changed;
|
||||
});
|
||||
|
||||
ContentRegistry::Settings::add(
|
||||
@ -569,10 +577,14 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
|
||||
static void loadThemeSettings() {
|
||||
auto theme = ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.color", static_cast<i64>(ImHexApi::System::Theme::Dark));
|
||||
auto theme = ContentRegistry::Settings::read("hex.builtin.setting.interface", "hex.builtin.setting.interface.color", api::ThemeManager::NativeTheme);
|
||||
|
||||
ImHexApi::System::enableSystemThemeDetection(theme == 0);
|
||||
ImHexApi::System::setTheme(static_cast<ImHexApi::System::Theme>(theme));
|
||||
if (theme == api::ThemeManager::NativeTheme)
|
||||
ImHexApi::System::enableSystemThemeDetection(true);
|
||||
else {
|
||||
ImHexApi::System::enableSystemThemeDetection(false);
|
||||
api::ThemeManager::changeTheme(theme);
|
||||
}
|
||||
}
|
||||
|
||||
static void loadFoldersSettings() {
|
||||
|
228
plugins/builtin/source/content/themes.cpp
Normal file
228
plugins/builtin/source/content/themes.cpp
Normal file
@ -0,0 +1,228 @@
|
||||
#include <hex/api/theme_manager.hpp>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <implot.h>
|
||||
#include <hex/ui/imgui_imhex_extensions.h>
|
||||
#include <imnodes.h>
|
||||
#include <TextEditor.h>
|
||||
#include <romfs/romfs.hpp>
|
||||
|
||||
#include <hex/helpers/utils.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/file.hpp>
|
||||
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
void registerThemeHandlers() {
|
||||
api::ThemeManager::addThemeHandler("imgui", [](const std::string &key, const std::string &value) {
|
||||
const static std::map<std::string, ImGuiCol> ColorMap = {
|
||||
{ "text", ImGuiCol_Text },
|
||||
{ "text-disabled", ImGuiCol_TextDisabled },
|
||||
{ "window-background", ImGuiCol_WindowBg },
|
||||
{ "child-background", ImGuiCol_ChildBg },
|
||||
{ "popup-background", ImGuiCol_PopupBg },
|
||||
{ "border", ImGuiCol_Border },
|
||||
{ "border-shadow", ImGuiCol_BorderShadow },
|
||||
{ "frame-background", ImGuiCol_FrameBg },
|
||||
{ "frame-background-hovered", ImGuiCol_FrameBgHovered },
|
||||
{ "frame-background-active", ImGuiCol_FrameBgActive },
|
||||
{ "title-background", ImGuiCol_TitleBg },
|
||||
{ "title-background-active", ImGuiCol_TitleBgActive },
|
||||
{ "title-background-collapse", ImGuiCol_TitleBgCollapsed },
|
||||
{ "menu-bar-background", ImGuiCol_MenuBarBg },
|
||||
{ "scrollbar-background", ImGuiCol_ScrollbarBg },
|
||||
{ "scrollbar-grab", ImGuiCol_ScrollbarGrab },
|
||||
{ "scrollbar-grab-hovered", ImGuiCol_ScrollbarGrabHovered },
|
||||
{ "scrollbar-grab-active", ImGuiCol_ScrollbarGrabActive },
|
||||
{ "check-mark", ImGuiCol_CheckMark },
|
||||
{ "slider-grab", ImGuiCol_SliderGrab },
|
||||
{ "slider-grab-active", ImGuiCol_SliderGrabActive },
|
||||
{ "button", ImGuiCol_Button },
|
||||
{ "button-hovered", ImGuiCol_ButtonHovered },
|
||||
{ "button-active", ImGuiCol_ButtonActive },
|
||||
{ "header", ImGuiCol_Header },
|
||||
{ "header-hovered", ImGuiCol_HeaderHovered },
|
||||
{ "header-active", ImGuiCol_HeaderActive },
|
||||
{ "separator", ImGuiCol_Separator },
|
||||
{ "separator-hovered", ImGuiCol_SeparatorHovered },
|
||||
{ "separator-active", ImGuiCol_SeparatorActive },
|
||||
{ "resize-grip", ImGuiCol_ResizeGrip },
|
||||
{ "resize-grip-hovered", ImGuiCol_ResizeGripHovered },
|
||||
{ "resize-grip-active", ImGuiCol_ResizeGripActive },
|
||||
{ "tab", ImGuiCol_Tab },
|
||||
{ "tab-hovered", ImGuiCol_TabHovered },
|
||||
{ "tab-active", ImGuiCol_TabActive },
|
||||
{ "tab-unfocused", ImGuiCol_TabUnfocused },
|
||||
{ "tab-unfocused-active", ImGuiCol_TabUnfocusedActive },
|
||||
{ "docking-preview", ImGuiCol_DockingPreview },
|
||||
{ "docking-empty-background", ImGuiCol_DockingEmptyBg },
|
||||
{ "plot-lines", ImGuiCol_PlotLines },
|
||||
{ "plot-lines-hovered", ImGuiCol_PlotLinesHovered },
|
||||
{ "plot-histogram", ImGuiCol_PlotHistogram },
|
||||
{ "plot-histogram-hovered", ImGuiCol_PlotHistogramHovered },
|
||||
{ "table-header-background", ImGuiCol_TableHeaderBg },
|
||||
{ "table-border-strong", ImGuiCol_TableBorderStrong },
|
||||
{ "table-border-light", ImGuiCol_TableBorderLight },
|
||||
{ "table-row-background", ImGuiCol_TableRowBg },
|
||||
{ "table-row-background-alt", ImGuiCol_TableRowBgAlt },
|
||||
{ "text-selected-background", ImGuiCol_TextSelectedBg },
|
||||
{ "drag-drop-target", ImGuiCol_DragDropTarget },
|
||||
{ "nav-highlight", ImGuiCol_NavHighlight },
|
||||
{ "nav-windowing-highlight", ImGuiCol_NavWindowingHighlight },
|
||||
{ "nav-windowing-background", ImGuiCol_NavWindowingDimBg },
|
||||
{ "modal-window-dim-background", ImGuiCol_ModalWindowDimBg }
|
||||
};
|
||||
|
||||
auto color = api::ThemeManager::parseColorString(value);
|
||||
auto colors = ImGui::GetStyle().Colors;
|
||||
|
||||
if (ColorMap.contains(key) && color.has_value())
|
||||
colors[ColorMap.at(key)] = color->Value;
|
||||
});
|
||||
|
||||
api::ThemeManager::addThemeHandler("implot", [](const std::string &key, const std::string &value) {
|
||||
const static std::map<std::string, ImPlotCol> ColorMap = {
|
||||
{ "line", ImPlotCol_Line },
|
||||
{ "fill", ImPlotCol_Fill },
|
||||
{ "marker-outline", ImPlotCol_MarkerOutline },
|
||||
{ "marker-fill", ImPlotCol_MarkerFill },
|
||||
{ "error-bar", ImPlotCol_ErrorBar },
|
||||
{ "frame-bg", ImPlotCol_FrameBg },
|
||||
{ "plot-bg", ImPlotCol_PlotBg },
|
||||
{ "plot-border", ImPlotCol_PlotBorder },
|
||||
{ "legend-bg", ImPlotCol_LegendBg },
|
||||
{ "legend-border", ImPlotCol_LegendBorder },
|
||||
{ "legend-text", ImPlotCol_LegendText },
|
||||
{ "title-text", ImPlotCol_TitleText },
|
||||
{ "inlay-text", ImPlotCol_InlayText },
|
||||
{ "axis-text", ImPlotCol_AxisText },
|
||||
{ "axis-grid", ImPlotCol_AxisGrid },
|
||||
{ "axis-tick", ImPlotCol_AxisTick },
|
||||
{ "axis-bg", ImPlotCol_AxisBg },
|
||||
{ "axis-bg-hovered", ImPlotCol_AxisBgHovered },
|
||||
{ "axis-bg-active", ImPlotCol_AxisBgActive },
|
||||
{ "selection", ImPlotCol_Selection },
|
||||
{ "crosshairs", ImPlotCol_Crosshairs }
|
||||
};
|
||||
|
||||
auto color = api::ThemeManager::parseColorString(value);
|
||||
auto &colors = ImPlot::GetStyle().Colors;
|
||||
|
||||
if (ColorMap.contains(key) && color.has_value())
|
||||
colors[ColorMap.at(key)] = color->Value;
|
||||
});
|
||||
|
||||
api::ThemeManager::addThemeHandler("imnodes", [](const std::string &key, const std::string &value) {
|
||||
const static std::map<std::string, ImNodesCol> ColorMap = {
|
||||
{ "node-background", ImNodesCol_NodeBackground },
|
||||
{ "node-background-hovered", ImNodesCol_NodeBackgroundHovered },
|
||||
{ "node-background-selected", ImNodesCol_NodeBackgroundSelected },
|
||||
{ "node-outline", ImNodesCol_NodeOutline },
|
||||
{ "title-bar", ImNodesCol_TitleBar },
|
||||
{ "title-bar-hovered", ImNodesCol_TitleBarHovered },
|
||||
{ "title-bar-selected", ImNodesCol_TitleBarSelected },
|
||||
{ "link", ImNodesCol_Link },
|
||||
{ "link-hovered", ImNodesCol_LinkHovered },
|
||||
{ "link-selected", ImNodesCol_LinkSelected },
|
||||
{ "pin", ImNodesCol_Pin },
|
||||
{ "pin-hovered", ImNodesCol_PinHovered },
|
||||
{ "box-selector", ImNodesCol_BoxSelector },
|
||||
{ "box-selector-outline", ImNodesCol_BoxSelectorOutline },
|
||||
{ "grid-background", ImNodesCol_GridBackground },
|
||||
{ "grid-line", ImNodesCol_GridLine },
|
||||
{ "grid-line-primary", ImNodesCol_GridLinePrimary },
|
||||
{ "mini-map-background", ImNodesCol_MiniMapBackground },
|
||||
{ "mini-map-background-hovered", ImNodesCol_MiniMapBackgroundHovered },
|
||||
{ "mini-map-outline", ImNodesCol_MiniMapOutline },
|
||||
{ "mini-map-outline-hovered", ImNodesCol_MiniMapOutlineHovered },
|
||||
{ "mini-map-node-background", ImNodesCol_MiniMapNodeBackground },
|
||||
{ "mini-map-node-background-hovered", ImNodesCol_MiniMapNodeBackgroundHovered },
|
||||
{ "mini-map-node-background-selected", ImNodesCol_MiniMapNodeBackgroundSelected },
|
||||
{ "mini-map-node-outline", ImNodesCol_MiniMapNodeOutline },
|
||||
{ "mini-map-link", ImNodesCol_MiniMapLink },
|
||||
{ "mini-map-link-selected", ImNodesCol_MiniMapLinkSelected },
|
||||
{ "mini-map-canvas", ImNodesCol_MiniMapCanvas },
|
||||
{ "mini-map-canvas-outline", ImNodesCol_MiniMapCanvasOutline },
|
||||
};
|
||||
|
||||
auto color = api::ThemeManager::parseColorString(value);
|
||||
auto &colors = ImNodes::GetStyle().Colors;
|
||||
|
||||
if (ColorMap.contains(key) && color.has_value())
|
||||
colors[ColorMap.at(key)] = *color;
|
||||
});
|
||||
|
||||
api::ThemeManager::addThemeHandler("imhex", [](const std::string &key, const std::string &value) {
|
||||
const static std::map<std::string, ImGuiCustomCol> ColorMap = {
|
||||
{ "desc-button", ImGuiCustomCol_DescButton },
|
||||
{ "desc-button-hovered", ImGuiCustomCol_DescButtonHovered },
|
||||
{ "desc-button-active", ImGuiCustomCol_DescButtonActive },
|
||||
{ "toolbar-gray", ImGuiCustomCol_ToolbarGray },
|
||||
{ "toolbar-red", ImGuiCustomCol_ToolbarRed },
|
||||
{ "toolbar-yellow", ImGuiCustomCol_ToolbarYellow },
|
||||
{ "toolbar-green", ImGuiCustomCol_ToolbarGreen },
|
||||
{ "toolbar-blue", ImGuiCustomCol_ToolbarBlue },
|
||||
{ "toolbar-purple", ImGuiCustomCol_ToolbarPurple },
|
||||
{ "toolbar-brown", ImGuiCustomCol_ToolbarBrown },
|
||||
{ "highlight", ImGuiCustomCol_Highlight }
|
||||
};
|
||||
|
||||
auto color = api::ThemeManager::parseColorString(value);
|
||||
auto &colors = static_cast<ImGui::ImHexCustomData *>(GImGui->IO.UserData)->Colors;
|
||||
|
||||
if (ColorMap.contains(key) && color.has_value())
|
||||
colors[ColorMap.at(key)] = color->Value;
|
||||
});
|
||||
|
||||
api::ThemeManager::addThemeHandler("text-editor", [](const std::string &key, const std::string &value) {
|
||||
using enum TextEditor::PaletteIndex;
|
||||
const static std::map<std::string, TextEditor::PaletteIndex> ColorMap = {
|
||||
{ "default", Default },
|
||||
{ "keyword", Keyword },
|
||||
{ "number", Number },
|
||||
{ "string", String },
|
||||
{ "char-literal", CharLiteral },
|
||||
{ "punctuation", Punctuation },
|
||||
{ "preprocessor", Preprocessor },
|
||||
{ "identifier", Identifier },
|
||||
{ "known-identifier", KnownIdentifier },
|
||||
{ "preproc-identifier", PreprocIdentifier },
|
||||
{ "comment", Comment },
|
||||
{ "multi-line-comment", MultiLineComment },
|
||||
{ "background", Background },
|
||||
{ "cursor", Cursor },
|
||||
{ "selection", Selection },
|
||||
{ "error-marker", ErrorMarker },
|
||||
{ "breakpoint", Breakpoint },
|
||||
{ "line-number", LineNumber },
|
||||
{ "current-line-fill", CurrentLineFill },
|
||||
{ "current-line-fill-inactive", CurrentLineFillInactive },
|
||||
{ "current-line-edge", CurrentLineEdge }
|
||||
};
|
||||
|
||||
auto color = api::ThemeManager::parseColorString(value);
|
||||
auto colors = TextEditor::GetPalette();
|
||||
|
||||
if (ColorMap.contains(key) && color.has_value())
|
||||
colors[size_t(ColorMap.at(key))] = ImU32(*color);
|
||||
|
||||
TextEditor::SetPalette(colors);
|
||||
});
|
||||
}
|
||||
|
||||
void registerThemes() {
|
||||
// Load built-in themes
|
||||
for (const auto &theme : romfs::list("themes")) {
|
||||
api::ThemeManager::addTheme(std::string(romfs::get(theme).string()));
|
||||
}
|
||||
|
||||
// Load user themes
|
||||
for (const auto &themeFolder : fs::getDefaultPaths(fs::ImHexPath::Themes)) {
|
||||
for (const auto &theme : std::fs::directory_iterator(themeFolder)) {
|
||||
if (theme.is_regular_file())
|
||||
api::ThemeManager::addTheme(fs::File(theme.path(), fs::File::Mode::Read).readString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -15,23 +15,6 @@
|
||||
namespace hex::plugin::builtin {
|
||||
|
||||
ViewDataProcessor::ViewDataProcessor() : View("hex.builtin.view.data_processor.name") {
|
||||
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;
|
||||
});
|
||||
|
||||
ProjectFile::registerPerProviderHandler({
|
||||
.basePath = "data_processor.json",
|
||||
.required = false,
|
||||
|
@ -828,21 +828,6 @@ namespace hex::plugin::builtin {
|
||||
this->m_textEditor.SetTextLines(lines);
|
||||
}
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static void createNestedMenu(const std::vector<std::string> &menus, const std::function<void()> &function) {
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/localization.hpp>
|
||||
#include <hex/api/plugin_manager.hpp>
|
||||
#include <hex/api/theme_manager.hpp>
|
||||
#include <hex/ui/view.hpp>
|
||||
#include <hex/helpers/fs.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
@ -419,12 +420,14 @@ namespace hex::plugin::builtin {
|
||||
{
|
||||
auto theme = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color");
|
||||
|
||||
if (theme.is_number()) {
|
||||
static int lastTheme = 0;
|
||||
if (theme.is_string()) {
|
||||
if (theme != api::ThemeManager::NativeTheme) {
|
||||
static std::string lastTheme;
|
||||
|
||||
if (const int thisTheme = theme.get<int>(); thisTheme != lastTheme) {
|
||||
EventManager::post<RequestChangeTheme>(thisTheme);
|
||||
lastTheme = thisTheme;
|
||||
if (const auto thisTheme = theme.get<std::string>(); thisTheme != lastTheme) {
|
||||
EventManager::post<RequestChangeTheme>(thisTheme);
|
||||
lastTheme = thisTheme;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -448,51 +451,16 @@ namespace hex::plugin::builtin {
|
||||
}
|
||||
});
|
||||
|
||||
(void)EventManager::subscribe<RequestChangeTheme>([](u32 theme) {
|
||||
(void)EventManager::subscribe<RequestChangeTheme>([](const std::string &theme) {
|
||||
auto changeTexture = [&](const std::string &path) {
|
||||
auto textureData = romfs::get(path);
|
||||
|
||||
return ImGui::Texture(reinterpret_cast<const ImU8*>(textureData.data()), textureData.size());
|
||||
};
|
||||
|
||||
switch (theme) {
|
||||
default:
|
||||
case 1: /* Dark theme */
|
||||
{
|
||||
ImGui::StyleColorsDark();
|
||||
ImGui::StyleCustomColorsDark();
|
||||
ImPlot::StyleColorsDark();
|
||||
s_bannerTexture = changeTexture("banner_dark.png");
|
||||
s_backdropTexture = changeTexture("backdrop_dark.png");
|
||||
|
||||
break;
|
||||
}
|
||||
case 2: /* Light theme */
|
||||
{
|
||||
ImGui::StyleColorsLight();
|
||||
ImGui::StyleCustomColorsLight();
|
||||
ImPlot::StyleColorsLight();
|
||||
s_bannerTexture = changeTexture("banner_light.png");
|
||||
s_backdropTexture = changeTexture("backdrop_light.png");
|
||||
|
||||
break;
|
||||
}
|
||||
case 3: /* Classic theme */
|
||||
{
|
||||
ImGui::StyleColorsClassic();
|
||||
ImGui::StyleCustomColorsClassic();
|
||||
ImPlot::StyleColorsClassic();
|
||||
s_bannerTexture = changeTexture("banner_dark.png");
|
||||
s_backdropTexture = changeTexture("backdrop_dark.png");
|
||||
|
||||
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];
|
||||
api::ThemeManager::changeTheme(theme);
|
||||
s_bannerTexture = changeTexture(hex::format("banner{}.png", api::ThemeManager::getThemeImagePostfix()));
|
||||
s_backdropTexture = changeTexture(hex::format("backdrop{}.png", api::ThemeManager::getThemeImagePostfix()));
|
||||
|
||||
if (!s_bannerTexture.isValid()) {
|
||||
log::error("Failed to load banner texture!");
|
||||
|
@ -26,6 +26,8 @@ namespace hex::plugin::builtin {
|
||||
void createWelcomeScreen();
|
||||
void registerViews();
|
||||
void registerShortcuts();
|
||||
void registerThemeHandlers();
|
||||
void registerThemes();
|
||||
|
||||
void addFooterItems();
|
||||
void addToolbarItems();
|
||||
@ -59,6 +61,8 @@ IMHEX_PLUGIN_SETUP("Built-in", "WerWolv", "Default ImHex functionality") {
|
||||
createWelcomeScreen();
|
||||
registerViews();
|
||||
registerShortcuts();
|
||||
registerThemeHandlers();
|
||||
registerThemes();
|
||||
|
||||
addFooterItems();
|
||||
addToolbarItems();
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <hex/plugin.hpp>
|
||||
|
||||
#include <hex/api/content_registry.hpp>
|
||||
#include <hex/api/theme_manager.hpp>
|
||||
#include <hex/helpers/logger.hpp>
|
||||
|
||||
#include <romfs/romfs.hpp>
|
||||
@ -20,7 +21,7 @@ namespace hex::plugin::windows {
|
||||
static void detectSystemTheme() {
|
||||
// Setup system theme change detector
|
||||
EventManager::subscribe<EventOSThemeChanged>([] {
|
||||
bool themeFollowSystem = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color") == 0;
|
||||
bool themeFollowSystem = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color") == api::ThemeManager::NativeTheme;
|
||||
if (!themeFollowSystem)
|
||||
return;
|
||||
|
||||
@ -31,7 +32,7 @@ static void detectSystemTheme() {
|
||||
|
||||
auto error = RegQueryValueEx(hkey, "AppsUseLightTheme", nullptr, nullptr, reinterpret_cast<LPBYTE>(&value), &size);
|
||||
if (error == ERROR_SUCCESS) {
|
||||
EventManager::post<RequestChangeTheme>(value == 0 ? 1 : 2);
|
||||
EventManager::post<RequestChangeTheme>(value == 0 ? "Dark" : "Light");
|
||||
} else {
|
||||
ImHexApi::System::impl::setBorderlessWindowMode(false);
|
||||
}
|
||||
@ -41,7 +42,7 @@ static void detectSystemTheme() {
|
||||
});
|
||||
|
||||
EventManager::subscribe<EventWindowInitialized>([=] {
|
||||
bool themeFollowSystem = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color") == 0;
|
||||
bool themeFollowSystem = ContentRegistry::Settings::getSetting("hex.builtin.setting.interface", "hex.builtin.setting.interface.color") == api::ThemeManager::NativeTheme;
|
||||
|
||||
if (themeFollowSystem)
|
||||
EventManager::post<EventOSThemeChanged>();
|
||||
|
Loading…
Reference in New Issue
Block a user