From e8e8ce6199ca4686debe10069aa68213e253b478 Mon Sep 17 00:00:00 2001 From: Jonekk Date: Mon, 4 Nov 2024 10:26:47 +0100 Subject: [PATCH] Fixed text wrapping in editable text windows, added text wrapping to report window --- modules/game_bugreport/bugreport.otui | 1 + src/framework/graphics/bitmapfont.cpp | 3 +- src/framework/ui/uitextedit.cpp | 41 +++++++++++++++++++++------ src/framework/ui/uiwidget.cpp | 34 ++++++++++++++++++++++ src/framework/ui/uiwidget.h | 4 +++ 5 files changed, 73 insertions(+), 10 deletions(-) diff --git a/modules/game_bugreport/bugreport.otui b/modules/game_bugreport/bugreport.otui index 8ce215e2..066ba4b9 100644 --- a/modules/game_bugreport/bugreport.otui +++ b/modules/game_bugreport/bugreport.otui @@ -14,6 +14,7 @@ BugReportWindow < MainWindow MultilineTextEdit id: bugTextEdit + text-wrap: true anchors.top: bugLabel.bottom anchors.left: parent.left anchors.right: parent.right diff --git a/src/framework/graphics/bitmapfont.cpp b/src/framework/graphics/bitmapfont.cpp index 44d3bfd3..9881c783 100644 --- a/src/framework/graphics/bitmapfont.cpp +++ b/src/framework/graphics/bitmapfont.cpp @@ -300,6 +300,7 @@ std::string BitmapFont::wrapText(const std::string& text, int maxWidth, std::vec lastSeparator = i + 1; lastColorSeparator = c; } else { // space + outText += ' '; wordLength = m_glyphsSize[glyph].width() + m_glyphSpacing.width(); // space lastSeparator = i; lastColorSeparator = c; @@ -328,7 +329,7 @@ std::string BitmapFont::wrapText(const std::string& text, int maxWidth, std::vec outText += '-'; // word continuation outText += '\n'; // new line - wordLength = m_glyphsSize[glyph].width() + m_glyphSpacing.width(); + wordLength = m_glyphsSize[glyph].width() + m_glyphsSize['-'].width() + m_glyphSpacing.width(); lineLength = 0; lastSeparator = i; lastColorSeparator = c; diff --git a/src/framework/ui/uitextedit.cpp b/src/framework/ui/uitextedit.cpp index 51c66d02..d87cd18c 100644 --- a/src/framework/ui/uitextedit.cpp +++ b/src/framework/ui/uitextedit.cpp @@ -112,8 +112,20 @@ void UITextEdit::drawSelf(Fw::DrawPane drawPane) if(hasSelection()) { if(glyphsMustRecache) { m_glyphsSelectCoordsBuffer.clear(); - for(int i=m_selectionStart;i= m_selectionStart) { + m_glyphsSelectCoordsBuffer.addRect(m_glyphsCoords[draw_text_pos], m_glyphsTexCoords[draw_text_pos]); + } + draw_text_pos++; + } } g_drawQueue->addFillCoords(m_glyphsSelectCoordsBuffer, m_selectionBackgroundColor); g_drawQueue->addTextureCoords(m_glyphsSelectCoordsBuffer, texture, m_selectionColor); @@ -130,8 +142,18 @@ void UITextEdit::drawSelf(Fw::DrawPane drawPane) // when cursor is at 0 if(m_cursorPos == 0) cursorRect = Rect(m_rect.left()+m_padding.left, m_rect.top()+m_padding.top, 1, m_font->getGlyphHeight()); - else - cursorRect = Rect(m_glyphsCoords[m_cursorPos-1].right(), m_glyphsCoords[m_cursorPos-1].top(), 1, m_font->getGlyphHeight()); + else { + unsigned draw_cursor_pos = getDrawTextPosForTextPos(m_cursorPos); + // first glyph in new line + if (m_drawText[draw_cursor_pos - 1] == '\n') { + cursorRect = Rect(m_rect.left()+m_padding.left, m_glyphsCoords[draw_cursor_pos - 1].top(), 1, m_font->getGlyphHeight()); + // end of text or newline glyph + } else if (draw_cursor_pos == m_drawText.length() || m_text[m_cursorPos] == '\n') { + cursorRect = Rect(m_glyphsCoords[draw_cursor_pos - 1].right(), m_glyphsCoords[draw_cursor_pos - 1].top(), 1, m_font->getGlyphHeight()); + } else { + cursorRect = Rect(m_glyphsCoords[draw_cursor_pos].left(), m_glyphsCoords[draw_cursor_pos].top(), 1, m_font->getGlyphHeight()); + } + } if (hasSelection() && m_cursorPos >= m_selectionStart && m_cursorPos <= m_selectionEnd) g_drawQueue->addFilledRect(cursorRect, m_selectionColor); @@ -229,9 +251,10 @@ void UITextEdit::update(bool focusCursor) } else { if(m_cursorPos > 0 && textLength > 0) { Rect virtualRect(m_textVirtualOffset, m_rect.size() - Size(2*m_padding.left+m_padding.right, 0) ); // previous rendered virtual rect - int pos = m_cursorPos - 1; // element before cursor - glyph = (uchar)text[pos]; // glyph of the element before cursor - Rect glyphRect(glyphsPositions[pos], glyphsSize[glyph]); + int drawPos = getDrawTextPosForTextPos(m_cursorPos); // cursor pos + if (text[drawPos] == '\0') drawPos--; + glyph = (uchar)text[drawPos]; // glyph of the element after cursor + Rect glyphRect(glyphsPositions[drawPos], glyphsSize[glyph]); if(virtualRect.contains(glyphRect.topLeft()) && virtualRect.contains(glyphRect.bottomRight())) m_cursorInRange = true; } else { @@ -285,7 +308,7 @@ void UITextEdit::update(bool focusCursor) m_glyphsCoords[i].clear(); // skip invalid glyphs - if(glyph < 32) + if(glyph < 32 && glyph != '\n') continue; // calculate initial glyph rect and texture coords @@ -627,7 +650,7 @@ int UITextEdit::getTextPos(Point pos) return textLength; } - return candidatePos; + return getTextPosForDrawTextPos(candidatePos); } std::string UITextEdit::getDisplayedText() diff --git a/src/framework/ui/uiwidget.cpp b/src/framework/ui/uiwidget.cpp index 62f32ef4..d5a76c99 100644 --- a/src/framework/ui/uiwidget.cpp +++ b/src/framework/ui/uiwidget.cpp @@ -2088,3 +2088,37 @@ bool UIWidget::isCharacterValid(char character) return false; } } + +unsigned UIWidget::getDrawTextPosForTextPos(unsigned tp) +{ + unsigned text_pos = 0; + unsigned draw_text_pos = 0; + + for (text_pos = 0; text_pos <= tp; text_pos++) { + while (draw_text_pos < m_drawText.length() && + m_text[text_pos] != m_drawText[draw_text_pos] && (m_text[text_pos] != ' ' || (m_drawText[draw_text_pos] != '-' && m_drawText[draw_text_pos] != '\n'))) { + draw_text_pos++; + } + if (text_pos == tp) { + return draw_text_pos; + } + draw_text_pos++; + } +} + +unsigned UIWidget::getTextPosForDrawTextPos(unsigned dtp) +{ + unsigned text_pos = 0; + unsigned draw_text_pos = 0; + + for (text_pos = 0; text_pos < m_text.length() && draw_text_pos < m_drawText.length(); text_pos++) { + while (draw_text_pos < m_drawText.length() && + m_text[text_pos] != m_drawText[draw_text_pos] && (m_text[text_pos] != ' ' || (m_drawText[draw_text_pos] != '-' && m_drawText[draw_text_pos] != '\n'))) { + draw_text_pos++; + } + if (draw_text_pos == dtp) { + return text_pos; + } + draw_text_pos++; + } +} \ No newline at end of file diff --git a/src/framework/ui/uiwidget.h b/src/framework/ui/uiwidget.h index e172a04f..1cd7a30c 100644 --- a/src/framework/ui/uiwidget.h +++ b/src/framework/ui/uiwidget.h @@ -581,6 +581,10 @@ class UIWidget : public LuaObject std::string getFont() { return m_font->getName(); } Size getTextSize() { return m_font->calculateTextRectSize(m_drawText); } std::string getTextByPos(const Point& mousePos); + + // Basing on bitmapfont module text wrapping + unsigned getDrawTextPosForTextPos(unsigned text_pos); + unsigned getTextPosForDrawTextPos(unsigned dtp); }; #endif