diff --git a/es-core/src/ThemeData.cpp b/es-core/src/ThemeData.cpp index 99f1f54f2..d15f016f5 100644 --- a/es-core/src/ThemeData.cpp +++ b/es-core/src/ThemeData.cpp @@ -44,6 +44,13 @@ std::vector<std::string> ThemeData::sLegacySupportedFeatures { {"z-index"}, {"visible"}}; +std::vector<std::string> ThemeData::sLegacyElements { + {"showSnapshotNoVideo"}, + {"showSnapshotDelay"}, + {"forceUppercase"}, + {"alignment"}, + {"logoAlignment"}}; + std::vector<std::pair<std::string, std::string>> ThemeData::sSupportedAspectRatios { {"16:9", "16:9"}, {"16:9_vertical", "16:9 vertical"}, @@ -124,7 +131,8 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>> {"origin", NORMALIZED_PAIR}, {"rotation", FLOAT}, {"rotationOrigin", NORMALIZED_PAIR}, - {"alignment", STRING}, + {"horizontalAlignment", STRING}, + {"alignment", STRING}, // For backward compatibility with legacy themes. {"direction", STRING}, {"lines", FLOAT}, {"itemsPerLine", FLOAT}, @@ -150,7 +158,9 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>> {"containerResetDelay", FLOAT}, {"fontPath", PATH}, {"fontSize", FLOAT}, - {"alignment", STRING}, + {"horizontalAlignment", STRING}, + {"verticalAlignment", STRING}, + {"alignment", STRING}, // For backward compatibility with legacy themes. {"color", COLOR}, {"backgroundColor", COLOR}, {"letterCase", STRING}, @@ -167,7 +177,9 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>> {"metadata", STRING}, {"fontPath", PATH}, {"fontSize", FLOAT}, - {"alignment", STRING}, + {"horizontalAlignment", STRING}, + {"verticalAlignment", STRING}, + {"alignment", STRING}, // For backward compatibility with legacy themes. {"color", COLOR}, {"backgroundColor", COLOR}, {"letterCase", STRING}, @@ -187,7 +199,9 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>> {"fontSize", FLOAT}, {"color", COLOR}, {"backgroundColor", COLOR}, - {"alignment", STRING}, + {"horizontalAlignment", STRING}, + {"verticalAlignment", STRING}, + {"alignment", STRING}, // For backward compatibility with legacy themes. {"visible", BOOLEAN}, {"zIndex", FLOAT}}}, {"rating", @@ -214,7 +228,9 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>> {"logoScale", FLOAT}, {"logoRotation", FLOAT}, {"logoRotationOrigin", NORMALIZED_PAIR}, - {"logoAlignment", STRING}, + {"logoHorizontalAlignment", STRING}, + {"logoVerticalAlignment", STRING}, + {"logoAlignment", STRING}, // For backward compatibility with legacy themes. {"maxLogoCount", FLOAT}, {"text", STRING}, {"textColor", COLOR}, @@ -243,7 +259,8 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>> {"fontSize", FLOAT}, {"scrollHide", BOOLEAN}, {"scrollSound", PATH}, // For backward compatibility with legacy themes. - {"alignment", STRING}, + {"horizontalAlignment", STRING}, + {"alignment", STRING}, // For backward compatibility with legacy themes. {"horizontalMargin", FLOAT}, {"letterCase", STRING}, {"forceUppercase", BOOLEAN}, // For backward compatibility with legacy themes. @@ -1069,14 +1086,14 @@ void ThemeData::parseElement(const pugi::xml_node& root, std::string nodeName = node.name(); + // Strictly enforce removal of legacy elements for non-legacy theme sets by creating + // an unthemed system if they're present in the configuration. if (!mLegacyTheme) { - if (nodeName == "showSnapshotNoVideo" || nodeName == "showSnapshotDelay") { - throw error << ": Legacy <" << nodeName - << "> property found for non-legacy theme set"; - } - else if (nodeName == "forceUppercase") { - throw error << ": Legacy <" << nodeName - << "> property found for non-legacy theme set"; + for (auto& legacyElement : sLegacyElements) { + if (nodeName == legacyElement) { + throw error << ": Legacy <" << nodeName + << "> property found for non-legacy theme set"; + } } } diff --git a/es-core/src/ThemeData.h b/es-core/src/ThemeData.h index 15288ffa4..868f61b61 100644 --- a/es-core/src/ThemeData.h +++ b/es-core/src/ThemeData.h @@ -239,14 +239,15 @@ private: const std::map<std::string, ElementPropertyType>& typeMap, ThemeElement& element); - static std::map<std::string, std::map<std::string, ElementPropertyType>> sElementMap; - static std::map<std::string, std::map<std::string, std::string>> sPropertyAttributeMap; - - static std::vector<std::string> sLegacySupportedFeatures; - static std::vector<std::string> sLegacySupportedViews; static std::vector<std::string> sSupportedViews; + static std::vector<std::string> sLegacySupportedViews; + static std::vector<std::string> sLegacySupportedFeatures; + static std::vector<std::string> sLegacyElements; static std::vector<std::pair<std::string, std::string>> sSupportedAspectRatios; + static std::map<std::string, std::map<std::string, std::string>> sPropertyAttributeMap; + static std::map<std::string, std::map<std::string, ElementPropertyType>> sElementMap; + static inline std::map<std::string, ThemeSet> mThemeSets; std::map<std::string, ThemeData::ThemeSet>::iterator mCurrentThemeSet; diff --git a/es-core/src/components/BadgeComponent.cpp b/es-core/src/components/BadgeComponent.cpp index 7a7b7549d..e3243668f 100644 --- a/es-core/src/components/BadgeComponent.cpp +++ b/es-core/src/components/BadgeComponent.cpp @@ -195,7 +195,19 @@ void BadgeComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, if (!elem) return; - if (elem->has("alignment")) { + if (elem->has("horizontalAlignment")) { + const std::string horizontalAlignment {elem->get<std::string>("horizontalAlignment")}; + if (horizontalAlignment != "left" && horizontalAlignment != "right") { + LOG(LogWarning) + << "BadgeComponent: Invalid theme configuration, <horizontalAlignment> set to \"" + << horizontalAlignment << "\""; + } + else { + mFlexboxComponent.setAlignment(horizontalAlignment); + } + } + // Legacy themes only. + else if (elem->has("alignment")) { const std::string alignment {elem->get<std::string>("alignment")}; if (alignment != "left" && alignment != "right") { LOG(LogWarning) << "BadgeComponent: Invalid theme configuration, <alignment> set to \"" diff --git a/es-core/src/components/CarouselComponent.cpp b/es-core/src/components/CarouselComponent.cpp index 1cd128c53..d83501c5c 100644 --- a/es-core/src/components/CarouselComponent.cpp +++ b/es-core/src/components/CarouselComponent.cpp @@ -28,7 +28,8 @@ CarouselComponent::CarouselComponent() , mTextColor {0x000000FF} , mTextBackgroundColor {0xFFFFFF00} , mLineSpacing {1.5f} - , mLogoAlignment {ALIGN_CENTER} + , mLogoHorizontalAlignment {ALIGN_CENTER} + , mLogoVerticalAlignment {ALIGN_CENTER} , mMaxLogoCount {3} , mLogoSize {Renderer::getScreenWidth() * 0.25f, Renderer::getScreenHeight() * 0.155f} , mLogoScale {1.2f} @@ -107,31 +108,25 @@ void CarouselComponent::addEntry(const std::shared_ptr<ThemeData>& theme, } entry.data.logo = text; - if (mLogoAlignment == ALIGN_LEFT || mLogoAlignment == ALIGN_RIGHT) { - text->setHorizontalAlignment(mLogoAlignment); - text->setVerticalAlignment(ALIGN_CENTER); - } - else if (mLogoAlignment == ALIGN_TOP || mLogoAlignment == ALIGN_BOTTOM) { - text->setVerticalAlignment(mLogoAlignment); - text->setHorizontalAlignment(ALIGN_CENTER); - } - else { - text->setHorizontalAlignment(ALIGN_CENTER); - text->setVerticalAlignment(ALIGN_CENTER); - } + text->setHorizontalAlignment(mLogoHorizontalAlignment); + text->setVerticalAlignment(mLogoVerticalAlignment); } - if (mLogoAlignment == ALIGN_LEFT) + // Set origin for the logos based on their alignment so they line up properly. + if (mLogoHorizontalAlignment == ALIGN_LEFT) entry.data.logo->setOrigin(0, 0.5); - else if (mLogoAlignment == ALIGN_RIGHT) + else if (mLogoHorizontalAlignment == ALIGN_RIGHT) entry.data.logo->setOrigin(1.0, 0.5); - else if (mLogoAlignment == ALIGN_TOP) - entry.data.logo->setOrigin(0.5, 0); - else if (mLogoAlignment == ALIGN_BOTTOM) - entry.data.logo->setOrigin(0.5, 1); else entry.data.logo->setOrigin(0.5, 0.5); + if (mLogoVerticalAlignment == ALIGN_TOP) + entry.data.logo->setOrigin(entry.data.logo->getOrigin().x, 0); + else if (mLogoVerticalAlignment == ALIGN_BOTTOM) + entry.data.logo->setOrigin(entry.data.logo->getOrigin().x, 1); + else + entry.data.logo->setOrigin(entry.data.logo->getOrigin().x, 0.5); + glm::vec2 denormalized {mLogoSize * entry.data.logo->getOrigin()}; entry.data.logo->setPosition(glm::vec3 {denormalized.x, denormalized.y, 0.0f}); @@ -221,9 +216,9 @@ void CarouselComponent::render(const glm::mat4& parentTrans) logoSpacing.y = ((mSize.y - (mLogoSize.y * mMaxLogoCount)) / (mMaxLogoCount)) + mLogoSize.y; yOff = (mSize.y - mLogoSize.y) / 2.0f - (mCamOffset * logoSpacing.y); - if (mLogoAlignment == ALIGN_LEFT) + if (mLogoHorizontalAlignment == ALIGN_LEFT) xOff = mLogoSize.x / 10.0f; - else if (mLogoAlignment == ALIGN_RIGHT) + else if (mLogoHorizontalAlignment == ALIGN_RIGHT) xOff = mSize.x - (mLogoSize.x * 1.1f); else xOff = (mSize.x - mLogoSize.x) / 2.0f; @@ -233,9 +228,9 @@ void CarouselComponent::render(const glm::mat4& parentTrans) logoSpacing.x = ((mSize.x - (mLogoSize.x * mMaxLogoCount)) / (mMaxLogoCount)) + mLogoSize.x; xOff = std::round((mSize.x - mLogoSize.x) / 2.0f - (mCamOffset * logoSpacing.x)); - if (mLogoAlignment == ALIGN_TOP) + if (mLogoVerticalAlignment == ALIGN_TOP) yOff = mLogoSize.y / 10.0f; - else if (mLogoAlignment == ALIGN_BOTTOM) + else if (mLogoVerticalAlignment == ALIGN_BOTTOM) yOff = mSize.y - (mLogoSize.y * 1.1f); else yOff = (mSize.y - mLogoSize.y) / 2.0f; @@ -321,14 +316,25 @@ void CarouselComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, return; if (elem->has("type")) { - if (!(elem->get<std::string>("type").compare("vertical"))) - mType = VERTICAL; - else if (!(elem->get<std::string>("type").compare("vertical_wheel"))) - mType = VERTICAL_WHEEL; - else if (!(elem->get<std::string>("type").compare("horizontal_wheel"))) - mType = HORIZONTAL_WHEEL; - else + const std::string type {elem->get<std::string>("type")}; + if (type == "horizontal") { mType = HORIZONTAL; + } + else if (type == "horizontal_wheel") { + mType = HORIZONTAL_WHEEL; + } + else if (type == "vertical") { + mType = VERTICAL; + } + else if (type == "vertical_wheel") { + mType = VERTICAL_WHEEL; + } + else { + LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property " + "<type> set to \"" + << type << "\""; + mType = HORIZONTAL; + } } if (elem->has("color")) { @@ -338,7 +344,7 @@ void CarouselComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, if (elem->has("colorEnd")) mCarouselColorEnd = elem->get<unsigned int>("colorEnd"); if (elem->has("gradientType")) - mColorGradientHorizontal = !(elem->get<std::string>("gradientType").compare("horizontal")); + mColorGradientHorizontal = (elem->get<std::string>("gradientType") == "horizontal"); if (elem->has("logoScale")) mLogoScale = glm::clamp(elem->get<float>("logoScale"), 0.5f, 3.0f); @@ -365,23 +371,74 @@ void CarouselComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, mLogoRotation = elem->get<float>("logoRotation"); if (elem->has("logoRotationOrigin")) mLogoRotationOrigin = elem->get<glm::vec2>("logoRotationOrigin"); - if (elem->has("logoAlignment")) { - if (!(elem->get<std::string>("logoAlignment").compare("left")) && mType != HORIZONTAL) { - mLogoAlignment = ALIGN_LEFT; + + if (elem->has("logoHorizontalAlignment")) { + const std::string alignment {elem->get<std::string>("logoHorizontalAlignment")}; + if (alignment == "left" && mType != HORIZONTAL) { + mLogoHorizontalAlignment = ALIGN_LEFT; } - else if (!(elem->get<std::string>("logoAlignment").compare("right")) && - mType != HORIZONTAL) { - mLogoAlignment = ALIGN_RIGHT; + else if (alignment == "right" && mType != HORIZONTAL) { + mLogoHorizontalAlignment = ALIGN_RIGHT; } - else if (!(elem->get<std::string>("logoAlignment").compare("top")) && mType != VERTICAL) { - mLogoAlignment = ALIGN_TOP; - } - else if (!(elem->get<std::string>("logoAlignment").compare("bottom")) && - mType != VERTICAL) { - mLogoAlignment = ALIGN_BOTTOM; + else if (alignment == "center") { + mLogoHorizontalAlignment = ALIGN_CENTER; } else { - mLogoAlignment = ALIGN_CENTER; + LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property " + "<logoHorizontalAlignment> set to \"" + << alignment << "\""; + mLogoHorizontalAlignment = ALIGN_CENTER; + } + } + + if (elem->has("logoVerticalAlignment")) { + const std::string alignment {elem->get<std::string>("logoVerticalAlignment")}; + if (alignment == "top" && mType != VERTICAL) { + mLogoVerticalAlignment = ALIGN_TOP; + } + else if (alignment == "bottom" && mType != VERTICAL) { + mLogoVerticalAlignment = ALIGN_BOTTOM; + } + else if (alignment == "center") { + mLogoVerticalAlignment = ALIGN_CENTER; + } + else { + LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property " + "<logoVerticalAlignment> set to \"" + << alignment << "\""; + mLogoVerticalAlignment = ALIGN_CENTER; + } + } + + // Legacy themes only. + if (elem->has("logoAlignment")) { + const std::string alignment {elem->get<std::string>("logoAlignment")}; + if (alignment == "left" && mType != HORIZONTAL) { + mLogoHorizontalAlignment = ALIGN_LEFT; + mLogoVerticalAlignment = ALIGN_CENTER; + } + else if (alignment == "right" && mType != HORIZONTAL) { + mLogoHorizontalAlignment = ALIGN_RIGHT; + mLogoVerticalAlignment = ALIGN_CENTER; + } + else if (alignment == "top" && mType != VERTICAL) { + mLogoVerticalAlignment = ALIGN_TOP; + mLogoHorizontalAlignment = ALIGN_CENTER; + } + else if (alignment == "bottom" && mType != VERTICAL) { + mLogoVerticalAlignment = ALIGN_BOTTOM; + mLogoHorizontalAlignment = ALIGN_CENTER; + } + else if (alignment == "center") { + mLogoHorizontalAlignment = ALIGN_CENTER; + mLogoVerticalAlignment = ALIGN_CENTER; + } + else { + LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property " + "<logoAlignment> set to \"" + << alignment << "\""; + mLogoHorizontalAlignment = ALIGN_CENTER; + mLogoVerticalAlignment = ALIGN_CENTER; } } diff --git a/es-core/src/components/CarouselComponent.h b/es-core/src/components/CarouselComponent.h index 04390f7b8..ec5708b62 100644 --- a/es-core/src/components/CarouselComponent.h +++ b/es-core/src/components/CarouselComponent.h @@ -80,7 +80,8 @@ private: unsigned int mTextBackgroundColor; std::string mText; float mLineSpacing; - Alignment mLogoAlignment; + Alignment mLogoHorizontalAlignment; + Alignment mLogoVerticalAlignment; int mMaxLogoCount; glm::vec2 mLogoSize; float mLogoScale; diff --git a/es-core/src/components/DateTimeComponent.cpp b/es-core/src/components/DateTimeComponent.cpp index 59efb5440..e4f077c2a 100644 --- a/es-core/src/components/DateTimeComponent.cpp +++ b/es-core/src/components/DateTimeComponent.cpp @@ -132,8 +132,8 @@ void DateTimeComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, setRenderBackground(true); } - if (properties & ALIGNMENT && elem->has("alignment")) { - std::string str = elem->get<std::string>("alignment"); + if (properties & ALIGNMENT && elem->has("horizontalAlignment")) { + std::string str {elem->get<std::string>("horizontalAlignment")}; if (str == "left") setHorizontalAlignment(ALIGN_LEFT); else if (str == "center") @@ -141,7 +141,38 @@ void DateTimeComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, else if (str == "right") setHorizontalAlignment(ALIGN_RIGHT); else - LOG(LogError) << "Unknown text alignment string: " << str; + LOG(LogWarning) << "DateTimeComponent: Invalid theme configuration, property " + "<horizontalAlignment> set to \"" + << str << "\""; + } + + if (properties & ALIGNMENT && elem->has("verticalAlignment")) { + std::string str {elem->get<std::string>("verticalAlignment")}; + if (str == "top") + setVerticalAlignment(ALIGN_TOP); + else if (str == "center") + setVerticalAlignment(ALIGN_CENTER); + else if (str == "bottom") + setVerticalAlignment(ALIGN_BOTTOM); + else + LOG(LogWarning) << "DateTimeComponent: Invalid theme configuration, property " + "<verticalAlignment> set to \"" + << str << "\""; + } + + // Legacy themes only. + if (properties & ALIGNMENT && elem->has("alignment")) { + std::string str {elem->get<std::string>("alignment")}; + if (str == "left") + setHorizontalAlignment(ALIGN_LEFT); + else if (str == "center") + setHorizontalAlignment(ALIGN_CENTER); + else if (str == "right") + setHorizontalAlignment(ALIGN_RIGHT); + else + LOG(LogWarning) << "DateTimeComponent: Invalid theme configuration, property " + "<alignment> set to \"" + << str << "\""; } if (properties & METADATA && elem->has("metadata")) diff --git a/es-core/src/components/TextComponent.cpp b/es-core/src/components/TextComponent.cpp index 81603a8ec..99f48356e 100644 --- a/es-core/src/components/TextComponent.cpp +++ b/es-core/src/components/TextComponent.cpp @@ -362,9 +362,12 @@ void TextComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, GuiComponent::applyTheme(theme, view, element, properties); std::string elementType {"text"}; + std::string componentName {"TextComponent"}; - if (element.substr(0, 13) == "gamelistinfo_") + if (element.substr(0, 13) == "gamelistinfo_") { elementType = "gamelistinfo"; + componentName = "gamelistInfoComponent"; + } const ThemeData::ThemeElement* elem = theme->getElement(view, element, elementType); if (!elem) @@ -379,8 +382,8 @@ void TextComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, setRenderBackground(true); } - if (properties & ALIGNMENT && elem->has("alignment")) { - std::string str = elem->get<std::string>("alignment"); + if (properties & ALIGNMENT && elem->has("horizontalAlignment")) { + std::string str {elem->get<std::string>("horizontalAlignment")}; if (str == "left") setHorizontalAlignment(ALIGN_LEFT); else if (str == "center") @@ -388,7 +391,41 @@ void TextComponent::applyTheme(const std::shared_ptr<ThemeData>& theme, else if (str == "right") setHorizontalAlignment(ALIGN_RIGHT); else - LOG(LogError) << "Unknown text alignment string: " << str; + LOG(LogWarning) << componentName + << ": Invalid theme configuration, property " + "<horizontalAlignment> set to \"" + << str << "\""; + } + + if (properties & ALIGNMENT && elem->has("verticalAlignment")) { + std::string str {elem->get<std::string>("verticalAlignment")}; + if (str == "top") + setVerticalAlignment(ALIGN_TOP); + else if (str == "center") + setVerticalAlignment(ALIGN_CENTER); + else if (str == "bottom") + setVerticalAlignment(ALIGN_BOTTOM); + else + LOG(LogWarning) << componentName + << ": Invalid theme configuration, property " + "<verticalAlignment> set to \"" + << str << "\""; + } + + // Legacy themes only. + if (properties & ALIGNMENT && elem->has("alignment")) { + std::string str {elem->get<std::string>("alignment")}; + if (str == "left") + setHorizontalAlignment(ALIGN_LEFT); + else if (str == "center") + setHorizontalAlignment(ALIGN_CENTER); + else if (str == "right") + setHorizontalAlignment(ALIGN_RIGHT); + else + LOG(LogWarning) << componentName + << ": Invalid theme configuration, property " + "<alignment> set to \"" + << str << "\""; } if (properties & TEXT && elem->has("text")) diff --git a/es-core/src/components/TextListComponent.h b/es-core/src/components/TextListComponent.h index 0f5c66028..15fcba8ae 100644 --- a/es-core/src/components/TextListComponent.h +++ b/es-core/src/components/TextListComponent.h @@ -491,8 +491,8 @@ void TextListComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme, setSelectorHeight(selectorHeight); if (properties & ALIGNMENT) { - if (elem->has("alignment")) { - const std::string& str = elem->get<std::string>("alignment"); + if (elem->has("horizontalAlignment")) { + const std::string& str {elem->get<std::string>("horizontalAlignment")}; if (str == "left") setAlignment(ALIGN_LEFT); else if (str == "center") @@ -500,7 +500,23 @@ void TextListComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme, else if (str == "right") setAlignment(ALIGN_RIGHT); else - LOG(LogError) << "Unknown TextListComponent alignment \"" << str << "\"!"; + LOG(LogWarning) << "TextListComponent: Invalid theme configuration, property " + "<horizontalAlignment> set to \"" + << str << "\""; + } + // Legacy themes only. + else if (elem->has("alignment")) { + const std::string& str {elem->get<std::string>("alignment")}; + if (str == "left") + setAlignment(ALIGN_LEFT); + else if (str == "center") + setAlignment(ALIGN_CENTER); + else if (str == "right") + setAlignment(ALIGN_RIGHT); + else + LOG(LogWarning) << "TextListComponent: Invalid theme configuration, property " + "<alignment> set to \"" + << str << "\""; } if (elem->has("horizontalMargin")) { mHorizontalMargin = elem->get<float>("horizontalMargin") * diff --git a/es-core/src/resources/Font.h b/es-core/src/resources/Font.h index 481283bbe..61ad7fbfa 100644 --- a/es-core/src/resources/Font.h +++ b/es-core/src/resources/Font.h @@ -37,7 +37,7 @@ class TextCache; enum Alignment { ALIGN_LEFT, - ALIGN_CENTER, // Centers both horizontally and vertically. + ALIGN_CENTER, // Used for both horizontal and vertical alignments. ALIGN_RIGHT, ALIGN_TOP, ALIGN_BOTTOM