// SPDX-License-Identifier: MIT // // ES-DE Frontend // TextComponent.h // // Displays text. // #ifndef ES_CORE_COMPONENTS_TEXT_COMPONENT_H #define ES_CORE_COMPONENTS_TEXT_COMPONENT_H #include "GuiComponent.h" #include "resources/Font.h" class ThemeData; // TextComponent sizing works in the following ways: // autoCalcExtent(1, 0) - Automatically expand horizontally, line breaks are removed. // autoCalcExtent(0, 0) - Wrap and abbreviate inside the width and height boundaries. // autoCalcExtent(0, 1) - Limit size horizontally and automatically expand vertically. // autoCalcExtent(1, 1) - Automatically expand horizontally and wrap by line break. // The sizing logic above translates to the following theme configuration: // 0 0 - autoCalcExtent(1, 0) // width 0 - autoCalcExtent(0, 1) // width height - autoCalcExtent(0, 0) class TextComponent : public GuiComponent { public: TextComponent(); TextComponent(const std::string& text, const std::shared_ptr& font, unsigned int color = 0x000000FF, Alignment horizontalAlignment = ALIGN_LEFT, Alignment verticalAlignment = ALIGN_CENTER, glm::ivec2 autoCalcExtent = {1, 0}, glm::vec3 pos = {0.0f, 0.0f, 0.0f}, glm::vec2 size = {0.0f, 0.0f}, unsigned int bgcolor = 0x00000000, float lineSpacing = 1.5f, float relativeScale = 1.0f, bool horizontalScrolling = false, float scrollSpeedMultiplier = 1.0f, float scrollDelay = 1500.0f, float scrollGap = 1.5f, float maxLength = 0.0f); void setFont(const std::shared_ptr& font); void setUppercase(bool uppercase); void setLowercase(bool lowercase); void setCapitalize(bool capitalize); void onSizeChanged() override { onTextChanged(); } void setText(const std::string& text, bool update = true, float maxLength = 0.0f); void setHiddenText(const std::string& text) { mHiddenText = text; } void setAutoCalcExtent(glm::ivec2 extent) override { mAutoCalcExtent = extent; } const glm::ivec2 getAutoCalcExtent() { return mAutoCalcExtent; } void setColor(unsigned int color) override; void setHorizontalAlignment(Alignment align); void setVerticalAlignment(Alignment align) { mVerticalAlignment = align; } void setLineSpacing(float spacing); float getLineSpacing() override { return mLineSpacing; } void setTextShaping(bool state) { mFont->setTextShaping(state); } void setNoTopMargin(bool margin); void setNeedGlyphsPos(bool state) { mNeedGlyphsPos = state; } void setRemoveLineBreaks(bool state) override { mRemoveLineBreaks = state; } void setNoSizeUpdate(bool state) { mNoSizeUpdate = state; } const glm::vec2 getGlyphPosition(int cursor); void setBackgroundColor(unsigned int color) override; void setRenderBackground(bool render) { mRenderBackground = render; } void setBackgroundMargins(const glm::vec2 margins) { mBackgroundMargins = margins; } void setBackgroundCornerRadius(const float radius) { mBackgroundCornerRadius = radius; } // Used by some components that render the debug overlay themselves. void setDebugRendering(bool state) { mDebugRendering = state; } void render(const glm::mat4& parentTrans) override; void onFocusLost() override { resetComponent(); } std::string getValue() const override { return mText; } void setValue(const std::string& value) override; std::string getHiddenValue() const override { return mHiddenText; } void setHiddenValue(const std::string& value) override { setHiddenText(value); } const std::string getDefaultValue() const { return mDefaultValue; } float const getOpacity() const override { return static_cast((mColor & 0x000000FF) / 255.0f); } float const getColorOpacity() const override { return mColorOpacity; } void setOpacity(float opacity) override; void setSaturation(float saturation) override; void setDimming(float dimming) override; void setSelectable(bool status) { mSelectable = status; } void applyTheme(const std::shared_ptr& theme, const std::string& view, const std::string& element, unsigned int properties) override; std::vector getHelpPrompts() override; unsigned int getColor() const override { return mColor; } std::shared_ptr getFont() const override { return mFont; } Alignment getHorizontalAlignment() { return mHorizontalAlignment; } Alignment getVerticalAlignment() { return mVerticalAlignment; } const bool getSystemNameSuffix() const { return mSystemNameSuffix; } const LetterCase getLetterCaseSystemNameSuffix() const { return mLetterCaseSystemNameSuffix; } const TextCache* getTextCache() override { return (mTextCache == nullptr ? nullptr : mTextCache.get()); } // Horizontal scrolling for single-line content that is too long to fit. void setHorizontalScrolling(bool state) override; void setHorizontalScrollingSpeedMultiplier(float speed) { mScrollSpeedMultiplier = speed; } void setHorizontalScrollingDelay(float delay) { mScrollDelay = delay; } void setHorizontalScrollingGap(float gap) { mScrollGap = gap; } void resetComponent() override { mScrollOffset1 = 0; mScrollOffset2 = 0; mScrollTime = 0; } void update(int deltaTime) override; protected: virtual void onTextChanged(); std::string mText; std::string mHiddenText; std::shared_ptr mFont; private: void onColorChanged(); static inline std::vector supportedSystemdataTypes {"name", "fullname", "gamecount", "gamecountGames", "gamecountGamesNoText", "gamecountFavorites", "gamecountFavoritesNoText"}; static inline std::vector supportedMetadataTypes {"name", "description", "rating", "developer", "publisher", "genre", "players", "favorite", "completed", "kidgame", "broken", "playcount", "controller", "altemulator", "emulator", "manual", "physicalName", "physicalNameExtension", "systemName", "systemFullname", "sourceSystemName", "sourceSystemFullname"}; Renderer* mRenderer; std::string mDefaultValue; unsigned int mColor; unsigned int mBgColor; glm::vec2 mBackgroundMargins; float mBackgroundCornerRadius; float mColorOpacity; float mBgColorOpacity; bool mRenderBackground; bool mSystemNameSuffix; LetterCase mLetterCaseSystemNameSuffix; bool mUppercase; bool mLowercase; bool mCapitalize; glm::ivec2 mAutoCalcExtent; std::shared_ptr mTextCache; Alignment mHorizontalAlignment; Alignment mVerticalAlignment; float mLineSpacing; float mRelativeScale; bool mNoTopMargin; bool mNeedGlyphsPos; bool mRemoveLineBreaks; bool mNoSizeUpdate; bool mSelectable; bool mHorizontalScrolling; bool mDebugRendering; float mScrollSpeed; float mScrollSpeedMultiplier; float mScrollDelay; float mScrollGap; float mScrollOffset1; float mScrollOffset2; float mScrollTime; float mMaxLength; }; #endif // ES_CORE_COMPONENTS_TEXT_COMPONENT_H