Widgets/TextAreaWidget: Add a way to limit text length

This commit is contained in:
SirLynix 2024-01-26 16:15:53 +01:00
parent f10671ac2a
commit c931e9a509
7 changed files with 92 additions and 9 deletions

View File

@ -42,6 +42,7 @@ namespace Nz
inline EchoMode GetEchoMode() const;
inline std::size_t GetGlyphIndex() const;
inline std::size_t GetGlyphIndex(const Vector2ui& cursorPosition) const;
inline std::size_t GetMaximumTextLength() const;
Vector2ui GetHoveredGlyph(float x, float y) const;
@ -61,6 +62,7 @@ namespace Nz
inline void SetCursorPosition(std::size_t glyphIndex);
inline void SetCursorPosition(Vector2ui cursorPosition);
inline void SetEchoMode(EchoMode echoMode);
virtual void SetMaximumTextLength(std::size_t maximumLength) = 0;
inline void SetReadOnly(bool readOnly = true);
inline void SetSelection(Vector2ui fromPosition, Vector2ui toPosition);
@ -131,6 +133,7 @@ namespace Nz
};
std::shared_ptr<TextSprite> m_textSprite;
std::size_t m_maximumTextLength;
std::vector<Cursor> m_cursors;
CharacterFilter m_characterFilter;
EchoMode m_echoMode;

View File

@ -87,6 +87,11 @@ namespace Nz
return glyphIndex;
}
inline std::size_t AbstractTextAreaWidget::GetMaximumTextLength() const
{
return m_maximumTextLength;
}
inline bool AbstractTextAreaWidget::HasSelection() const
{
return m_cursorPositionBegin != m_cursorPositionEnd;
@ -257,3 +262,4 @@ namespace Nz
}
#include <Nazara/Widgets/DebugOff.hpp>
#include "AbstractTextAreaWidget.hpp"

View File

@ -38,6 +38,7 @@ namespace Nz
inline void SetCharacterSize(unsigned int characterSize);
inline void SetCharacterSpacingOffset(float offset);
inline void SetLineSpacingOffset(float offset);
void SetMaximumTextLength(std::size_t maximumLength) override;
inline void SetTextColor(const Color& color);
inline void SetTextFont(std::shared_ptr<Font> font);
inline void SetTextOutlineColor(const Color& color);

View File

@ -41,6 +41,7 @@ namespace Nz
inline void SetCharacterSize(unsigned int characterSize);
inline void SetCharacterSpacingOffset(float offset);
inline void SetLineSpacingOffset(float offset);
void SetMaximumTextLength(std::size_t maximumLength) override;
inline void SetText(std::string text);
inline void SetTextColor(const Color& text);
inline void SetTextFont(std::shared_ptr<Font> font);

View File

@ -22,7 +22,7 @@ namespace Nz
AbstractTextAreaWidget::AbstractTextAreaWidget(BaseWidget* parent) :
BaseWidget(parent),
m_characterFilter(),
m_maximumTextLength(0),
m_echoMode(EchoMode::Normal),
m_cursorPositionBegin(0U, 0U),
m_cursorPositionEnd(0U, 0U),
@ -120,6 +120,11 @@ namespace Nz
return Vector2ui::Zero();
}
void AbstractTextAreaWidget::SetMaximumTextLength(std::size_t maximumLength)
{
m_maximumTextLength = maximumLength;
}
Color AbstractTextAreaWidget::GetCursorColor() const
{
if (m_cursorPositionBegin == m_cursorPositionEnd)

View File

@ -132,22 +132,66 @@ namespace Nz
UpdateDisplayText();
}
void RichTextAreaWidget::SetMaximumTextLength(std::size_t maximumLength)
{
AbstractTextAreaWidget::SetMaximumTextLength(maximumLength);
if (m_maximumTextLength > 0 && m_drawer.HasBlocks())
{
std::size_t blockIndex = m_drawer.FindBlock(m_maximumTextLength);
auto blockRef = m_drawer.GetBlock(blockIndex);
const std::string& blockText = blockRef.GetText();
assert(m_maximumTextLength >= blockRef.GetFirstGlyphIndex());
std::size_t maxBlockSize = m_maximumTextLength - blockRef.GetFirstGlyphIndex();
std::size_t textLength = ComputeCharacterCount(blockText);
if (textLength > maxBlockSize)
{
blockRef.SetText(std::string(TrimRightCount(blockText, textLength - maxBlockSize, Nz::UnicodeAware{})));
// And then remove all blocks after the limit (in reverse order because of index shifting)
std::size_t lastBlockIndex = m_drawer.GetBlockCount();
assert(lastBlockIndex > 0);
for (std::size_t i = lastBlockIndex - 1; i > blockIndex; --i)
m_drawer.RemoveBlock(i);
UpdateDisplayText();
}
}
}
void RichTextAreaWidget::Write(std::string_view text, std::size_t glyphPosition)
{
if (m_drawer.HasBlocks())
{
auto block = m_drawer.GetBlock(m_drawer.FindBlock((glyphPosition > 0) ? glyphPosition - 1 : glyphPosition));
std::size_t firstGlyph = block.GetFirstGlyphIndex();
if (m_maximumTextLength > 0)
{
auto lastBlockRef = m_drawer.GetBlock(m_drawer.GetBlockCount() - 1);
std::size_t currentLength = lastBlockRef.GetFirstGlyphIndex() + ComputeCharacterCount(lastBlockRef.GetText());
if (m_maximumTextLength <= currentLength)
return;
text = Substring(text, 0, m_maximumTextLength - currentLength, UnicodeAware{});
}
auto blockRef = m_drawer.GetBlock(m_drawer.FindBlock((glyphPosition > 0) ? glyphPosition - 1 : glyphPosition));
std::size_t firstGlyph = blockRef.GetFirstGlyphIndex();
assert(glyphPosition >= firstGlyph);
std::string blockText = block.GetText();
std::string blockText = blockRef.GetText();
std::size_t characterPosition = GetCharacterPosition(blockText, glyphPosition - firstGlyph);
blockText.insert(characterPosition, text);
block.SetText(blockText);
blockRef.SetText(blockText);
}
else
{
if (m_maximumTextLength > 0)
text = Substring(text, 0, m_maximumTextLength, UnicodeAware{});
m_drawer.AppendText(text);
}
SetCursorPosition(glyphPosition + ComputeCharacterCount(text));

View File

@ -41,6 +41,15 @@ namespace Nz
void TextAreaWidget::AppendText(std::string_view text)
{
if (m_maximumTextLength > 0)
{
std::size_t currentLength = ComputeCharacterCount(m_text);
if (m_maximumTextLength <= currentLength)
return;
text = Substring(text, 0, m_maximumTextLength - currentLength, UnicodeAware{});
}
m_text += text;
switch (m_echoMode)
@ -113,6 +122,14 @@ namespace Nz
SetText(newText);
}
void TextAreaWidget::SetMaximumTextLength(std::size_t maximumLength)
{
AbstractTextAreaWidget::SetMaximumTextLength(maximumLength);
if (m_maximumTextLength > 0 && ComputeCharacterCount(m_text) > m_maximumTextLength)
SetText(std::string(Substring(m_text, 0, m_maximumTextLength, UnicodeAware{})));
}
void TextAreaWidget::Write(std::string_view text, std::size_t glyphPosition)
{
if (glyphPosition >= m_drawer.GetGlyphCount())
@ -123,6 +140,15 @@ namespace Nz
}
else
{
if (m_maximumTextLength > 0)
{
std::size_t currentLength = ComputeCharacterCount(m_text);
if (m_maximumTextLength <= currentLength)
return;
text = Substring(text, 0, m_maximumTextLength - currentLength, UnicodeAware{});
}
m_text.insert(GetCharacterPosition(m_text, glyphPosition), text);
SetText(m_text);
@ -284,10 +310,7 @@ namespace Nz
if (clipboardString.empty())
return;
m_text.insert(targetIndex, clipboardString);
UpdateDisplayText();
SetCursorPosition(targetIndex + ComputeCharacterCount(clipboardString));
Write(clipboardString, targetIndex);
}
void TextAreaWidget::UpdateDisplayText()