// 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