diff --git a/es-core/src/GuiComponent.h b/es-core/src/GuiComponent.h index a6d141f65..06dd67847 100644 --- a/es-core/src/GuiComponent.h +++ b/es-core/src/GuiComponent.h @@ -253,6 +253,7 @@ public: // Used to set the parameters for ScrollableContainer. virtual void setScrollParameters(float, float, float) {} + virtual const bool isScrollable() const { return false; } virtual void onFocusGained() {} virtual void onFocusLost() {} diff --git a/es-core/src/components/ScrollableContainer.cpp b/es-core/src/components/ScrollableContainer.cpp index afd6fab1f..c356803ac 100644 --- a/es-core/src/components/ScrollableContainer.cpp +++ b/es-core/src/components/ScrollableContainer.cpp @@ -239,6 +239,9 @@ void ScrollableContainer::render(const glm::mat4& parentTrans) trans = glm::translate(trans, -glm::vec3 {mScrollPos.x, mScrollPos.y, 0.0f}); mRenderer->setMatrix(trans); + if (Settings::getInstance()->getBool("DebugText")) + mRenderer->drawRect(0.0f, mScrollPos.y, mSize.x, mSize.y, 0x0000FF33, 0x0000FF33); + GuiComponent::renderChildren(trans); mRenderer->popClipRect(); } diff --git a/es-core/src/components/ScrollableContainer.h b/es-core/src/components/ScrollableContainer.h index 58dab3d08..01976ccc1 100644 --- a/es-core/src/components/ScrollableContainer.h +++ b/es-core/src/components/ScrollableContainer.h @@ -28,6 +28,8 @@ public: glm::vec2 getScrollPos() const { return mScrollPos; } void setScrollPos(const glm::vec2& pos) { mScrollPos = pos; } + const bool isScrollable() const override { return true; } + void setAutoScroll(bool autoScroll); void setScrollParameters(float autoScrollDelayConstant, float autoScrollResetDelayConstant, diff --git a/es-core/src/components/TextComponent.cpp b/es-core/src/components/TextComponent.cpp index cd8c094bb..f3ea7c139 100644 --- a/es-core/src/components/TextComponent.cpp +++ b/es-core/src/components/TextComponent.cpp @@ -159,7 +159,7 @@ void TextComponent::setCapitalize(bool capitalize) void TextComponent::render(const glm::mat4& parentTrans) { - if (!isVisible() || mThemeOpacity == 0.0f) + if (!isVisible() || mThemeOpacity == 0.0f || mSize.x == 0.0f || mSize.y == 0.0f) return; glm::mat4 trans {parentTrans * getTransform()}; @@ -197,9 +197,12 @@ void TextComponent::render(const glm::mat4& parentTrans) yOff = (getSize().y - textSize.y) / 2.0f; } - // Draw the "textbox" area, what we are aligned within. - if (Settings::getInstance()->getBool("DebugText")) - mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0x0000FF33, 0x0000FF33); + // Draw the overall textbox area. If we're inside a scrollable container then this + // area is rendered inside that component instead of here. + if (Settings::getInstance()->getBool("DebugText")) { + if (!mParent || !mParent->isScrollable()) + mRenderer->drawRect(0.0f, 0.0f, mSize.x, mSize.y, 0x0000FF33, 0x0000FF33); + } trans = glm::translate(trans, glm::vec3 {0.0f, std::round(yOff), 0.0f}); @@ -279,7 +282,7 @@ void TextComponent::onTextChanged() { calculateExtent(); - if (!mFont || mText.empty()) { + if (!mFont || mText.empty() || mSize.x == 0.0f || mSize.y == 0.0f) { mTextCache.reset(); return; } @@ -295,25 +298,27 @@ void TextComponent::onTextChanged() else text = mText; // Original case. - std::shared_ptr f = mFont; - const bool isMultiline = (mSize.y == 0.0f || mSize.y > f->getHeight() * 1.2f); + std::shared_ptr f {mFont}; + const float lineHeight {f->getHeight(mLineSpacing)}; + const bool isMultiline {mSize.y > lineHeight}; + const bool isScrollable {mParent && mParent->isScrollable()}; - bool addAbbrev = false; + bool addAbbrev {false}; if (!isMultiline) { - size_t newline = text.find('\n'); + size_t newline {text.find('\n')}; // Single line of text - stop at the first newline since it'll mess everything up. text = text.substr(0, newline); addAbbrev = newline != std::string::npos; } glm::vec2 size {f->sizeText(text)}; - if (!isMultiline && mSize.x > 0.0f && text.size() && (size.x > mSize.x || addAbbrev)) { + if (!isMultiline && text.size() && (size.x > mSize.x || addAbbrev)) { // Abbreviate text. - const std::string abbrev = "..."; - glm::vec2 abbrevSize {f->sizeText(abbrev)}; + const std::string abbrev {"..."}; + float abbrevSize {f->sizeText(abbrev).x}; - while (text.size() && size.x + abbrevSize.x > mSize.x) { - size_t newSize = Utils::String::prevCursor(text, text.size()); + while (text.size() && size.x + abbrevSize > mSize.x) { + size_t newSize {Utils::String::prevCursor(text, text.size())}; text.erase(newSize, text.size() - newSize); if (!text.empty() && text.back() == ' ') text.pop_back(); @@ -324,6 +329,13 @@ void TextComponent::onTextChanged() mTextCache = std::shared_ptr(f->buildTextCache( text, glm::vec2 {}, mColor, mSize.x, mHorizontalAlignment, mLineSpacing, mNoTopMargin)); } + else if (isMultiline && text.size() && !isScrollable) { + const std::string wrappedText { + f->wrapText(text, mSize.x, mSize.y - lineHeight, mLineSpacing)}; + mTextCache = std::shared_ptr(f->buildTextCache(wrappedText, glm::vec2 {}, mColor, + mSize.x, mHorizontalAlignment, + mLineSpacing, mNoTopMargin)); + } else { mTextCache = std::shared_ptr( f->buildTextCache(f->wrapText(text, mSize.x), glm::vec2 {}, mColor, mSize.x,