Improve theme preferences and make editor static
This commit is contained in:
parent
01edf59446
commit
9c6f69203d
3 changed files with 79 additions and 48 deletions
42
main.cpp
42
main.cpp
|
@ -17,6 +17,7 @@
|
|||
#include <string>
|
||||
#include <SDL.h>
|
||||
#include <SDL_image.h>
|
||||
#include <filesystem>
|
||||
#if defined(IMGUI_IMPL_OPENGL_ES2)
|
||||
#include <SDL_opengles2.h>
|
||||
#else
|
||||
|
@ -215,6 +216,18 @@ int main(int, char**)
|
|||
}
|
||||
stream.close();
|
||||
}
|
||||
if (is_empty(Theme::themeDir)) {
|
||||
path lightPath = Theme::themeDir / "light.json";
|
||||
path darkPath = Theme::themeDir / "dark.json";
|
||||
if (!exists(lightPath)) {
|
||||
Theme light(false);
|
||||
light.Save(lightPath);
|
||||
}
|
||||
if (!exists(darkPath)) {
|
||||
Theme dark(true);
|
||||
dark.Save(darkPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef __EMSCRIPTEN__
|
||||
// For an Emscripten build we are disabling file-system access, so let's not attempt to do a fopen() of the imgui.ini file.
|
||||
|
@ -312,23 +325,44 @@ int main(int, char**)
|
|||
if (prefs_window) {
|
||||
ImVec2 min_size;
|
||||
min_size.x = ImGui::GetFontSize() * 18;
|
||||
min_size.y = (ImGui::GetStyle().FramePadding.y * 5) + (ImGui::GetFontSize() * 5);
|
||||
min_size.y = (ImGui::GetFrameHeightWithSpacing() * 8) + (ImGui::GetFontSize());
|
||||
ImVec2 max_size;
|
||||
max_size.x = 99999997952; // The compiler says that if this were just 9s it would be turned into this anyways.
|
||||
max_size.y = min_size.y;
|
||||
max_size.y = 99999997952;
|
||||
ImGui::SetNextWindowSizeConstraints(min_size, max_size);
|
||||
ImGui::Begin("Preferences...", &prefs_window);
|
||||
{
|
||||
if (ImGui::Button(ICON_FK_MAGIC "Theme Editor")) {
|
||||
if (ImGui::Button(ICON_FK_MAGIC "Theme Editor", ImVec2(ImGui::GetWindowWidth() - (ImGui::GetStyle().WindowPadding.x * 2.0f), 0))) {
|
||||
theme_editor = true;
|
||||
}
|
||||
static char filter[1024] = {0};
|
||||
ImGui::Text("Filter:"); ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - ImGui::GetStyle().WindowPadding.x);
|
||||
ImGui::InputText("##FilterInput", filter, 1024);
|
||||
ImGui::Text("Select a theme...");
|
||||
if (ImGui::BeginListBox("##Themes", ImVec2(ImGui::GetWindowWidth() - (ImGui::GetStyle().WindowPadding.x * 2.0f), -ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().WindowPadding.y))) {
|
||||
for (auto themePath : Theme::availableThemes) {
|
||||
if (themePath.stem().string().starts_with(filter)) {
|
||||
const bool is_selected = themePath == theme->file_path;
|
||||
if (ImGui::Selectable(themePath.stem().c_str(), is_selected)) {
|
||||
delete theme;
|
||||
theme = new Theme(themePath);
|
||||
break;
|
||||
}
|
||||
if (is_selected) {
|
||||
ImGui::SetItemDefaultFocus();
|
||||
}
|
||||
}
|
||||
}
|
||||
ImGui::EndListBox();
|
||||
}
|
||||
ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - (ImGui::GetStyle().FramePadding.x * 4));
|
||||
ImGui::SliderFloat("##AccentColor", &accent_color, 0.0, 360.0, "UI hue: %.0f°", ImGuiSliderFlags_NoRoundToFormat);
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
if (theme_editor) {
|
||||
theme->ShowEditor(&theme_editor, theme);
|
||||
Theme::ShowEditor(&theme_editor, theme);
|
||||
}
|
||||
theme->Apply(accent_color);
|
||||
fileDialog.Display();
|
||||
|
|
73
theme.cpp
73
theme.cpp
|
@ -12,11 +12,18 @@
|
|||
using namespace std::filesystem;
|
||||
using namespace std::numbers;
|
||||
const char* Theme::prefPath = NULL;
|
||||
path Theme::themeDir = path();
|
||||
std::set<path> Theme::availableThemes = std::set<path>();
|
||||
bool Theme::ShowEditor(bool* open, Theme* &theme) {
|
||||
static ImGui::FileBrowser importDialog;
|
||||
static ImGui::FileBrowser exportDialog;
|
||||
static bool loadOpen = false;
|
||||
static bool saveAsOpen = false;
|
||||
ImGui::Begin("Theme Editor", open);
|
||||
ImGuiStyle *ref = &style;
|
||||
ImGuiStyle& style = theme->style;
|
||||
ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.50f);
|
||||
if (ImGui::Button("Create light")) {
|
||||
ImVec2 buttonSize = ImVec2((ImGui::GetWindowWidth() * 0.50f) - (ImGui::GetStyle().WindowPadding.x) - (ImGui::GetStyle().ItemSpacing.x * 0.5f), 0);
|
||||
if (ImGui::Button("Create light", buttonSize)) {
|
||||
delete theme;
|
||||
theme = new Theme(false);
|
||||
|
||||
|
@ -25,7 +32,7 @@ bool Theme::ShowEditor(bool* open, Theme* &theme) {
|
|||
return true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Create dark")) {
|
||||
if (ImGui::Button("Create dark", buttonSize)) {
|
||||
delete theme;
|
||||
theme = new Theme(true);
|
||||
|
||||
|
@ -33,7 +40,7 @@ bool Theme::ShowEditor(bool* open, Theme* &theme) {
|
|||
ImGui::End();
|
||||
return true;
|
||||
}
|
||||
if (ImGui::Button("Import...")) {
|
||||
if (ImGui::Button("Import...", buttonSize)) {
|
||||
importDialog.SetTitle("Import theme...");
|
||||
importDialog.SetTypeFilters({ ".json"});
|
||||
std::string userdir = std::getenv(
|
||||
|
@ -47,7 +54,7 @@ bool Theme::ShowEditor(bool* open, Theme* &theme) {
|
|||
importDialog.Open();
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Export...")) {
|
||||
if (ImGui::Button("Export...", buttonSize)) {
|
||||
exportDialog = ImGui::FileBrowser(ImGuiFileBrowserFlags_EnterNewFilename|ImGuiFileBrowserFlags_CreateNewDir);
|
||||
exportDialog.SetTitle("Export theme...");
|
||||
exportDialog.SetTypeFilters({ ".json"});
|
||||
|
@ -63,9 +70,9 @@ bool Theme::ShowEditor(bool* open, Theme* &theme) {
|
|||
}
|
||||
importDialog.Display();
|
||||
exportDialog.Display();
|
||||
if (!file_path.empty()) {
|
||||
if (ImGui::Button("Revert")) {
|
||||
string file_path_backup = file_path;
|
||||
if (!theme->file_path.empty()) {
|
||||
if (ImGui::Button("Revert", buttonSize)) {
|
||||
string file_path_backup = theme->file_path;
|
||||
delete theme;
|
||||
theme = new Theme(file_path_backup);
|
||||
ImGui::PopItemWidth();
|
||||
|
@ -73,15 +80,15 @@ bool Theme::ShowEditor(bool* open, Theme* &theme) {
|
|||
return true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Save")) {
|
||||
Save(file_path);
|
||||
if (ImGui::Button("Save", buttonSize)) {
|
||||
theme->Save(theme->file_path);
|
||||
}
|
||||
}
|
||||
if (ImGui::Button("Load...")) {
|
||||
if (ImGui::Button("Load...", buttonSize)) {
|
||||
loadOpen = true;
|
||||
}
|
||||
ImGui::SameLine();
|
||||
if (ImGui::Button("Save as...")) {
|
||||
if (ImGui::Button("Save as...", buttonSize)) {
|
||||
saveAsOpen = true;
|
||||
}
|
||||
|
||||
|
@ -140,22 +147,14 @@ bool Theme::ShowEditor(bool* open, Theme* &theme) {
|
|||
continue;
|
||||
ImGui::PushID(i);
|
||||
ImGui::ColorEdit4("##color", (float*)&style.Colors[i], ImGuiColorEditFlags_AlphaBar | alpha_flags | ImGuiColorEditFlags_DisplayHSV);
|
||||
if (memcmp(&style.Colors[i], &ref->Colors[i], sizeof(ImVec4)) != 0)
|
||||
{
|
||||
// Tips: in a real user application, you may want to merge and use an icon font into the main font,
|
||||
// so instead of "Save"/"Revert" you'd use icons!
|
||||
// Read the FAQ and docs/FONTS.md about using icon fonts. It's really easy and super convenient!
|
||||
ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Save")) { ref->Colors[i] = style.Colors[i]; }
|
||||
ImGui::SameLine(0.0f, style.ItemInnerSpacing.x); if (ImGui::Button("Revert")) { style.Colors[i] = ref->Colors[i]; }
|
||||
}
|
||||
ImGui::SameLine(0.0f, style.ItemInnerSpacing.x);
|
||||
ImGui::TextUnformatted(name);
|
||||
bool hueEnabled = HueEnabledColors.contains(i);
|
||||
bool hueEnabled = theme->HueEnabledColors.contains(i);
|
||||
if (ImGui::Checkbox("Match accent color hue", &hueEnabled)) {
|
||||
if (hueEnabled) {
|
||||
HueEnabledColors.insert(i);
|
||||
theme->HueEnabledColors.insert(i);
|
||||
} else {
|
||||
HueEnabledColors.erase(i);
|
||||
theme->HueEnabledColors.erase(i);
|
||||
}
|
||||
}
|
||||
ImGui::PopID();
|
||||
|
@ -174,12 +173,12 @@ bool Theme::ShowEditor(bool* open, Theme* &theme) {
|
|||
if (importDialog.HasSelected()) {
|
||||
path selected_path = importDialog.GetSelected();
|
||||
path filename = selected_path.filename();
|
||||
copy_file(selected_path, themeDir / filename);
|
||||
availableThemes.insert(filename);
|
||||
copy_file(selected_path, theme->themeDir / filename);
|
||||
theme->availableThemes.insert(filename);
|
||||
}
|
||||
if (exportDialog.HasSelected()) {
|
||||
path selected_path = importDialog.GetSelected();
|
||||
Save(selected_path);
|
||||
theme->Save(selected_path);
|
||||
}
|
||||
if (loadOpen) {
|
||||
ImGui::OpenPopup("Load...");
|
||||
|
@ -187,11 +186,12 @@ bool Theme::ShowEditor(bool* open, Theme* &theme) {
|
|||
if (ImGui::BeginPopupModal("Load...", &loadOpen)) {
|
||||
static path selectedThemePath;
|
||||
static char filter[1024] = {0};
|
||||
ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - (ImGui::GetStyle().WindowPadding.x * 2.0f));
|
||||
ImGui::InputText("Filter: ", filter, 1024);
|
||||
ImGui::Text("Filter:"); ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - ImGui::GetStyle().WindowPadding.x);
|
||||
ImGui::InputText("##FilterInput", filter, 1024);
|
||||
ImGui::Text("Available themes...");
|
||||
if (ImGui::BeginListBox("##Themes", ImVec2(ImGui::GetWindowWidth() - (ImGui::GetStyle().WindowPadding.x * 2.0f), -ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().WindowPadding.y))) {
|
||||
for (auto themePath : availableThemes) {
|
||||
for (auto themePath : Theme::availableThemes) {
|
||||
if (themePath.stem().string().starts_with(filter)) {
|
||||
const bool is_selected = themePath == selectedThemePath;
|
||||
if (ImGui::Selectable(themePath.stem().c_str(), is_selected)) {
|
||||
|
@ -229,11 +229,12 @@ bool Theme::ShowEditor(bool* open, Theme* &theme) {
|
|||
if (ImGui::BeginPopupModal("Save as...", &saveAsOpen)) {
|
||||
static char selectedThemeName[1024] = {0};
|
||||
static char filter[1024] = {0};
|
||||
ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - (ImGui::GetStyle().WindowPadding.x * 2.0f));
|
||||
ImGui::InputText("Filter: ", filter, 1024);
|
||||
ImGui::Text("Filter:"); ImGui::SameLine();
|
||||
ImGui::SetNextItemWidth(ImGui::GetWindowWidth() - ImGui::GetCursorPosX() - ImGui::GetStyle().WindowPadding.x);
|
||||
ImGui::InputText("##FilterInput", filter, 1024);
|
||||
ImGui::Text("Available themes...");
|
||||
if (ImGui::BeginListBox("##Themes", ImVec2(ImGui::GetWindowWidth() - (ImGui::GetStyle().WindowPadding.x * 2.0f), -ImGui::GetFrameHeightWithSpacing() - ImGui::GetTextLineHeightWithSpacing() - ImGui::GetStyle().WindowPadding.y))) {
|
||||
for (auto themePath : availableThemes) {
|
||||
for (auto themePath : Theme::availableThemes) {
|
||||
if (themePath.stem().string().starts_with(filter)) {
|
||||
const bool is_selected = strcmp(themePath.stem().c_str(), selectedThemeName) == 0;
|
||||
if (ImGui::Selectable(themePath.stem().c_str(), is_selected)) {
|
||||
|
@ -254,8 +255,8 @@ bool Theme::ShowEditor(bool* open, Theme* &theme) {
|
|||
selectedThemeName[0] = '\0'; // This empties the string by taking advantage of C strings.
|
||||
filter[0] = '\0';
|
||||
saveAsOpen = false;
|
||||
Save(themeDir / selectedThemePath.replace_extension(".json"));
|
||||
file_path = selectedThemePath;
|
||||
theme->Save(Theme::themeDir / selectedThemePath.replace_extension(".json"));
|
||||
theme->file_path = selectedThemePath;
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();
|
||||
|
@ -342,6 +343,8 @@ void Theme::Save(string path) {
|
|||
updateAvailableThemes();
|
||||
}
|
||||
void Theme::updateAvailableThemes() {
|
||||
themeDir = path(prefPath) / path("themes");
|
||||
create_directories(themeDir);
|
||||
availableThemes.clear();
|
||||
for (auto const& dir_entry : directory_iterator(themeDir)) {
|
||||
if (dir_entry.is_regular_file()) {
|
||||
|
@ -355,8 +358,6 @@ Theme::Theme() {
|
|||
if (prefPath == NULL) {
|
||||
throw std::exception();
|
||||
}
|
||||
themeDir = path(prefPath) / path("themes");
|
||||
create_directories(themeDir);
|
||||
updateAvailableThemes();
|
||||
}
|
||||
|
||||
|
|
12
theme.h
12
theme.h
|
@ -9,19 +9,15 @@ using namespace std::filesystem;
|
|||
|
||||
class Theme {
|
||||
ImGuiStyle style;
|
||||
ImGui::FileBrowser importDialog;
|
||||
ImGui::FileBrowser exportDialog;
|
||||
bool loadOpen = false;
|
||||
bool saveAsOpen = false;
|
||||
std::set<path> availableThemes;
|
||||
void updateAvailableThemes();
|
||||
|
||||
public:
|
||||
path themeDir;
|
||||
static std::set<path> availableThemes;
|
||||
static void updateAvailableThemes();
|
||||
static path themeDir;
|
||||
static const char* prefPath;
|
||||
string file_path;
|
||||
std::set<int> HueEnabledColors;
|
||||
bool ShowEditor(bool *open, Theme* &theme);
|
||||
static bool ShowEditor(bool *open, Theme* &theme);
|
||||
void Apply(float hue);
|
||||
void Save(string path);
|
||||
Theme();
|
||||
|
|
Loading…
Reference in a new issue