Sdk/TextAreaWidget: Refactor cursor position

In order to have only one cursor instead of two
This commit is contained in:
Lynix 2017-11-11 18:18:44 +01:00
parent 79338c7177
commit 2b88d81294
3 changed files with 47 additions and 38 deletions

View File

@ -34,7 +34,7 @@ namespace Ndk
inline const Nz::Vector2ui& GetCursorPosition() const; inline const Nz::Vector2ui& GetCursorPosition() const;
inline const Nz::String& GetDisplayText() const; inline const Nz::String& GetDisplayText() const;
inline EchoMode GetEchoMode() const; inline EchoMode GetEchoMode() const;
inline std::size_t GetGlyphUnderCursor() const; inline std::size_t GetGlyphIndex(const Nz::Vector2ui& cursorPosition);
inline const Nz::String& GetText() const; inline const Nz::String& GetText() const;
inline const Nz::Color& GetTextColor() const; inline const Nz::Color& GetTextColor() const;
@ -92,7 +92,6 @@ namespace Ndk
Nz::String m_text; Nz::String m_text;
Nz::TextSpriteRef m_textSprite; Nz::TextSpriteRef m_textSprite;
Nz::Vector2ui m_cursorPosition; Nz::Vector2ui m_cursorPosition;
std::size_t m_cursorGlyph;
bool m_multiLineEnabled; bool m_multiLineEnabled;
bool m_readOnly; bool m_readOnly;
}; };

View File

@ -30,21 +30,27 @@ namespace Ndk
return m_cursorPosition; return m_cursorPosition;
} }
inline const Nz::String & TextAreaWidget::GetDisplayText() const inline const Nz::String& TextAreaWidget::GetDisplayText() const
{ {
return m_drawer.GetText(); return m_drawer.GetText();
} }
inline std::size_t TextAreaWidget::GetGlyphIndex(const Nz::Vector2ui& cursorPosition)
{
std::size_t glyphIndex = m_drawer.GetLine(cursorPosition.y).glyphIndex + cursorPosition.x;
if (m_drawer.GetLineCount() > cursorPosition.y + 1)
glyphIndex = std::min(glyphIndex, m_drawer.GetLine(cursorPosition.y + 1).glyphIndex - 1);
else
glyphIndex = std::min(glyphIndex, m_drawer.GetGlyphCount());
return glyphIndex;
}
inline EchoMode TextAreaWidget::GetEchoMode() const inline EchoMode TextAreaWidget::GetEchoMode() const
{ {
return m_echoMode; return m_echoMode;
} }
inline std::size_t Ndk::TextAreaWidget::GetGlyphUnderCursor() const
{
return m_cursorGlyph;
}
inline const Nz::String& TextAreaWidget::GetText() const inline const Nz::String& TextAreaWidget::GetText() const
{ {
return m_text; return m_text;
@ -67,21 +73,22 @@ namespace Ndk
inline void TextAreaWidget::MoveCursor(int offset) inline void TextAreaWidget::MoveCursor(int offset)
{ {
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition);
if (offset >= 0) if (offset >= 0)
SetCursorPosition(m_cursorGlyph + static_cast<std::size_t>(offset)); SetCursorPosition(cursorGlyph + static_cast<std::size_t>(offset));
else else
{ {
std::size_t nOffset = static_cast<std::size_t>(-offset); std::size_t nOffset = static_cast<std::size_t>(-offset);
if (nOffset >= m_cursorGlyph) if (nOffset >= cursorGlyph)
SetCursorPosition(0); SetCursorPosition(0);
else else
SetCursorPosition(m_cursorGlyph - nOffset); SetCursorPosition(cursorGlyph - nOffset);
} }
} }
inline void TextAreaWidget::MoveCursor(const Nz::Vector2i& offset) inline void TextAreaWidget::MoveCursor(const Nz::Vector2i& offset)
{ {
auto BoundOffset = [] (unsigned int cursorPosition, int cursorOffset) -> unsigned int auto ClampOffset = [] (unsigned int cursorPosition, int cursorOffset) -> unsigned int
{ {
if (cursorOffset >= 0) if (cursorOffset >= 0)
return cursorPosition + cursorOffset; return cursorPosition + cursorOffset;
@ -96,8 +103,8 @@ namespace Ndk
}; };
Nz::Vector2ui cursorPosition = m_cursorPosition; Nz::Vector2ui cursorPosition = m_cursorPosition;
cursorPosition.x = BoundOffset(static_cast<unsigned int>(cursorPosition.x), offset.x); cursorPosition.x = ClampOffset(static_cast<unsigned int>(cursorPosition.x), offset.x);
cursorPosition.y = BoundOffset(static_cast<unsigned int>(cursorPosition.y), offset.y); cursorPosition.y = ClampOffset(static_cast<unsigned int>(cursorPosition.y), offset.y);
SetCursorPosition(cursorPosition); SetCursorPosition(cursorPosition);
} }
@ -111,13 +118,13 @@ namespace Ndk
{ {
OnTextAreaCursorMove(this, &glyphIndex); OnTextAreaCursorMove(this, &glyphIndex);
m_cursorGlyph = std::min(glyphIndex, m_drawer.GetGlyphCount()); glyphIndex = std::min(glyphIndex, m_drawer.GetGlyphCount());
std::size_t lineCount = m_drawer.GetLineCount(); std::size_t lineCount = m_drawer.GetLineCount();
std::size_t line = 0U; std::size_t line = 0U;
for (std::size_t i = line + 1; i < lineCount; ++i) for (std::size_t i = line + 1; i < lineCount; ++i)
{ {
if (m_drawer.GetLine(i).glyphIndex > m_cursorGlyph) if (m_drawer.GetLine(i).glyphIndex > glyphIndex)
break; break;
line = i; line = i;
@ -126,7 +133,7 @@ namespace Ndk
const auto& lineInfo = m_drawer.GetLine(line); const auto& lineInfo = m_drawer.GetLine(line);
m_cursorPosition.y = static_cast<unsigned int>(line); m_cursorPosition.y = static_cast<unsigned int>(line);
m_cursorPosition.x = static_cast<unsigned int>(m_cursorGlyph - lineInfo.glyphIndex); m_cursorPosition.x = static_cast<unsigned int>(glyphIndex - lineInfo.glyphIndex);
RefreshCursor(); RefreshCursor();
} }
@ -150,8 +157,6 @@ namespace Ndk
OnTextAreaCursorMove(this, &glyphIndex); OnTextAreaCursorMove(this, &glyphIndex);
m_cursorGlyph = std::min(glyphIndex, m_drawer.GetGlyphCount());
RefreshCursor(); RefreshCursor();
} }

View File

@ -13,7 +13,6 @@ namespace Ndk
BaseWidget(parent), BaseWidget(parent),
m_echoMode(EchoMode_Normal), m_echoMode(EchoMode_Normal),
m_cursorPosition(0U, 0U), m_cursorPosition(0U, 0U),
m_cursorGlyph(0),
m_multiLineEnabled(false), m_multiLineEnabled(false),
m_readOnly(false) m_readOnly(false)
{ {
@ -110,17 +109,19 @@ namespace Ndk
void TextAreaWidget::Write(const Nz::String& text) void TextAreaWidget::Write(const Nz::String& text)
{ {
if (m_cursorGlyph >= m_drawer.GetGlyphCount()) std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition);
if (cursorGlyph >= m_drawer.GetGlyphCount())
{ {
AppendText(text); AppendText(text);
SetCursorPosition(m_drawer.GetGlyphCount()); SetCursorPosition(m_drawer.GetGlyphCount());
} }
else else
{ {
m_text.Insert(m_text.GetCharacterPosition(m_cursorGlyph), text); m_text.Insert(m_text.GetCharacterPosition(cursorGlyph), text);
SetText(m_text); SetText(m_text);
SetCursorPosition(m_cursorGlyph + text.GetLength()); SetCursorPosition(cursorGlyph + text.GetLength());
} }
} }
@ -139,16 +140,18 @@ namespace Ndk
{ {
case Nz::Keyboard::Delete: case Nz::Keyboard::Delete:
{ {
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition);
std::size_t textLength = m_text.GetLength(); std::size_t textLength = m_text.GetLength();
if (m_cursorGlyph > textLength) if (cursorGlyph > textLength)
break; break;
Nz::String newText; Nz::String newText;
if (m_cursorGlyph > 0) if (cursorGlyph > 0)
newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(m_cursorGlyph) - 1)); newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(cursorGlyph) - 1));
if (m_cursorGlyph < textLength) if (cursorGlyph < textLength)
newText.Append(m_text.SubString(m_text.GetCharacterPosition(m_cursorGlyph + 1))); newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyph + 1)));
SetText(newText); SetText(newText);
break; break;
@ -247,18 +250,19 @@ namespace Ndk
bool ignoreDefaultAction = false; bool ignoreDefaultAction = false;
OnTextAreaKeyBackspace(this, &ignoreDefaultAction); OnTextAreaKeyBackspace(this, &ignoreDefaultAction);
if (ignoreDefaultAction || m_cursorGlyph == 0) std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition);
if (ignoreDefaultAction || cursorGlyph == 0)
break; break;
Nz::String newText; Nz::String newText;
if (m_cursorGlyph > 1) if (cursorGlyph > 1)
newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(m_cursorGlyph - 1) - 1)); newText.Append(m_text.SubString(0, m_text.GetCharacterPosition(cursorGlyph - 1) - 1));
if (m_cursorGlyph < m_text.GetLength()) if (cursorGlyph < m_text.GetLength())
newText.Append(m_text.SubString(m_text.GetCharacterPosition(m_cursorGlyph))); newText.Append(m_text.SubString(m_text.GetCharacterPosition(cursorGlyph)));
MoveCursor({-1, 0}); MoveCursor(-1);
SetText(newText); SetText(newText);
break; break;
} }
@ -290,14 +294,15 @@ namespace Ndk
void TextAreaWidget::RefreshCursor() void TextAreaWidget::RefreshCursor()
{ {
const auto& lineInfo = m_drawer.GetLine(m_cursorPosition.y); const auto& lineInfo = m_drawer.GetLine(m_cursorPosition.y);
std::size_t cursorGlyph = GetGlyphIndex(m_cursorPosition);
std::size_t glyphCount = m_drawer.GetGlyphCount(); std::size_t glyphCount = m_drawer.GetGlyphCount();
float position; float position;
if (glyphCount > 0 && lineInfo.glyphIndex < m_cursorGlyph) if (glyphCount > 0 && lineInfo.glyphIndex < cursorGlyph)
{ {
const auto& glyph = m_drawer.GetGlyph(std::min(m_cursorGlyph, glyphCount - 1)); const auto& glyph = m_drawer.GetGlyph(std::min(cursorGlyph, glyphCount - 1));
position = glyph.bounds.x; position = glyph.bounds.x;
if (m_cursorGlyph >= glyphCount) if (cursorGlyph >= glyphCount)
position += glyph.bounds.width; position += glyph.bounds.width;
} }
else else