mirror of
https://github.com/RetroDECK/ES-DE.git
synced 2025-02-16 20:15:38 +00:00
Removed direct use of Font::wrapText() from OptionListComponent, TextEditComponent and TextListComponent
This commit is contained in:
parent
0723ae8364
commit
1d3b2f8066
|
@ -352,12 +352,10 @@ private:
|
|||
// Display the selected entry and left/right option arrows.
|
||||
for (auto it = mEntries.cbegin(); it != mEntries.cend(); ++it) {
|
||||
if (it->selected) {
|
||||
if (it->maxNameLength > 0.0f &&
|
||||
Font::get(FONT_SIZE_MEDIUM)->sizeText(it->name).x > it->maxNameLength) {
|
||||
// A maximum length parameter has been passed and the "name" size surpasses
|
||||
// this value, so abbreviate the string inside the arrows.
|
||||
auto font = Font::get(FONT_SIZE_MEDIUM);
|
||||
mText.setText(font->wrapText(it->name, it->maxNameLength));
|
||||
if (it->maxNameLength > 0.0f) {
|
||||
// A maximum length parameter is passed to make sure the text is
|
||||
// abbreviated if it doesn't fit.
|
||||
mText.setText(it->name, true, it->maxNameLength);
|
||||
}
|
||||
else {
|
||||
mText.setText(it->name);
|
||||
|
|
|
@ -46,6 +46,7 @@ TextComponent::TextComponent()
|
|||
, mScrollOffset1 {0.0f}
|
||||
, mScrollOffset2 {0.0f}
|
||||
, mScrollTime {0.0f}
|
||||
, mMaxLength {0.0f}
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -62,7 +63,8 @@ TextComponent::TextComponent(const std::string& text,
|
|||
bool horizontalScrolling,
|
||||
float scrollSpeedMultiplier,
|
||||
float scrollDelay,
|
||||
float scrollGap)
|
||||
float scrollGap,
|
||||
float maxLength)
|
||||
: mFont {nullptr}
|
||||
, mRenderer {Renderer::getInstance()}
|
||||
, mColor {0x000000FF}
|
||||
|
@ -94,14 +96,18 @@ TextComponent::TextComponent(const std::string& text,
|
|||
, mScrollOffset1 {0.0f}
|
||||
, mScrollOffset2 {0.0f}
|
||||
, mScrollTime {0.0f}
|
||||
, mMaxLength {maxLength}
|
||||
{
|
||||
setFont(font);
|
||||
setColor(color);
|
||||
setBackgroundColor(bgcolor);
|
||||
setHorizontalScrolling(mHorizontalScrolling);
|
||||
setText(text, false);
|
||||
setText(text, false, mMaxLength);
|
||||
setPosition(pos);
|
||||
setSize(size);
|
||||
if (mMaxLength == 0.0f)
|
||||
setSize(size);
|
||||
else
|
||||
setSize(glm::vec2 {mMaxLength, size.y});
|
||||
}
|
||||
|
||||
void TextComponent::onSizeChanged()
|
||||
|
@ -172,12 +178,13 @@ void TextComponent::setDimming(float dimming)
|
|||
mTextCache->setDimming(dimming);
|
||||
}
|
||||
|
||||
void TextComponent::setText(const std::string& text, bool update)
|
||||
void TextComponent::setText(const std::string& text, bool update, float maxLength)
|
||||
{
|
||||
if (mText == text)
|
||||
if (mText == text && mMaxLength == maxLength)
|
||||
return;
|
||||
|
||||
mText = text;
|
||||
mMaxLength = maxLength;
|
||||
|
||||
if (update)
|
||||
onTextChanged();
|
||||
|
@ -475,7 +482,9 @@ void TextComponent::onTextChanged()
|
|||
|
||||
if (mFont && mAutoCalcExtent.x) {
|
||||
mSize = mFont->sizeText(text, mLineSpacing);
|
||||
if (mSize.x == 0.0f)
|
||||
if (mMaxLength > 0.0f && mSize.x > mMaxLength)
|
||||
mSize.x = std::round(mMaxLength);
|
||||
else if (mSize.x == 0.0f)
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -486,7 +495,8 @@ void TextComponent::onTextChanged()
|
|||
const float lineHeight {mFont->getHeight(mLineSpacing)};
|
||||
const bool isScrollable {mParent && mParent->isScrollable()};
|
||||
|
||||
const bool isMultiline {mAutoCalcExtent.y == 1 || mSize.y * mRelativeScale > lineHeight};
|
||||
// Add one extra pixel to lineHeight as the font may be fractional in size.
|
||||
const bool isMultiline {mAutoCalcExtent.y == 1 || mSize.y * mRelativeScale > lineHeight + 1};
|
||||
float offsetY {0.0f};
|
||||
|
||||
if (mHorizontalScrolling) {
|
||||
|
|
|
@ -35,14 +35,15 @@ public:
|
|||
bool horizontalScrolling = false,
|
||||
float scrollSpeedMultiplier = 1.0f,
|
||||
float scrollDelay = 1500.0f,
|
||||
float scrollGap = 1.5f);
|
||||
float scrollGap = 1.5f,
|
||||
float maxLength = 0.0f);
|
||||
|
||||
void setFont(const std::shared_ptr<Font>& font);
|
||||
void setUppercase(bool uppercase);
|
||||
void setLowercase(bool lowercase);
|
||||
void setCapitalize(bool capitalize);
|
||||
void onSizeChanged() override;
|
||||
void setText(const std::string& text, bool update = true);
|
||||
void setText(const std::string& text, bool update = true, float maxLength = 0.0f);
|
||||
void setHiddenText(const std::string& text) { mHiddenText = text; }
|
||||
void setColor(unsigned int color) override;
|
||||
void setHorizontalAlignment(Alignment align);
|
||||
|
@ -188,6 +189,7 @@ private:
|
|||
float mScrollOffset1;
|
||||
float mScrollOffset2;
|
||||
float mScrollTime;
|
||||
float mMaxLength;
|
||||
};
|
||||
|
||||
#endif // ES_CORE_COMPONENTS_TEXT_COMPONENT_H
|
||||
|
|
|
@ -28,6 +28,7 @@ TextEditComponent::TextEditComponent()
|
|||
, mFocused {false}
|
||||
, mEditing {false}
|
||||
, mMaskInput {true}
|
||||
, mMultiLine {false}
|
||||
, mCursor {0}
|
||||
, mBlinkTime {0}
|
||||
, mCursorRepeatDir {0}
|
||||
|
@ -76,10 +77,10 @@ void TextEditComponent::onSizeChanged()
|
|||
onTextChanged(); // Wrap point probably changed.
|
||||
}
|
||||
|
||||
void TextEditComponent::setValue(const std::string& val)
|
||||
void TextEditComponent::setValue(const std::string& val, bool multiLine, bool update)
|
||||
{
|
||||
mText = val;
|
||||
mTextOrig = val;
|
||||
mMultiLine = multiLine;
|
||||
onTextChanged();
|
||||
onCursorChanged();
|
||||
}
|
||||
|
@ -92,7 +93,7 @@ void TextEditComponent::textInput(const std::string& text, const bool pasting)
|
|||
#endif
|
||||
|
||||
// Allow pasting up to a reasonable max clipboard size.
|
||||
if (pasting && text.length() > (isMultiline() ? 16384 : 300))
|
||||
if (pasting && text.length() > (mMultiLine ? 16384 : 300))
|
||||
return;
|
||||
|
||||
if (mEditing) {
|
||||
|
@ -106,12 +107,10 @@ void TextEditComponent::textInput(const std::string& text, const bool pasting)
|
|||
}
|
||||
}
|
||||
else {
|
||||
mText.insert(
|
||||
mCursor,
|
||||
(pasting && !isMultiline() ? Utils::String::replace(text, "\n", " ") : text));
|
||||
mText.insert(mCursor,
|
||||
(pasting && !mMultiLine ? Utils::String::replace(text, "\n", " ") : text));
|
||||
mCursor += static_cast<unsigned int>(
|
||||
(pasting && !isMultiline() ? Utils::String::replace(text, "\n", " ") : text)
|
||||
.size());
|
||||
(pasting && !mMultiLine ? Utils::String::replace(text, "\n", " ") : text).size());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,7 +190,7 @@ bool TextEditComponent::input(InputConfig* config, Input input)
|
|||
if (config->getDeviceId() == DEVICE_KEYBOARD) {
|
||||
// Special handling for keyboard input as the "A" and "B" buttons are overridden.
|
||||
if (input.id == SDLK_RETURN || input.id == SDLK_KP_ENTER) {
|
||||
if (isMultiline()) {
|
||||
if (mMultiLine) {
|
||||
const bool maskValue {mMaskInput};
|
||||
mMaskInput = false;
|
||||
textInput("\n");
|
||||
|
@ -311,11 +310,11 @@ void TextEditComponent::setCursor(size_t pos)
|
|||
|
||||
void TextEditComponent::onTextChanged()
|
||||
{
|
||||
mWrappedText =
|
||||
(isMultiline() ? getFont()->wrapText(mText, getTextAreaSize().x, 0.0f, 1.5f, true) : mText);
|
||||
mEditText->setText(mWrappedText);
|
||||
// Setting the Y size to zero makes the text area expand vertically as needed.
|
||||
mEditText->setSize(mEditText->getSize().x, 0.0f);
|
||||
if (mMultiLine)
|
||||
mEditText->setText(mText, true, mSize.x);
|
||||
else
|
||||
mEditText->setText(mText);
|
||||
|
||||
mEditText->setColor(mMenuColorKeyboardText | static_cast<unsigned char>(mOpacity * 255.0f));
|
||||
|
||||
if (mCursor > static_cast<int>(mText.length()))
|
||||
|
@ -324,8 +323,8 @@ void TextEditComponent::onTextChanged()
|
|||
|
||||
void TextEditComponent::onCursorChanged()
|
||||
{
|
||||
if (isMultiline()) {
|
||||
mCursorPos = getFont()->getWrappedTextCursorOffset(mWrappedText, mCursor);
|
||||
if (mMultiLine) {
|
||||
mCursorPos = getFont()->getWrappedTextCursorOffset(mText, mCursor);
|
||||
|
||||
// Need to scroll down?
|
||||
if (mScrollOffset.y + getTextAreaSize().y < mCursorPos.y + getFont()->getHeight())
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
|
||||
void onSizeChanged() override;
|
||||
|
||||
void setValue(const std::string& val) override;
|
||||
void setValue(const std::string& val, bool multiLine, bool update = true);
|
||||
std::string getValue() const override;
|
||||
|
||||
void startEditing();
|
||||
|
@ -50,17 +50,15 @@ private:
|
|||
void updateCursorRepeat(int deltaTime);
|
||||
void moveCursor(int amt);
|
||||
|
||||
bool isMultiline() { return (getSize().y > getFont()->getHeight() * 1.25f); }
|
||||
glm::vec2 getTextAreaPos() const;
|
||||
glm::vec2 getTextAreaSize() const;
|
||||
|
||||
Renderer* mRenderer;
|
||||
std::string mText;
|
||||
std::string mWrappedText;
|
||||
std::string mTextOrig;
|
||||
bool mFocused;
|
||||
bool mEditing;
|
||||
bool mMaskInput;
|
||||
bool mMultiLine;
|
||||
int mCursor; // Cursor position in characters.
|
||||
int mBlinkTime;
|
||||
|
||||
|
|
|
@ -201,11 +201,17 @@ TextListComponent<T>::TextListComponent()
|
|||
template <typename T>
|
||||
void TextListComponent<T>::addEntry(Entry& entry, const std::shared_ptr<ThemeData>& theme)
|
||||
{
|
||||
entry.data.entryName = std::make_shared<TextComponent>(
|
||||
mHorizontalScrolling ? entry.name :
|
||||
mFont->wrapText(entry.name, mSize.x - mHorizontalMargin * 2.0f),
|
||||
mFont, 0x000000FF, ALIGN_LEFT, ALIGN_CENTER, glm::vec3 {0.0f, 0.0f, 0.0f},
|
||||
glm::vec2 {mFont->sizeText(entry.name).x, mFont->getSize() * 1.5f});
|
||||
if (mHorizontalScrolling) {
|
||||
entry.data.entryName = std::make_shared<TextComponent>(
|
||||
entry.name, mFont, 0x000000FF, ALIGN_LEFT, ALIGN_CENTER, glm::vec3 {0.0f, 0.0f, 0.0f},
|
||||
glm::vec2 {mFont->sizeText(entry.name).x, mFont->getSize() * 1.5f});
|
||||
}
|
||||
else {
|
||||
entry.data.entryName = std::make_shared<TextComponent>(
|
||||
entry.name, mFont, 0x000000FF, ALIGN_LEFT, ALIGN_CENTER, glm::vec3 {0.0f, 0.0f, 0.0f},
|
||||
glm::vec2 {mFont->sizeText(entry.name).x, mFont->getSize() * 1.5f}, 0x00000000, 1.5f,
|
||||
1.0f, false, 1.0f, 1500.0f, 1.5f, mSize.x - (mHorizontalMargin * 2.0f));
|
||||
}
|
||||
|
||||
if (mHorizontalScrolling) {
|
||||
glm::vec2 textSize {entry.data.entryName->getSize()};
|
||||
|
|
|
@ -135,7 +135,7 @@ GuiTextEditKeyboardPopup::GuiTextEditKeyboardPopup(
|
|||
glm::ivec2 {mHorizontalKeyCount, static_cast<int>(kbLayout.size()) / 3});
|
||||
|
||||
mText = std::make_shared<TextEditComponent>();
|
||||
mText->setValue(initValue);
|
||||
mText->setValue(initValue, mMultiLine, false);
|
||||
|
||||
// Header.
|
||||
mGrid.setEntry(mTitle, glm::ivec2 {0, 0}, false, true);
|
||||
|
@ -685,12 +685,12 @@ std::shared_ptr<ButtonComponent> GuiTextEditKeyboardPopup::makeButton(
|
|||
return;
|
||||
}
|
||||
else if (key == _("LOAD")) {
|
||||
mText->setValue(mDefaultValue->getValue());
|
||||
mText->setValue(mDefaultValue->getValue(), mMultiLine);
|
||||
mText->setCursor(mDefaultValue->getValue().size());
|
||||
return;
|
||||
}
|
||||
else if (key == _("CLEAR")) {
|
||||
mText->setValue("");
|
||||
mText->setValue("", mMultiLine);
|
||||
return;
|
||||
}
|
||||
else if (key == _("CANCEL")) {
|
||||
|
|
|
@ -56,7 +56,7 @@ GuiTextEditPopup::GuiTextEditPopup(const HelpStyle& helpstyle,
|
|||
}
|
||||
|
||||
mText = std::make_shared<TextEditComponent>();
|
||||
mText->setValue(initValue);
|
||||
mText->setValue(initValue, mMultiLine, false);
|
||||
|
||||
std::vector<std::shared_ptr<ButtonComponent>> buttons;
|
||||
buttons.push_back(
|
||||
|
@ -67,14 +67,14 @@ GuiTextEditPopup::GuiTextEditPopup(const HelpStyle& helpstyle,
|
|||
if (mComplexMode) {
|
||||
buttons.push_back(
|
||||
std::make_shared<ButtonComponent>(_("LOAD"), loadBtnHelpText, [this, defaultValue] {
|
||||
mText->setValue(defaultValue);
|
||||
mText->setValue(defaultValue, mMultiLine);
|
||||
mText->setCursor(0);
|
||||
mText->setCursor(defaultValue.size());
|
||||
}));
|
||||
}
|
||||
|
||||
buttons.push_back(std::make_shared<ButtonComponent>(_("CLEAR"), clearBtnHelpText,
|
||||
[this] { mText->setValue(""); }));
|
||||
buttons.push_back(std::make_shared<ButtonComponent>(
|
||||
_("CLEAR"), clearBtnHelpText, [this] { mText->setValue("", mMultiLine); }));
|
||||
|
||||
buttons.push_back(std::make_shared<ButtonComponent>(_("CANCEL"), _("discard changes"),
|
||||
[this] { delete this; }));
|
||||
|
|
|
@ -22,6 +22,9 @@ Font::Font(float size, const std::string& path)
|
|||
, mFontSize {size}
|
||||
, mLetterHeight {0.0f}
|
||||
, mMaxGlyphHeight {static_cast<int>(std::round(size))}
|
||||
, mWrapMaxLength {0.0f}
|
||||
, mWrapMaxHeight {0.0f}
|
||||
, mWrapLineSpacing {1.5f}
|
||||
{
|
||||
if (mFontSize < 3.0f) {
|
||||
mFontSize = 3.0f;
|
||||
|
@ -195,6 +198,14 @@ std::string Font::wrapText(const std::string& text,
|
|||
bool addEllipsis {false};
|
||||
float totalWidth {0.0f};
|
||||
|
||||
mWrapMaxLength = maxLength;
|
||||
mWrapMaxHeight = maxHeight;
|
||||
mWrapLineSpacing = lineSpacing;
|
||||
|
||||
// TODO: Fix this rounding issue properly elsewhere.
|
||||
if (mWrapMaxHeight < 1.0f)
|
||||
mWrapMaxHeight = 0.0f;
|
||||
|
||||
std::vector<ShapeSegment> segmentsHB;
|
||||
shapeText(text, segmentsHB);
|
||||
|
||||
|
@ -230,7 +241,7 @@ std::string Font::wrapText(const std::string& text,
|
|||
break;
|
||||
}
|
||||
accumHeight += lineHeight;
|
||||
if (maxHeight != 0.0f && accumHeight > maxHeight) {
|
||||
if (mWrapMaxHeight != 0.0f && accumHeight > mWrapMaxHeight) {
|
||||
addEllipsis = true;
|
||||
break;
|
||||
}
|
||||
|
@ -272,7 +283,7 @@ std::string Font::wrapText(const std::string& text,
|
|||
break;
|
||||
}
|
||||
else {
|
||||
if (maxHeight == 0.0f || accumHeight < maxHeight) {
|
||||
if (mWrapMaxHeight == 0.0f || accumHeight < mWrapMaxHeight) {
|
||||
// New row.
|
||||
float spaceOffset {0.0f};
|
||||
if (lastSpace == wrappedText.size()) {
|
||||
|
@ -336,7 +347,7 @@ std::string Font::wrapText(const std::string& text,
|
|||
return wrappedText;
|
||||
}
|
||||
|
||||
glm::vec2 Font::getWrappedTextCursorOffset(const std::string& wrappedText,
|
||||
glm::vec2 Font::getWrappedTextCursorOffset(const std::string& text,
|
||||
const size_t stop,
|
||||
const float lineSpacing)
|
||||
{
|
||||
|
@ -344,6 +355,9 @@ glm::vec2 Font::getWrappedTextCursorOffset(const std::string& wrappedText,
|
|||
float yPos {0.0f};
|
||||
size_t cursor {0};
|
||||
|
||||
const std::string wrappedText {
|
||||
wrapText(text, mWrapMaxLength, mWrapMaxHeight, mWrapLineSpacing, true)};
|
||||
|
||||
// TODO: Enable this code when shaped text is properly wrapped in wrapText().
|
||||
// std::vector<ShapeSegment> segmentsHB;
|
||||
// shapeText(wrappedText, segmentsHB);
|
||||
|
@ -753,9 +767,12 @@ void Font::shapeText(const std::string& text, std::vector<ShapeSegment>& segment
|
|||
segment.length = static_cast<unsigned int>(textCursor - lastFlushPos);
|
||||
segment.fontHB = (lastFont == nullptr ? currGlyph->fontHB : lastFont);
|
||||
segment.doShape = shapeSegment;
|
||||
#if !defined(NDEBUG)
|
||||
segment.substring = text.substr(lastFlushPos, textCursor - lastFlushPos);
|
||||
#else
|
||||
if (!shapeSegment)
|
||||
segment.substring = text.substr(lastFlushPos, textCursor - lastFlushPos);
|
||||
|
||||
#endif
|
||||
segmentsHB.emplace_back(std::move(segment));
|
||||
|
||||
lastFlushPos = textCursor;
|
||||
|
|
|
@ -95,7 +95,7 @@ public:
|
|||
const bool multiLine = false);
|
||||
|
||||
// Returns the position of the cursor after moving it to the stop position.
|
||||
glm::vec2 getWrappedTextCursorOffset(const std::string& wrappedText,
|
||||
glm::vec2 getWrappedTextCursorOffset(const std::string& text,
|
||||
const size_t stop,
|
||||
const float lineSpacing = 1.5f);
|
||||
|
||||
|
@ -248,6 +248,9 @@ private:
|
|||
float mFontSize;
|
||||
float mLetterHeight;
|
||||
int mMaxGlyphHeight;
|
||||
float mWrapMaxLength;
|
||||
float mWrapMaxHeight;
|
||||
float mWrapLineSpacing;
|
||||
};
|
||||
|
||||
// Caching of shaped and rendered text.
|
||||
|
|
Loading…
Reference in a new issue