From 10d9fa9a7cf93b07a49f9ac8aded50fef2f874ba Mon Sep 17 00:00:00 2001 From: Leon Styhre Date: Wed, 20 Dec 2023 21:58:40 +0100 Subject: [PATCH] Added support for defining font sizes from the theme configuration and selecting these from the UI settings menu --- es-app/src/guis/GuiMenu.cpp | 56 +++++++++++++++++++ es-core/src/Settings.cpp | 1 + es-core/src/ThemeData.cpp | 108 ++++++++++++++++++++++++++++++++++++ es-core/src/ThemeData.h | 7 +++ 4 files changed, 172 insertions(+) diff --git a/es-app/src/guis/GuiMenu.cpp b/es-app/src/guis/GuiMenu.cpp index 86a6fac89..93e12ac42 100644 --- a/es-app/src/guis/GuiMenu.cpp +++ b/es-app/src/guis/GuiMenu.cpp @@ -286,6 +286,47 @@ void GuiMenu::openUIOptions() themeColorSchemesFunc(Settings::getInstance()->getString("Theme"), Settings::getInstance()->getString("ThemeColorScheme")); + // Theme font sizes. + auto themeFontSize = std::make_shared>( + getHelpStyle(), "THEME FONT SIZE", false); + s->addWithLabel("THEME FONT SIZE", themeFontSize); + s->addSaveFunc([themeFontSize, s] { + if (themeFontSize->getSelected() != Settings::getInstance()->getString("ThemeFontSize")) { + Settings::getInstance()->setString("ThemeFontSize", themeFontSize->getSelected()); + s->setNeedsSaving(); + s->setNeedsReloading(); + s->setInvalidateCachedBackground(); + } + }); + + auto themeFontSizeFunc = [=](const std::string& selectedTheme, + const std::string& selectedFontSize) { + std::map::const_iterator + currentSet {themes.find(selectedTheme)}; + if (currentSet == themes.cend()) + return; + // We need to recreate the OptionListComponent entries. + themeFontSize->clearEntries(); + if (currentSet->second.capabilities.fontSizes.size() > 0) { + for (auto& fontSize : currentSet->second.capabilities.fontSizes) + themeFontSize->add(ThemeData::getFontSizeLabel(fontSize), fontSize, + fontSize == selectedFontSize); + if (themeFontSize->getSelectedObjects().size() == 0) + themeFontSize->selectEntry(0); + } + else { + themeFontSize->add("None defined", "none", true); + themeFontSize->setEnabled(false); + themeFontSize->setOpacity(DISABLED_OPACITY); + themeFontSize->getParent() + ->getChild(themeFontSize->getChildIndex() - 1) + ->setOpacity(DISABLED_OPACITY); + } + }; + + themeFontSizeFunc(Settings::getInstance()->getString("Theme"), + Settings::getInstance()->getString("ThemeFontSize")); + // Theme aspect ratios. auto themeAspectRatio = std::make_shared>( getHelpStyle(), "THEME ASPECT RATIO", false); @@ -889,6 +930,7 @@ void GuiMenu::openUIOptions() if (!firstRun) { themeVariantsFunc(themeName, themeVariant->getSelected()); themeColorSchemesFunc(themeName, themeColorScheme->getSelected()); + themeFontSizeFunc(themeName, themeFontSize->getSelected()); themeAspectRatiosFunc(themeName, themeAspectRatio->getSelected()); themeTransitionsFunc(themeName, themeTransitions->getSelected()); } @@ -925,6 +967,20 @@ void GuiMenu::openUIOptions() ->getChild(themeColorScheme->getChildIndex() - 1) ->setOpacity(DISABLED_OPACITY); } + if (selectedTheme->second.capabilities.fontSizes.size() > 0) { + themeFontSize->setEnabled(true); + themeFontSize->setOpacity(1.0f); + themeFontSize->getParent() + ->getChild(themeFontSize->getChildIndex() - 1) + ->setOpacity(1.0f); + } + else { + themeFontSize->setEnabled(false); + themeFontSize->setOpacity(DISABLED_OPACITY); + themeFontSize->getParent() + ->getChild(themeFontSize->getChildIndex() - 1) + ->setOpacity(DISABLED_OPACITY); + } if (selectedTheme->second.capabilities.aspectRatios.size() > 0) { themeAspectRatio->setEnabled(true); themeAspectRatio->setOpacity(1.0f); diff --git a/es-core/src/Settings.cpp b/es-core/src/Settings.cpp index 919516ca8..f5b69bafa 100644 --- a/es-core/src/Settings.cpp +++ b/es-core/src/Settings.cpp @@ -165,6 +165,7 @@ void Settings::setDefaults() mStringMap["Theme"] = {"slate-es-de", "slate-es-de"}; mStringMap["ThemeVariant"] = {"", ""}; mStringMap["ThemeColorScheme"] = {"", ""}; + mStringMap["ThemeFontSize"] = {"", ""}; mStringMap["ThemeAspectRatio"] = {"", ""}; mStringMap["ThemeTransitions"] = {"automatic", "automatic"}; mStringMap["QuickSystemSelect"] = {"leftrightshoulders", "leftrightshoulders"}; diff --git a/es-core/src/ThemeData.cpp b/es-core/src/ThemeData.cpp index f40f11d07..589063468 100644 --- a/es-core/src/ThemeData.cpp +++ b/es-core/src/ThemeData.cpp @@ -51,6 +51,13 @@ std::vector ThemeData::sSupportedTransitionAnimations { {"builtin-slide"}, {"builtin-fade"}}; +std::vector> ThemeData::sSupportedFontSizes { + {"medium", "medium"}, + {"large", "large"}, + {"small", "small"}, + {"x-large", "extra large"}, + {"x-small", "extra small"}}; + std::vector> ThemeData::sSupportedAspectRatios { {"automatic", "automatic"}, {"16:9", "16:9"}, @@ -596,6 +603,17 @@ void ThemeData::loadFile(const std::map& sysDataMap, mSelectedColorScheme = mColorSchemes.front(); } + if (sCurrentTheme->second.capabilities.fontSizes.size() > 0) { + for (auto& fontSize : sCurrentTheme->second.capabilities.fontSizes) + mFontSizes.emplace_back(fontSize); + + if (std::find(mFontSizes.cbegin(), mFontSizes.cend(), + Settings::getInstance()->getString("ThemeFontSize")) != mFontSizes.cend()) + mSelectedFontSize = Settings::getInstance()->getString("ThemeFontSize"); + else + mSelectedFontSize = mFontSizes.front(); + } + sAspectRatioMatch = false; if (sCurrentTheme->second.capabilities.aspectRatios.size() > 0) { @@ -633,6 +651,7 @@ void ThemeData::loadFile(const std::map& sysDataMap, parseVariables(root); parseColorSchemes(root); + parseFontSizes(root); parseIncludes(root); parseViews(root); if (root.child("feature") != nullptr) @@ -768,6 +787,8 @@ void ThemeData::populateThemes() << " variant" << (capabilities.variants.size() != 1 ? "s" : "") << ", " << capabilities.colorSchemes.size() << " color scheme" << (capabilities.colorSchemes.size() != 1 ? "s" : "") << ", " + << capabilities.fontSizes.size() << " font size" + << (capabilities.fontSizes.size() != 1 ? "s" : "") << ", " << aspectRatios << " aspect ratio" << (aspectRatios != 1 ? "s" : "") << " and " << capabilities.transitions.size() << " transition" << (capabilities.transitions.size() != 1 ? "s" : ""); @@ -819,6 +840,18 @@ const std::string ThemeData::getSystemThemeFile(const std::string& system) return theme->second.getThemePath(system); } +const std::string ThemeData::getFontSizeLabel(const std::string& fontSize) +{ + auto it = std::find_if(sSupportedFontSizes.cbegin(), sSupportedFontSizes.cend(), + [&fontSize](const std::pair& entry) { + return entry.first == fontSize; + }); + if (it != sSupportedFontSizes.cend()) + return it->second; + else + return "invalid font size"; +} + const std::string ThemeData::getAspectRatioLabel(const std::string& aspectRatio) { auto it = std::find_if(sSupportedAspectRatios.cbegin(), sSupportedAspectRatios.cend(), @@ -980,6 +1013,7 @@ ThemeData::ThemeCapability ThemeData::parseThemeCapabilities(const std::string& { ThemeCapability capabilities; std::vector aspectRatiosTemp; + std::vector fontSizesTemp; bool hasTriggers {false}; const std::string capFile {path + "/capabilities.xml"}; @@ -1034,6 +1068,29 @@ ThemeData::ThemeCapability ThemeData::parseThemeCapabilities(const std::string& } } + for (pugi::xml_node fontSize {themeCapabilities.child("fontSize")}; fontSize; + fontSize = fontSize.next_sibling("fontSize")) { + const std::string& value {fontSize.text().get()}; + if (std::find_if(sSupportedFontSizes.cbegin(), sSupportedFontSizes.cend(), + [&value](const std::pair& entry) { + return entry.first == value; + }) == sSupportedFontSizes.cend()) { + LOG(LogWarning) << "Declared font size \"" << value + << "\" is not supported, ignoring entry in \"" << capFile << "\""; + } + else { + if (std::find(fontSizesTemp.cbegin(), fontSizesTemp.cend(), value) != + fontSizesTemp.cend()) { + LOG(LogWarning) + << "Font size \"" << value + << "\" is declared multiple times, ignoring entry in \"" << capFile << "\""; + } + else { + fontSizesTemp.emplace_back(value); + } + } + } + for (pugi::xml_node variant {themeCapabilities.child("variant")}; variant; variant = variant.next_sibling("variant")) { ThemeVariant readVariant; @@ -1411,6 +1468,17 @@ ThemeData::ThemeCapability ThemeData::parseThemeCapabilities(const std::string& } } + // Add the font sizes in the order they are defined in sSupportedFontSizes so they always + // show up in the same order in the UI Settings menu. + if (!fontSizesTemp.empty()) { + for (auto& fontSize : sSupportedFontSizes) { + if (std::find(fontSizesTemp.cbegin(), fontSizesTemp.cend(), fontSize.first) != + fontSizesTemp.cend()) { + capabilities.fontSizes.emplace_back(fontSize.first); + } + } + } + if (hasTriggers) { for (auto& variant : capabilities.variants) { for (auto it = variant.overrides.begin(); it != variant.overrides.end();) { @@ -1500,6 +1568,7 @@ void ThemeData::parseIncludes(const pugi::xml_node& root) parseTransitions(theme); parseVariables(theme); parseColorSchemes(theme); + parseFontSizes(theme); parseIncludes(theme); parseViews(theme); if (theme.child("feature") != nullptr) @@ -1549,6 +1618,7 @@ void ThemeData::parseVariants(const pugi::xml_node& root) parseTransitions(node); parseVariables(node); parseColorSchemes(node); + parseFontSizes(node); parseIncludes(node); parseViews(node); parseAspectRatios(node); @@ -1596,6 +1666,43 @@ void ThemeData::parseColorSchemes(const pugi::xml_node& root) } } +void ThemeData::parseFontSizes(const pugi::xml_node& root) +{ + if (sCurrentTheme == sThemes.end()) + return; + + if (mSelectedFontSize == "") + return; + + ThemeException error; + error << "ThemeData::parseFontSizes(): "; + error.setFiles(mPaths); + + for (pugi::xml_node node {root.child("fontSize")}; node; node = node.next_sibling("fontSize")) { + if (!node.attribute("name")) + throw error << ": tag missing \"name\" attribute"; + + const std::string delim {" \t\r\n,"}; + const std::string nameAttr {node.attribute("name").as_string()}; + size_t prevOff {nameAttr.find_first_not_of(delim, 0)}; + size_t off {nameAttr.find_first_of(delim, prevOff)}; + std::string viewKey; + while (off != std::string::npos || prevOff != std::string::npos) { + viewKey = nameAttr.substr(prevOff, off - prevOff); + prevOff = nameAttr.find_first_not_of(delim, off); + off = nameAttr.find_first_of(delim, prevOff); + + if (std::find(mFontSizes.cbegin(), mFontSizes.cend(), viewKey) == mFontSizes.cend()) { + throw error << ": value \"" << viewKey + << "\" is not defined in capabilities.xml"; + } + + if (mSelectedFontSize == viewKey) + parseVariables(node); + } + } +} + void ThemeData::parseAspectRatios(const pugi::xml_node& root) { if (sCurrentTheme == sThemes.end()) @@ -1633,6 +1740,7 @@ void ThemeData::parseAspectRatios(const pugi::xml_node& root) if (sSelectedAspectRatio == viewKey) { parseVariables(node); parseColorSchemes(node); + parseFontSizes(node); parseIncludes(node); parseViews(node); } diff --git a/es-core/src/ThemeData.h b/es-core/src/ThemeData.h index 3a9ff783e..d6ed87fa3 100644 --- a/es-core/src/ThemeData.h +++ b/es-core/src/ThemeData.h @@ -184,6 +184,7 @@ public: std::string themeName; std::vector variants; std::vector colorSchemes; + std::vector fontSizes; std::vector aspectRatios; std::vector transitions; std::vector suppressedTransitionProfiles; @@ -222,6 +223,7 @@ public: static void populateThemes(); const static std::map& getThemes() { return sThemes; } const static std::string getSystemThemeFile(const std::string& system); + const static std::string getFontSizeLabel(const std::string& fontSize); const static std::string getAspectRatioLabel(const std::string& aspectRatio); static void setThemeTransitions(); @@ -251,6 +253,7 @@ private: void parseIncludes(const pugi::xml_node& root); void parseVariants(const pugi::xml_node& root); void parseColorSchemes(const pugi::xml_node& root); + void parseFontSizes(const pugi::xml_node& root); void parseAspectRatios(const pugi::xml_node& root); void parseTransitions(const pugi::xml_node& root); void parseVariables(const pugi::xml_node& root); @@ -264,6 +267,8 @@ private: static std::vector sSupportedMediaTypes; static std::vector sSupportedTransitions; static std::vector sSupportedTransitionAnimations; + + static std::vector> sSupportedFontSizes; static std::vector> sSupportedAspectRatios; static std::map sAspectRatioMap; @@ -278,9 +283,11 @@ private: std::deque mPaths; std::vector mVariants; std::vector mColorSchemes; + std::vector mFontSizes; std::string mSelectedVariant; std::string mOverrideVariant; std::string mSelectedColorScheme; + std::string mSelectedFontSize; static inline std::string sSelectedAspectRatio; static inline bool sAspectRatioMatch {false}; bool mCustomCollection;