diff --git a/SDK/include/NDK/Widgets/TextAreaWidget.hpp b/SDK/include/NDK/Widgets/TextAreaWidget.hpp index 0bf5a3a59..7bab6f1bf 100644 --- a/SDK/include/NDK/Widgets/TextAreaWidget.hpp +++ b/SDK/include/NDK/Widgets/TextAreaWidget.hpp @@ -32,7 +32,8 @@ namespace Ndk inline void EnableMultiline(bool enable = true); - inline std::size_t GetCursorPosition() const; + inline const Nz::Vector2ui& GetCursorPosition() const; + inline std::size_t GetGlyphUnderCursor() const; inline std::size_t GetLineCount() const; inline const Nz::String& GetText() const; inline const Nz::Color& GetTextColor() const; @@ -43,10 +44,12 @@ namespace Ndk inline bool IsReadOnly() const; inline void MoveCursor(int offset); + inline void MoveCursor(const Nz::Vector2i& offset); void ResizeToContent() override; - inline void SetCursorPosition(std::size_t cursorPosition); + inline void SetCursorPosition(std::size_t glyphIndex); + inline void SetCursorPosition(Nz::Vector2ui cursorPosition); inline void SetReadOnly(bool readOnly = true); inline void SetText(const Nz::String& text); inline void SetTextColor(const Nz::Color& text); @@ -82,7 +85,8 @@ namespace Ndk Nz::SimpleTextDrawer m_drawer; Nz::SpriteRef m_cursorSprite; Nz::TextSpriteRef m_textSprite; - std::size_t m_cursorPosition; + Nz::Vector2ui m_cursorPosition; + std::size_t m_cursorGlyph; bool m_multiLineEnabled; bool m_readOnly; }; diff --git a/SDK/include/NDK/Widgets/TextAreaWidget.inl b/SDK/include/NDK/Widgets/TextAreaWidget.inl index 077f538ec..f76147ec7 100644 --- a/SDK/include/NDK/Widgets/TextAreaWidget.inl +++ b/SDK/include/NDK/Widgets/TextAreaWidget.inl @@ -20,11 +20,16 @@ namespace Ndk m_multiLineEnabled = enable; } - inline std::size_t TextAreaWidget::GetCursorPosition() const + inline const Nz::Vector2ui& TextAreaWidget::GetCursorPosition() const { return m_cursorPosition; } + inline std::size_t Ndk::TextAreaWidget::GetGlyphUnderCursor() const + { + return m_cursorGlyph; + } + inline std::size_t TextAreaWidget::GetLineCount() const { return m_drawer.GetLineCount(); @@ -53,26 +58,80 @@ namespace Ndk inline void TextAreaWidget::MoveCursor(int offset) { if (offset >= 0) - SetCursorPosition(m_cursorPosition += static_cast(offset)); + SetCursorPosition(m_cursorGlyph + static_cast(offset)); else { std::size_t nOffset = static_cast(-offset); - if (nOffset >= m_cursorPosition) + if (nOffset >= m_cursorGlyph) SetCursorPosition(0); else - SetCursorPosition(m_cursorPosition - nOffset); + SetCursorPosition(m_cursorGlyph - nOffset); } } - inline void TextAreaWidget::SetCursorPosition(std::size_t cursorPosition) + inline void TextAreaWidget::MoveCursor(const Nz::Vector2i& offset) { - OnTextAreaCursorMove(this, &cursorPosition); + auto BoundOffset = [] (unsigned int cursorPosition, int offset) -> unsigned int + { + if (offset >= 0) + return cursorPosition + offset; + else + { + unsigned int nOffset = static_cast(-offset); + if (nOffset >= cursorPosition) + return 0; + else + return cursorPosition - nOffset; + } + }; - m_cursorPosition = std::min(cursorPosition, m_drawer.GetGlyphCount()); + Nz::Vector2ui cursorPosition = m_cursorPosition; + cursorPosition.x = BoundOffset(static_cast(cursorPosition.x), offset.x); + cursorPosition.y = BoundOffset(static_cast(cursorPosition.y), offset.y); + + SetCursorPosition(cursorPosition); + } + + inline void TextAreaWidget::SetCursorPosition(std::size_t glyphIndex) + { + OnTextAreaCursorMove(this, &glyphIndex); + + m_cursorGlyph = std::min(glyphIndex, m_drawer.GetGlyphCount()); + + std::size_t lineCount = m_drawer.GetLineCount(); + std::size_t line = 0U; + for (std::size_t i = line + 1; i < lineCount; ++i) + { + if (m_drawer.GetLine(i).glyphIndex > m_cursorGlyph) + break; + + line = i; + } + + const auto& lineInfo = m_drawer.GetLine(line); + + m_cursorPosition.y = line; + m_cursorPosition.x = m_cursorGlyph - lineInfo.glyphIndex; RefreshCursor(); } + inline void TextAreaWidget::SetCursorPosition(Nz::Vector2ui cursorPosition) + { + std::size_t lineCount = m_drawer.GetLineCount(); + if (cursorPosition.y >= lineCount) + cursorPosition.y = static_cast(lineCount - 1); + + const auto& lineInfo = m_drawer.GetLine(cursorPosition.y); + if (cursorPosition.y + 1 < lineCount) + { + const auto& nextLineInfo = m_drawer.GetLine(cursorPosition.y + 1); + cursorPosition.x = std::min(cursorPosition.x, static_cast(nextLineInfo.glyphIndex - lineInfo.glyphIndex - 1)); + } + + SetCursorPosition(lineInfo.glyphIndex + cursorPosition.x); //= m_drawer.GetGlyphCount()) + if (m_cursorGlyph >= m_drawer.GetGlyphCount()) { AppendText(text); SetCursorPosition(m_drawer.GetGlyphCount()); @@ -89,10 +90,10 @@ namespace Ndk else { Nz::String currentText = m_drawer.GetText(); - currentText.Insert(currentText.GetCharacterPosition(m_cursorPosition), text); + currentText.Insert(currentText.GetCharacterPosition(m_cursorGlyph), text); SetText(currentText); - SetCursorPosition(m_cursorPosition + text.GetLength()); + SetCursorPosition(m_cursorGlyph + text.GetLength()); } } @@ -114,11 +115,11 @@ namespace Ndk const Nz::String& text = m_drawer.GetText(); Nz::String newText; - if (m_cursorPosition > 0) - newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorPosition) - 1)); + if (m_cursorGlyph > 0) + newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorGlyph) - 1)); - if (m_cursorPosition < m_drawer.GetGlyphCount()) - newText.Append(text.SubString(text.GetCharacterPosition(m_cursorPosition + 1))); + if (m_cursorGlyph < m_drawer.GetGlyphCount()) + newText.Append(text.SubString(text.GetCharacterPosition(m_cursorGlyph + 1))); m_drawer.SetText(newText); m_textSprite->Update(m_drawer); @@ -133,7 +134,7 @@ namespace Ndk if (ignoreDefaultAction) break; - //TODO + MoveCursor({0, 1}); break; } @@ -145,7 +146,7 @@ namespace Ndk if (ignoreDefaultAction) break; - MoveCursor(-1); + MoveCursor({-1, 0}); break; } @@ -157,7 +158,7 @@ namespace Ndk if (ignoreDefaultAction) break; - MoveCursor(1); + MoveCursor({1, 0}); break; } @@ -169,7 +170,7 @@ namespace Ndk if (ignoreDefaultAction) break; - //TODO + MoveCursor({0, -1}); break; } } @@ -221,13 +222,13 @@ namespace Ndk const Nz::String& text = m_drawer.GetText(); Nz::String newText; - if (m_cursorPosition > 1) - newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorPosition - 1) - 1)); + if (m_cursorGlyph > 1) + newText.Append(text.SubString(0, text.GetCharacterPosition(m_cursorGlyph - 1) - 1)); - if (m_cursorPosition < m_drawer.GetGlyphCount()) - newText.Append(text.SubString(text.GetCharacterPosition(m_cursorPosition))); + if (m_cursorGlyph < m_drawer.GetGlyphCount()) + newText.Append(text.SubString(text.GetCharacterPosition(m_cursorGlyph))); - MoveCursor(-1); + MoveCursor({-1, 0}); SetText(newText); break; } @@ -258,25 +259,15 @@ namespace Ndk void TextAreaWidget::RefreshCursor() { - std::size_t lineCount = m_drawer.GetLineCount(); - std::size_t line = 0U; - for (std::size_t i = line + 1; i < lineCount; ++i) - { - if (m_drawer.GetLine(i).glyphIndex > m_cursorPosition) - break; - - line = i; - } - - const auto& lineInfo = m_drawer.GetLine(line); + const auto& lineInfo = m_drawer.GetLine(m_cursorPosition.y); std::size_t glyphCount = m_drawer.GetGlyphCount(); float position; - if (glyphCount > 0 && lineInfo.glyphIndex < m_cursorPosition) + if (glyphCount > 0 && lineInfo.glyphIndex < m_cursorGlyph) { - const auto& glyph = m_drawer.GetGlyph(std::min(m_cursorPosition, glyphCount - 1)); + const auto& glyph = m_drawer.GetGlyph(std::min(m_cursorGlyph, glyphCount - 1)); position = glyph.bounds.x; - if (m_cursorPosition >= glyphCount) + if (m_cursorGlyph >= glyphCount) position += glyph.bounds.width; } else