diff --git a/THEMES.md b/THEMES.md index 98f057ae2..30a5db44c 100644 --- a/THEMES.md +++ b/THEMES.md @@ -385,8 +385,8 @@ Can be created as an extra. - Path to a truetype font (.ttf). * `fontSize` - type: FLOAT. - Size of the font as a percentage of screen height (e.g. for a value of `0.1`, the text's height would be 10% of the screen height). -* `center` - type: BOOLEAN. - - True to center, false to left-align. +* `alignment` - type: STRING. + - Valid values are "left", "center", or "right". Controls alignment on the X axis. "center" will also align vertically. #### textlist diff --git a/src/ThemeData.cpp b/src/ThemeData.cpp index c958d7bd1..3594d5f1e 100644 --- a/src/ThemeData.cpp +++ b/src/ThemeData.cpp @@ -38,7 +38,7 @@ std::map< std::string, ElementMapType > ThemeData::sElementMap = boost::assign:: ("color", COLOR) ("fontPath", PATH) ("fontSize", FLOAT) - ("center", BOOLEAN))) + ("alignment", STRING))) ("textlist", makeMap(boost::assign::map_list_of ("pos", NORMALIZED_PAIR) ("size", NORMALIZED_PAIR) diff --git a/src/components/ComponentList.cpp b/src/components/ComponentList.cpp index e0068f5b0..24e52d852 100644 --- a/src/components/ComponentList.cpp +++ b/src/components/ComponentList.cpp @@ -150,7 +150,22 @@ void ComponentList::render(const Eigen::Affine3f& parentTrans) trans.translate(Eigen::Vector3f(0, -round(mCameraOffset), 0)); // draw our entries - renderChildren(trans); + std::vector drawAfterCursor; + bool drawAll; + for(unsigned int i = 0; i < mEntries.size(); i++) + { + auto& entry = mEntries.at(i); + drawAll = !mFocused || i != mCursor; + for(auto it = entry.data.elements.begin(); it != entry.data.elements.end(); it++) + { + if(drawAll || it->invert_when_selected) + { + it->component->render(trans); + }else{ + drawAfterCursor.push_back(it->component.get()); + } + } + } // custom rendering Renderer::setMatrix(trans); @@ -172,6 +187,13 @@ void ComponentList::render(const Eigen::Affine3f& parentTrans) // hack to draw 2px dark on left/right of the bar Renderer::drawRect(0.0f, mSelectorBarOffset, 2.0f, selectedRowHeight, 0x878787FF); Renderer::drawRect(mSize.x() - 2.0f, mSelectorBarOffset, 2.0f, selectedRowHeight, 0x878787FF); + + for(auto it = drawAfterCursor.begin(); it != drawAfterCursor.end(); it++) + (*it)->render(trans); + + // reset matrix if one of these components changed it + if(drawAfterCursor.size()) + Renderer::setMatrix(trans); } // draw separators diff --git a/src/components/ComponentList.h b/src/components/ComponentList.h index c7596bb51..049e89776 100644 --- a/src/components/ComponentList.h +++ b/src/components/ComponentList.h @@ -5,10 +5,12 @@ struct ComponentListElement { - ComponentListElement(const std::shared_ptr& cmp = nullptr, bool resize_w = true) : component(cmp), resize_width(resize_w) { }; + ComponentListElement(const std::shared_ptr& cmp = nullptr, bool resize_w = true, bool inv = true) + : component(cmp), resize_width(resize_w), invert_when_selected(inv) { }; std::shared_ptr component; bool resize_width; + bool invert_when_selected; }; struct ComponentListRow @@ -21,9 +23,9 @@ struct ComponentListRow // the rightmost element in the currently selected row. std::function input_handler; - inline void addElement(const std::shared_ptr& component, bool resize_width) + inline void addElement(const std::shared_ptr& component, bool resize_width, bool invert_when_selected = true) { - elements.push_back(ComponentListElement(component, resize_width)); + elements.push_back(ComponentListElement(component, resize_width, invert_when_selected)); } // Utility method for making an input handler for "when the users presses A on this, do func." diff --git a/src/components/DateTimeComponent.cpp b/src/components/DateTimeComponent.cpp index 390807c85..47a86b534 100644 --- a/src/components/DateTimeComponent.cpp +++ b/src/components/DateTimeComponent.cpp @@ -7,9 +7,9 @@ DateTimeComponent::DateTimeComponent(Window* window, DisplayMode dispMode) : GuiComponent(window), mEditing(false), mEditIndex(0), mDisplayMode(dispMode), mRelativeUpdateAccumulator(0), - mColor(0x000000FF) + mColor(0x777777FF), mFont(Font::get(FONT_SIZE_SMALL, FONT_PATH_LIGHT)) { - mSize << 64, (float)getFont()->getHeight(); + mSize << 64, getFont()->getHeight(); updateTextCache(); } diff --git a/src/components/MenuComponent.cpp b/src/components/MenuComponent.cpp index 010fd7b4b..b6cd3a731 100644 --- a/src/components/MenuComponent.cpp +++ b/src/components/MenuComponent.cpp @@ -15,7 +15,7 @@ MenuComponent::MenuComponent(Window* window, const char* title) : GuiComponent(w mBackground.setImagePath(":/frame.png"); // set up title which will never change - mTitle = std::make_shared(mWindow, strToUpper(title), Font::get(FONT_SIZE_LARGE), 0x555555FF, true); + mTitle = std::make_shared(mWindow, strToUpper(title), Font::get(FONT_SIZE_LARGE), 0x555555FF, TextComponent::ALIGN_CENTER); mGrid.setEntry(mTitle, Vector2i(0, 0), false); // set up list which will never change (externally, anyway) diff --git a/src/components/MenuComponent.h b/src/components/MenuComponent.h index 52e5bae24..7c23672fe 100644 --- a/src/components/MenuComponent.h +++ b/src/components/MenuComponent.h @@ -19,11 +19,11 @@ public: inline void addRow(const ComponentListRow& row, bool setCursorHere = false) { mList->addRow(row, setCursorHere); updateSize(); } - inline void addWithLabel(const std::string& label, const std::shared_ptr& comp, bool setCursorHere = false) + inline void addWithLabel(const std::string& label, const std::shared_ptr& comp, bool setCursorHere = false, bool invert_when_selected = true) { ComponentListRow row; - row.addElement(std::make_shared(mWindow, strToUpper(label), Font::get(FONT_SIZE_MEDIUM), 0x777777FF), true); - row.addElement(comp, false); + row.addElement(std::make_shared(mWindow, strToUpper(label), Font::get(FONT_SIZE_MEDIUM), 0x777777FF), TextComponent::ALIGN_CENTER); + row.addElement(comp, false, invert_when_selected); addRow(row, setCursorHere); } diff --git a/src/components/OptionListComponent.h b/src/components/OptionListComponent.h index ee95eaf60..9d5cec1c7 100644 --- a/src/components/OptionListComponent.h +++ b/src/components/OptionListComponent.h @@ -116,7 +116,7 @@ public: auto font = Font::get(FONT_SIZE_MEDIUM, FONT_PATH_LIGHT); mText.setFont(font); mText.setColor(0x777777FF); - mText.setCentered(true); + mText.setAlignment(TextComponent::ALIGN_CENTER); addChild(&mText); if(mMultiSelect) diff --git a/src/components/TextComponent.cpp b/src/components/TextComponent.cpp index cd997a66a..b2ca17845 100644 --- a/src/components/TextComponent.cpp +++ b/src/components/TextComponent.cpp @@ -6,13 +6,13 @@ #include "../Util.h" TextComponent::TextComponent(Window* window) : GuiComponent(window), - mFont(Font::get(FONT_SIZE_MEDIUM)), mColor(0x000000FF), mAutoCalcExtent(true, true), mCentered(false) + mFont(Font::get(FONT_SIZE_MEDIUM)), mColor(0x000000FF), mAutoCalcExtent(true, true), mAlignment(ALIGN_LEFT) { } -TextComponent::TextComponent(Window* window, const std::string& text, const std::shared_ptr& font, unsigned int color, bool center, +TextComponent::TextComponent(Window* window, const std::string& text, const std::shared_ptr& font, unsigned int color, Alignment align, Eigen::Vector3f pos, Eigen::Vector2f size) : GuiComponent(window), - mFont(NULL), mColor(0x000000FF), mAutoCalcExtent(true, true), mCentered(center) + mFont(NULL), mColor(0x000000FF), mAutoCalcExtent(true, true), mAlignment(align) { setFont(font); setColor(color); @@ -62,11 +62,6 @@ void TextComponent::setText(const std::string& text) onTextChanged(); } -void TextComponent::setCentered(bool center) -{ - mCentered = center; -} - void TextComponent::render(const Eigen::Affine3f& parentTrans) { Eigen::Affine3f trans = roundMatrix(parentTrans * getTransform()); @@ -78,19 +73,28 @@ void TextComponent::render(const Eigen::Affine3f& parentTrans) if(mTextCache) { - if(mCentered) - { - const Eigen::Vector2f& textSize = mTextCache->metrics.size; - Eigen::Vector3f off((getSize().x() - textSize.x()) / 2, (getSize().y() - textSize.y()) / 2, 0); - off = roundVector(off); + const Eigen::Vector2f& textSize = mTextCache->metrics.size; + Eigen::Vector3f off(0, 0, 0); - trans.translate(off); - Renderer::setMatrix(trans); - trans.translate(-off); - }else{ - Renderer::setMatrix(trans); + switch(mAlignment) + { + case ALIGN_LEFT: + break; + + case ALIGN_CENTER: + off << (getSize().x() - textSize.x()) / 2, (getSize().y() - textSize.y()) / 2, 0; + break; + + case ALIGN_RIGHT: + off << (getSize().x() - textSize.x()), 0, 0; + break; } + off = roundVector(off); + trans.translate(off); + Renderer::setMatrix(trans); + trans.translate(-off); + mFont->renderTextCache(mTextCache.get()); } @@ -171,8 +175,18 @@ void TextComponent::applyTheme(const std::shared_ptr& theme, const st if(properties & COLOR && elem->has("color")) setColor(elem->get("color")); - if(properties & ALIGNMENT && elem->has("center")) - setCentered(elem->get("center")); + if(properties & ALIGNMENT && elem->has("alignment")) + { + std::string str = elem->get("alignment"); + if(str == "left") + setAlignment(ALIGN_LEFT); + else if(str == "center") + setAlignment(ALIGN_CENTER); + else if(str == "ALIGN_RIGHT") + setAlignment(ALIGN_RIGHT); + else + LOG(LogError) << "Unknown text alignment string: " << str; + } if(properties & TEXT && elem->has("text")) setText(elem->get("text")); diff --git a/src/components/TextComponent.h b/src/components/TextComponent.h index e3039a2a1..36d825c1b 100644 --- a/src/components/TextComponent.h +++ b/src/components/TextComponent.h @@ -14,15 +14,22 @@ class ThemeData; class TextComponent : public GuiComponent { public: + enum Alignment + { + ALIGN_LEFT, + ALIGN_CENTER, // centers both horizontally and vertically + ALIGN_RIGHT + }; + TextComponent(Window* window); - TextComponent(Window* window, const std::string& text, const std::shared_ptr& font, unsigned int color = 0x000000FF, bool center = false, + TextComponent(Window* window, const std::string& text, const std::shared_ptr& font, unsigned int color = 0x000000FF, Alignment align = ALIGN_LEFT, Eigen::Vector3f pos = Eigen::Vector3f::Zero(), Eigen::Vector2f size = Eigen::Vector2f::Zero()); void setFont(const std::shared_ptr& font); void onSizeChanged() override; void setText(const std::string& text); void setColor(unsigned int color); - void setCentered(bool center); // Will horizontally center text. Default is false. + inline void setAlignment(Alignment align) { mAlignment = align; } void render(const Eigen::Affine3f& parentTrans) override; @@ -47,7 +54,7 @@ private: Eigen::Matrix mAutoCalcExtent; std::string mText; std::shared_ptr mTextCache; - bool mCentered; + Alignment mAlignment; }; #endif diff --git a/src/guis/GuiFastSelect.cpp b/src/guis/GuiFastSelect.cpp index cecf73cfc..d5a36e8a6 100644 --- a/src/guis/GuiFastSelect.cpp +++ b/src/guis/GuiFastSelect.cpp @@ -19,14 +19,14 @@ GuiFastSelect::GuiFastSelect(Window* window, IGameListView* gamelist) : GuiCompo addChild(&mBackground); mLetterText.setSize(mSize.x(), mSize.y() * 0.75f); - mLetterText.setCentered(true); + mLetterText.setAlignment(TextComponent::ALIGN_CENTER); mLetterText.applyTheme(theme, "fastSelect", "letter", FONT_PATH | COLOR); // TODO - set font size addChild(&mLetterText); mSortText.setPosition(0, mSize.y() * 0.75f); mSortText.setSize(mSize.x(), mSize.y() * 0.25f); - mSortText.setCentered(true); + mSortText.setAlignment(TextComponent::ALIGN_CENTER); mSortText.applyTheme(theme, "fastSelect", "subtext", FONT_PATH | COLOR); // TODO - set font size addChild(&mSortText); diff --git a/src/guis/GuiGameScraper.cpp b/src/guis/GuiGameScraper.cpp index 422e3dbd9..cc84870a3 100644 --- a/src/guis/GuiGameScraper.cpp +++ b/src/guis/GuiGameScraper.cpp @@ -19,7 +19,7 @@ GuiGameScraper::GuiGameScraper(Window* window, ScraperSearchParams params, std:: addChild(&mGrid); // header - mHeader = std::make_shared(mWindow, getCleanFileName(mSearchParams.game->getName()), Font::get(FONT_SIZE_LARGE), 0x777777FF, true); + mHeader = std::make_shared(mWindow, getCleanFileName(mSearchParams.game->getName()), Font::get(FONT_SIZE_LARGE), 0x777777FF, TextComponent::ALIGN_CENTER); mGrid.setEntry(mHeader, Eigen::Vector2i(0, 0), false, true); // ScraperSearchComponent diff --git a/src/guis/GuiMetaDataEd.cpp b/src/guis/GuiMetaDataEd.cpp index 83b83939c..47f9f1b4f 100644 --- a/src/guis/GuiMetaDataEd.cpp +++ b/src/guis/GuiMetaDataEd.cpp @@ -31,35 +31,39 @@ GuiMetaDataEd::GuiMetaDataEd(Window* window, MetaDataList* md, const std::vector // create ed and add it (and any related components) to mMenu // ed's value will be set below + ComponentListRow row; + auto lbl = std::make_shared(mWindow, strToUpper(iter->key), Font::get(FONT_SIZE_SMALL), 0x777777FF); + row.addElement(lbl, true); // label + switch(iter->type) { case MD_RATING: { ed = std::make_shared(window); - mMenu.addWithLabel(iter->key, ed); + ed->setSize(0, lbl->getSize().y()); + row.addElement(ed, false, false); + mMenu.addRow(row); break; } case MD_DATE: { ed = std::make_shared(window); - mMenu.addWithLabel(iter->key, ed); + row.addElement(ed, false); + mMenu.addRow(row); break; } case MD_TIME: { ed = std::make_shared(window, DateTimeComponent::DISP_RELATIVE_TO_NOW); - mMenu.addWithLabel(iter->key, ed); + row.addElement(ed, false); + mMenu.addRow(row); break; } case MD_MULTILINE_STRING: default: { // MD_STRING - ComponentListRow row; - auto lbl = std::make_shared(mWindow, iter->key, Font::get(FONT_SIZE_SMALL), 0x777777FF); - row.addElement(lbl, true); // label - - ed = std::make_shared(window, "", Font::get(FONT_SIZE_SMALL, FONT_PATH_LIGHT), 0x777777FF); + ed = std::make_shared(window, "", Font::get(FONT_SIZE_SMALL, FONT_PATH_LIGHT), 0x777777FF, TextComponent::ALIGN_RIGHT); row.addElement(ed, true); auto bracket = std::make_shared(mWindow); diff --git a/src/guis/GuiMsgBox.cpp b/src/guis/GuiMsgBox.cpp index da58c6c5f..5f59a9d0b 100644 --- a/src/guis/GuiMsgBox.cpp +++ b/src/guis/GuiMsgBox.cpp @@ -14,7 +14,7 @@ GuiMsgBox::GuiMsgBox(Window* window, const std::string& text, float width = Renderer::getScreenWidth() * 0.6f; // max width float minWidth = Renderer::getScreenWidth() * 0.3f; // minimum width - mMsg = std::make_shared(mWindow, text, Font::get(FONT_SIZE_MEDIUM), 0x777777FF, true); + mMsg = std::make_shared(mWindow, text, Font::get(FONT_SIZE_MEDIUM), 0x777777FF, TextComponent::ALIGN_CENTER); // create the buttons mButtons.push_back(std::make_shared(mWindow, name1, name1, std::bind(&GuiMsgBox::deleteMeAndCall, this, func1))); diff --git a/src/guis/GuiScraperMulti.cpp b/src/guis/GuiScraperMulti.cpp index 96c766dc3..27cdb2b9c 100644 --- a/src/guis/GuiScraperMulti.cpp +++ b/src/guis/GuiScraperMulti.cpp @@ -20,10 +20,10 @@ GuiScraperMulti::GuiScraperMulti(Window* window, const std::queue(mWindow, "SCRAPING IN PROGRESS", Font::get(FONT_SIZE_SMALL), 0x777777FF, true); + mTitle = std::make_shared(mWindow, "SCRAPING IN PROGRESS", Font::get(FONT_SIZE_SMALL), 0x777777FF, TextComponent::ALIGN_CENTER); mGrid.setEntry(mTitle, Vector2i(0, 0), false, true); - mSubtitle = std::make_shared(mWindow, "subtitle text", Font::get(FONT_SIZE_SMALL), 0x888888FF, true); + mSubtitle = std::make_shared(mWindow, "subtitle text", Font::get(FONT_SIZE_SMALL), 0x888888FF, TextComponent::ALIGN_CENTER); mGrid.setEntry(mSubtitle, Vector2i(0, 1), false, true); mSearchComp = std::make_shared(mWindow, diff --git a/src/guis/GuiTextEditPopup.cpp b/src/guis/GuiTextEditPopup.cpp index 1c540cb12..74b076d90 100644 --- a/src/guis/GuiTextEditPopup.cpp +++ b/src/guis/GuiTextEditPopup.cpp @@ -10,7 +10,7 @@ GuiTextEditPopup::GuiTextEditPopup(Window* window, const std::string& title, con addChild(&mBackground); addChild(&mGrid); - mTitle = std::make_shared(mWindow, strToUpper(title), Font::get(FONT_SIZE_MEDIUM), 0x777777FF, true); + mTitle = std::make_shared(mWindow, strToUpper(title), Font::get(FONT_SIZE_MEDIUM), 0x777777FF, TextComponent::ALIGN_CENTER); mText = std::make_shared(mWindow); mText->setValue(initValue); diff --git a/src/views/SystemView.cpp b/src/views/SystemView.cpp index 8a8bd245e..d01679409 100644 --- a/src/views/SystemView.cpp +++ b/src/views/SystemView.cpp @@ -46,7 +46,7 @@ void SystemView::populate() text->setText((*it)->getName()); text->setSize(logoSize().x(), 0); text->setPosition(0, (logoSize().y() - text->getSize().y()) / 2); // vertically center - text->setCentered(true); // horizontally center + text->setAlignment(TextComponent::ALIGN_CENTER); e.data.logo = std::shared_ptr(text); } diff --git a/src/views/gamelist/ISimpleGameListView.cpp b/src/views/gamelist/ISimpleGameListView.cpp index 262954b96..ed1bf29d9 100644 --- a/src/views/gamelist/ISimpleGameListView.cpp +++ b/src/views/gamelist/ISimpleGameListView.cpp @@ -10,7 +10,7 @@ ISimpleGameListView::ISimpleGameListView(Window* window, FileData* root) : IGame mHeaderText.setText("Logo Text"); mHeaderText.setSize(mSize.x(), 0); mHeaderText.setPosition(0, 0); - mHeaderText.setCentered(true); + mHeaderText.setAlignment(TextComponent::ALIGN_CENTER); mHeaderImage.setResize(0, mSize.y() * 0.185f); mHeaderImage.setOrigin(0.5f, 0.0f);