Added two letterCaseCollections and letterCaseGroupedCollections properties to TextListComponent and CarouselComponent.

Also refactored the letterCase logic overall in these two components.
This commit is contained in:
Leon Styhre 2022-11-03 12:31:42 +01:00
parent b426473ec0
commit 412a19275d
7 changed files with 190 additions and 119 deletions

View file

@ -543,18 +543,21 @@ void GamelistBase::populateList(const std::vector<FileData*>& files, FileData* f
mFirstGameEntry = nullptr;
bool favoriteStar {true};
bool isEditing {false};
bool customCollection {false};
std::string editingCollection;
std::string inCollectionPrefix;
LetterCase letterCase {LetterCase::NONE};
if (CollectionSystemsManager::getInstance()->isEditing()) {
editingCollection = CollectionSystemsManager::getInstance()->getEditingCollection();
isEditing = true;
}
// Read the settings that control whether a unicode star character should be added
// as a prefix to the game name.
if (files.size() > 0) {
if (files.front()->getSystem()->isCustomCollection())
customCollection = files.front()->getSystem()->isCustomCollection();
// Read the settings that control whether a unicode star character should be added
// as a prefix to the game name.
if (customCollection)
favoriteStar = Settings::getInstance()->getBool("FavStarCustom");
else
favoriteStar = Settings::getInstance()->getBool("FavoritesStar");
@ -575,13 +578,21 @@ void GamelistBase::populateList(const std::vector<FileData*>& files, FileData* f
if (!ResourceManager::getInstance().fileExists(carouselDefaultItem))
carouselDefaultItem = "";
}
if (files.size() > 0) {
for (auto it = files.cbegin(); it != files.cend(); ++it) {
if (!mFirstGameEntry && (*it)->getType() == GAME)
mFirstGameEntry = (*it);
if (customCollection && (*it)->getType() == FOLDER) {
letterCase = mPrimary->getLetterCaseGroupedCollections();
if (letterCase == LetterCase::NONE)
letterCase = mPrimary->getLetterCase();
}
else {
letterCase = mPrimary->getLetterCase();
}
if (mCarousel != nullptr) {
assert(carouselItemType != "");
@ -589,6 +600,13 @@ void GamelistBase::populateList(const std::vector<FileData*>& files, FileData* f
carouselEntry.name = (*it)->getName();
carouselEntry.object = *it;
if (letterCase == LetterCase::UPPERCASE)
carouselEntry.name = Utils::String::toUpper(carouselEntry.name);
else if (letterCase == LetterCase::LOWERCASE)
carouselEntry.name = Utils::String::toLower(carouselEntry.name);
else if (letterCase == LetterCase::CAPITALIZED)
carouselEntry.name = Utils::String::toCapitalized(carouselEntry.name);
if (carouselDefaultItem != "")
carouselEntry.data.defaultItemPath = carouselDefaultItem;
@ -646,6 +664,14 @@ void GamelistBase::populateList(const std::vector<FileData*>& files, FileData* f
name = inCollectionPrefix + (*it)->getName();
}
}
if (letterCase == LetterCase::UPPERCASE)
name = Utils::String::toUpper(name);
else if (letterCase == LetterCase::LOWERCASE)
name = Utils::String::toLower(name);
else if (letterCase == LetterCase::CAPITALIZED)
name = Utils::String::toCapitalized(name);
color = (*it)->getType() == FOLDER;
textListEntry.name = name;
textListEntry.object = *it;

View file

@ -637,17 +637,43 @@ void SystemView::populate()
});
}
auto letterCaseFunc = [&it, this](std::string& name) {
LetterCase letterCase {LetterCase::NONE};
if (it->isCollection()) {
letterCase = mPrimary->getLetterCaseCollections();
if (letterCase == LetterCase::NONE)
letterCase = mPrimary->getLetterCase();
}
else {
letterCase = mPrimary->getLetterCase();
}
if (letterCase == LetterCase::UPPERCASE)
name = Utils::String::toUpper(name);
else if (letterCase == LetterCase::LOWERCASE)
name = Utils::String::toLower(name);
else if (letterCase == LetterCase::CAPITALIZED)
name = Utils::String::toCapitalized(name);
};
if (mCarousel != nullptr) {
CarouselComponent<SystemData*>::Entry entry;
entry.name = it->getName();
// Keep showing only the short name for legacy themes to maintain maximum
// backward compatibility. This also applies to unreadable theme sets.
if (mLegacyMode)
entry.name = it->getName();
else
entry.name = it->getFullName();
letterCaseFunc(entry.name);
entry.object = it;
entry.data.itemPath = itemPath;
entry.data.defaultItemPath = defaultItemPath;
mCarousel->addEntry(entry, theme);
}
if (mTextList != nullptr) {
else if (mTextList != nullptr) {
TextListComponent<SystemData*>::Entry entry;
entry.name = it->getFullName();
letterCaseFunc(entry.name);
entry.object = it;
entry.data.colorId = 0;
mTextList->addEntry(entry);

View file

@ -42,6 +42,13 @@ enum Alignment {
ALIGN_BOTTOM
};
enum class LetterCase {
UPPERCASE,
LOWERCASE,
CAPITALIZED,
NONE
};
class GuiComponent
{
public:

View file

@ -316,6 +316,8 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>>
{"fontPath", PATH},
{"fontSize", FLOAT},
{"letterCase", STRING},
{"letterCaseCollections", STRING},
{"letterCaseGroupedCollections", STRING},
{"lineSpacing", FLOAT},
{"fadeAbovePrimary", BOOLEAN},
{"zIndex", FLOAT},
@ -341,6 +343,8 @@ std::map<std::string, std::map<std::string, ThemeData::ElementPropertyType>>
{"alignment", STRING}, // For backward compatibility with legacy themes.
{"horizontalMargin", FLOAT},
{"letterCase", STRING},
{"letterCaseCollections", STRING},
{"letterCaseGroupedCollections", STRING},
{"forceUppercase", BOOLEAN}, // For backward compatibility with legacy themes.
{"lineSpacing", FLOAT},
{"indicators", STRING},

View file

@ -59,6 +59,12 @@ public:
const std::string& getDefaultItem() { return mDefaultItem; }
void setDefaultItem(std::string defaultItem) { mDefaultItem = defaultItem; }
bool isScrolling() const override { return List::isScrolling(); }
const LetterCase getLetterCase() const override { return mLetterCase; }
const LetterCase getLetterCaseCollections() const override { return mLetterCaseCollections; }
const LetterCase getLetterCaseGroupedCollections() const override
{
return mLetterCaseGroupedCollections;
}
void setCursorChangedCallback(const std::function<void(CursorState state)>& func) override
{
@ -116,9 +122,6 @@ private:
bool mPositiveDirection;
bool mTriggerJump;
bool mGamelistView;
bool mUppercase;
bool mLowercase;
bool mCapitalize;
CarouselType mType;
std::string mItemType;
@ -127,7 +130,6 @@ private:
std::shared_ptr<Font> mFont;
unsigned int mTextColor;
unsigned int mTextBackgroundColor;
std::string mText;
float mLineSpacing;
Alignment mItemHorizontalAlignment;
Alignment mItemVerticalAlignment;
@ -141,6 +143,9 @@ private:
bool mInstantItemTransitions;
bool mItemAxisHorizontal;
bool mFadeAbovePrimary;
LetterCase mLetterCase;
LetterCase mLetterCaseCollections;
LetterCase mLetterCaseGroupedCollections;
float mItemScale;
float mItemRotation;
glm::vec2 mItemRotationOrigin;
@ -167,9 +172,6 @@ CarouselComponent<T>::CarouselComponent()
, mPositiveDirection {false}
, mTriggerJump {false}
, mGamelistView {std::is_same_v<T, FileData*> ? true : false}
, mUppercase {false}
, mLowercase {false}
, mCapitalize {false}
, mType {CarouselType::HORIZONTAL}
, mLegacyMode {false}
, mFont {Font::get(FONT_SIZE_LARGE)}
@ -189,6 +191,9 @@ CarouselComponent<T>::CarouselComponent()
, mInstantItemTransitions {false}
, mItemAxisHorizontal {false}
, mFadeAbovePrimary {false}
, mLetterCase {LetterCase::NONE}
, mLetterCaseCollections {LetterCase::NONE}
, mLetterCaseGroupedCollections {LetterCase::NONE}
, mItemScale {1.2f}
, mItemRotation {7.5f}
, mItemRotationOrigin {-3.0f, 0.5f}
@ -263,20 +268,9 @@ void CarouselComponent<T>::addEntry(Entry& entry, const std::shared_ptr<ThemeDat
if (!entry.data.item) {
// If no item image is present, add item text as fallback.
std::string nameEntry;
if (!mGamelistView)
nameEntry = entry.name;
else if (mUppercase)
nameEntry = Utils::String::toUpper(entry.name);
else if (mLowercase)
nameEntry = Utils::String::toLower(entry.name);
else if (mCapitalize)
nameEntry = Utils::String::toCapitalized(entry.name);
else
nameEntry = entry.name;
auto text = std::make_shared<TextComponent>(
nameEntry, mFont, 0x000000FF, mItemHorizontalAlignment, mItemVerticalAlignment,
entry.name, mFont, 0x000000FF, mItemHorizontalAlignment, mItemVerticalAlignment,
glm::vec3 {0.0f, 0.0f, 0.0f},
glm::round(mItemSize * (mItemScale >= 1.0f ? mItemScale : 1.0f)), 0x00000000);
if (legacyMode) {
@ -287,10 +281,8 @@ void CarouselComponent<T>::addEntry(Entry& entry, const std::shared_ptr<ThemeDat
}
if (!legacyMode) {
text->setLineSpacing(mLineSpacing);
if (!mGamelistView) {
if (mText != "")
text->setValue(mText);
}
if (!mGamelistView)
text->setValue(entry.name);
text->setColor(mTextColor);
text->setBackgroundColor(mTextBackgroundColor);
text->setRenderBackground(true);
@ -317,8 +309,6 @@ void CarouselComponent<T>::addEntry(Entry& entry, const std::shared_ptr<ThemeDat
entry.data.item->setPosition(glm::vec3 {denormalized.x, denormalized.y, 0.0f});
List::add(entry);
mText = "";
}
template <typename T>
@ -934,10 +924,6 @@ void CarouselComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
mCarouselColor = 0xFFFFFFD8;
mCarouselColorEnd = 0xFFFFFFD8;
mZIndex = mDefaultZIndex;
mText = "";
mUppercase = false;
mLowercase = false;
mCapitalize = false;
if (!elem)
return;
@ -1229,36 +1215,60 @@ void CarouselComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
if (elem->has("lineSpacing"))
mLineSpacing = glm::clamp(elem->get<float>("lineSpacing"), 0.5f, 3.0f);
std::string letterCase;
bool hasText {!mGamelistView && elem->has("text")};
if (elem->has("letterCase")) {
letterCase = elem->get<std::string>("letterCase");
const std::string letterCase {elem->get<std::string>("letterCase")};
if (letterCase == "uppercase") {
mUppercase = true;
if (hasText)
mText = Utils::String::toUpper(elem->get<std::string>("text"));
mLetterCase = LetterCase::UPPERCASE;
}
else if (letterCase == "lowercase") {
mLowercase = true;
if (hasText)
mText = Utils::String::toLower(elem->get<std::string>("text"));
mLetterCase = LetterCase::LOWERCASE;
}
else if (letterCase == "capitalize") {
mCapitalize = true;
if (hasText)
mText = Utils::String::toCapitalized(elem->get<std::string>("text"));
mLetterCase = LetterCase::CAPITALIZED;
}
else if (hasText && letterCase == "none") {
mText = elem->get<std::string>("text");
}
else {
else if (letterCase != "none") {
LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property "
"\"letterCase\" for element \""
<< element.substr(9) << "\" defined as \"" << letterCase << "\"";
if (hasText)
mText = elem->get<std::string>("text");
}
}
if (elem->has("letterCaseCollections")) {
const std::string letterCase {elem->get<std::string>("letterCaseCollections")};
if (letterCase == "uppercase") {
mLetterCaseCollections = LetterCase::UPPERCASE;
}
else if (letterCase == "lowercase") {
mLetterCaseCollections = LetterCase::LOWERCASE;
}
else if (letterCase == "capitalize") {
mLetterCaseCollections = LetterCase::CAPITALIZED;
}
else {
LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property "
"\"letterCaseCollections\" for element \""
<< element.substr(9) << "\" defined as \"" << letterCase << "\"";
}
}
if (elem->has("letterCaseGroupedCollections")) {
const std::string letterCase {elem->get<std::string>("letterCaseGroupedCollections")};
if (letterCase == "uppercase") {
mLetterCaseGroupedCollections = LetterCase::UPPERCASE;
}
else if (letterCase == "lowercase") {
mLetterCaseGroupedCollections = LetterCase::LOWERCASE;
}
else if (letterCase == "capitalize") {
mLetterCaseGroupedCollections = LetterCase::CAPITALIZED;
}
else {
LOG(LogWarning) << "CarouselComponent: Invalid theme configuration, property "
"\"letterCaseGroupedCollections\" for element \""
<< element.substr(9) << "\" defined as \"" << letterCase << "\"";
}
}

View file

@ -43,6 +43,9 @@ public:
virtual int getCursor() = 0;
virtual const size_t getNumEntries() = 0;
virtual const bool getFadeAbovePrimary() const = 0;
virtual const LetterCase getLetterCase() const = 0;
virtual const LetterCase getLetterCaseCollections() const = 0;
virtual const LetterCase getLetterCaseGroupedCollections() const = 0;
// Functions used by some primary components.
virtual void onDemandTextureLoad() {}

View file

@ -68,45 +68,6 @@ public:
it->data.textCache.reset();
}
void setUppercase(bool uppercase)
{
mUppercase = uppercase;
if (uppercase) {
mLowercase = false;
mCapitalize = false;
}
for (auto it = mEntries.begin(); it != mEntries.end(); ++it)
it->data.textCache.reset();
}
void setLowercase(bool lowercase)
{
mLowercase = lowercase;
if (lowercase) {
mUppercase = false;
mCapitalize = false;
}
for (auto it = mEntries.begin(); it != mEntries.end(); ++it)
it->data.textCache.reset();
}
void setCapitalize(bool capitalize)
{
mCapitalize = capitalize;
if (capitalize) {
mUppercase = false;
mLowercase = false;
}
for (auto it = mEntries.begin(); it != mEntries.end(); ++it)
it->data.textCache.reset();
}
void setSelectorHeight(float selectorScale) { mSelectorHeight = selectorScale; }
void setSelectorOffsetY(float selectorOffsetY) { mSelectorOffsetY = selectorOffsetY; }
void setSelectorColor(unsigned int color) { mSelectorColor = color; }
@ -120,6 +81,12 @@ public:
void setLineSpacing(float lineSpacing) { mLineSpacing = lineSpacing; }
const std::string& getIndicators() const { return mIndicators; }
const std::string& getCollectionIndicators() const { return mCollectionIndicators; }
const LetterCase getLetterCase() const override { return mLetterCase; }
const LetterCase getLetterCaseCollections() const override { return mLetterCaseCollections; }
const LetterCase getLetterCaseGroupedCollections() const override
{
return mLetterCaseGroupedCollections;
}
protected:
void onShow() override { mLoopTime = 0; }
@ -169,9 +136,9 @@ private:
std::string mCollectionIndicators;
bool mLegacyMode;
bool mFadeAbovePrimary;
bool mUppercase;
bool mLowercase;
bool mCapitalize;
LetterCase mLetterCase;
LetterCase mLetterCaseCollections;
LetterCase mLetterCaseGroupedCollections;
float mLineSpacing;
float mSelectorHeight;
float mSelectorOffsetY;
@ -202,9 +169,9 @@ TextListComponent<T>::TextListComponent()
, mCollectionIndicators {"symbols"}
, mLegacyMode {false}
, mFadeAbovePrimary {false}
, mUppercase {false}
, mLowercase {false}
, mCapitalize {false}
, mLetterCase {LetterCase::NONE}
, mLetterCaseCollections {LetterCase::NONE}
, mLetterCaseGroupedCollections {LetterCase::NONE}
, mLineSpacing {1.5f}
, mSelectorHeight {mFont->getSize() * 1.5f}
, mSelectorOffsetY {0.0f}
@ -435,18 +402,8 @@ template <typename T> void TextListComponent<T>::render(const glm::mat4& parentT
color = mColors[entry.data.colorId];
if (!entry.data.textCache) {
if (mUppercase)
entry.data.textCache = std::unique_ptr<TextCache>(
font->buildTextCache(Utils::String::toUpper(entry.name), 0, 0, 0x000000FF));
else if (mLowercase)
entry.data.textCache = std::unique_ptr<TextCache>(
font->buildTextCache(Utils::String::toLower(entry.name), 0, 0, 0x000000FF));
else if (mCapitalize)
entry.data.textCache = std::unique_ptr<TextCache>(font->buildTextCache(
Utils::String::toCapitalized(entry.name), 0, 0, 0x000000FF));
else
entry.data.textCache =
std::unique_ptr<TextCache>(font->buildTextCache(entry.name, 0, 0, 0x000000FF));
entry.data.textCache =
std::unique_ptr<TextCache>(font->buildTextCache(entry.name, 0, 0, 0x000000FF));
}
if constexpr (std::is_same_v<T, FileData*>) {
@ -604,26 +561,64 @@ void TextListComponent<T>::applyTheme(const std::shared_ptr<ThemeData>& theme,
}
if (properties & LETTER_CASE && elem->has("letterCase")) {
std::string letterCase {elem->get<std::string>("letterCase")};
const std::string letterCase {elem->get<std::string>("letterCase")};
if (letterCase == "uppercase") {
setUppercase(true);
mLetterCase = LetterCase::UPPERCASE;
}
else if (letterCase == "lowercase") {
setLowercase(true);
mLetterCase = LetterCase::LOWERCASE;
}
else if (letterCase == "capitalize") {
setCapitalize(true);
mLetterCase = LetterCase::CAPITALIZED;
}
else if (letterCase != "none") {
LOG(LogWarning) << "TextListComponent: Invalid theme configuration, property "
"<letterCase> defined as \""
<< letterCase << "\"";
"\"letterCase\" for element \""
<< element.substr(9) << "\" defined as \"" << letterCase << "\"";
}
}
if (properties & LETTER_CASE && elem->has("letterCaseCollections")) {
const std::string letterCase {elem->get<std::string>("letterCaseCollections")};
if (letterCase == "uppercase") {
mLetterCaseCollections = LetterCase::UPPERCASE;
}
else if (letterCase == "lowercase") {
mLetterCaseCollections = LetterCase::LOWERCASE;
}
else if (letterCase == "capitalize") {
mLetterCaseCollections = LetterCase::CAPITALIZED;
}
else {
LOG(LogWarning) << "TextListComponent: Invalid theme configuration, property "
"\"letterCaseCollections\" for element \""
<< element.substr(9) << "\" defined as \"" << letterCase << "\"";
}
}
if (properties & LETTER_CASE && elem->has("letterCaseGroupedCollections")) {
const std::string letterCase {elem->get<std::string>("letterCaseGroupedCollections")};
if (letterCase == "uppercase") {
mLetterCaseGroupedCollections = LetterCase::UPPERCASE;
}
else if (letterCase == "lowercase") {
mLetterCaseGroupedCollections = LetterCase::LOWERCASE;
}
else if (letterCase == "capitalize") {
mLetterCaseGroupedCollections = LetterCase::CAPITALIZED;
}
else {
LOG(LogWarning) << "TextListComponent: Invalid theme configuration, property "
"\"letterCaseGroupedCollections\" for element \""
<< element.substr(9) << "\" defined as \"" << letterCase << "\"";
}
}
// Legacy themes only.
if (properties & FORCE_UPPERCASE && elem->has("forceUppercase"))
setUppercase(elem->get<bool>("forceUppercase"));
if (properties & FORCE_UPPERCASE && elem->has("forceUppercase")) {
if (elem->get<bool>("forceUppercase"))
mLetterCase = LetterCase::UPPERCASE;
}
if (properties & LINE_SPACING) {
if (elem->has("lineSpacing"))