Add line wrapping

This commit is contained in:
Lynix 2019-07-05 23:12:12 +02:00
parent b41637c990
commit 0ec1480024
7 changed files with 79 additions and 13 deletions

View File

@ -190,6 +190,7 @@ Nazara Engine:
- ⚠ SimpleTextDrawer no longer supports faux bold rendering
- Added PhysWorld2D::[RaycastQuery, RegionQuery] overloads taking a callback
- Added x and y mouse position to MouseWheelEvent
- Added SimpleTextDrawer::[Get|Set]MaxLineWidth (which does line wrap)
Nazara Development Kit:
- Added ImageWidget (#139)
@ -275,6 +276,7 @@ Nazara Development Kit:
- BaseWidget now has a rendering rect property (allowing to tell a widget what part of it will be rendered)
- Added ScrollAreaWidget
- Console has been remade with widgets (allowing to scroll back history, select text, etc.)
- Added TextAreaWidget line wrap option
# 0.4:

View File

@ -32,7 +32,7 @@ namespace Ndk
//virtual TextAreaWidget* Clone() const = 0;
void EnableLineWrap(bool enable = true);
inline void EnableMultiline(bool enable = true);
inline void EnableTabWriting(bool enable = true);
@ -57,6 +57,7 @@ namespace Ndk
inline bool HasSelection() const;
inline bool IsLineWrapEnabled() const;
inline bool IsMultilineEnabled() const;
inline bool IsReadOnly() const;
inline bool IsTabWritingEnabled() const;
@ -122,6 +123,7 @@ namespace Ndk
Nz::Vector2ui m_cursorPositionEnd;
Nz::Vector2ui m_selectionCursor;
std::vector<Nz::SpriteRef> m_cursorSprites;
bool m_isLineWrapEnabled;
bool m_isMouseButtonDown;
bool m_multiLineEnabled;
bool m_readOnly;

View File

@ -123,6 +123,11 @@ namespace Ndk
return m_cursorPositionBegin != m_cursorPositionEnd;
}
inline bool TextAreaWidget::IsLineWrapEnabled() const
{
return m_isLineWrapEnabled;
}
inline bool TextAreaWidget::IsMultilineEnabled() const
{
return m_multiLineEnabled;

View File

@ -45,6 +45,7 @@ namespace Ndk
// History
m_history = Add<TextAreaWidget>();
m_history->EnableBackground(true);
m_history->EnableLineWrap(true);
m_history->SetReadOnly(true);
m_history->SetBackgroundColor(Nz::Color(80, 80, 160, 128));

View File

@ -16,6 +16,7 @@ namespace Ndk
m_echoMode(EchoMode_Normal),
m_cursorPositionBegin(0U, 0U),
m_cursorPositionEnd(0U, 0U),
m_isLineWrapEnabled(false),
m_isMouseButtonDown(false),
m_multiLineEnabled(false),
m_readOnly(false),
@ -74,12 +75,26 @@ namespace Ndk
}
}
m_textSprite->Update(m_drawer);
SetPreferredSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
UpdateTextSprite();
OnTextChanged(this, m_text);
}
void TextAreaWidget::EnableLineWrap(bool enable)
{
if (m_isLineWrapEnabled != enable)
{
m_isLineWrapEnabled = enable;
if (enable)
m_drawer.SetMaxLineWidth(GetWidth());
else
m_drawer.SetMaxLineWidth(std::numeric_limits<float>::infinity());
UpdateTextSprite();
}
}
void TextAreaWidget::Erase(std::size_t firstGlyph, std::size_t lastGlyph)
{
if (firstGlyph > lastGlyph)
@ -188,6 +203,12 @@ namespace Ndk
{
BaseWidget::Layout();
if (m_isLineWrapEnabled)
{
m_drawer.SetMaxLineWidth(GetWidth());
UpdateTextSprite();
}
RefreshCursor();
}
@ -607,9 +628,14 @@ namespace Ndk
break;
}
m_textSprite->Update(m_drawer);
SetPreferredSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
UpdateTextSprite();
SetCursorPosition(m_cursorPositionBegin); //< Refresh cursor position (prevent it from being outside of the text)
}
void TextAreaWidget::UpdateTextSprite()
{
m_textSprite->Update(m_drawer);
SetPreferredSize(Nz::Vector2f(m_textSprite->GetBoundingVolume().obb.localBox.GetLengths()));
}
}

View File

@ -38,6 +38,7 @@ namespace Nz
std::size_t GetGlyphCount() const override;
const Line& GetLine(std::size_t index) const override;
std::size_t GetLineCount() const override;
float GetMaxLineWidth() const;
const Color& GetOutlineColor() const;
float GetOutlineThickness() const;
TextStyleFlags GetStyle() const;
@ -46,6 +47,7 @@ namespace Nz
void SetCharacterSize(unsigned int characterSize);
void SetColor(const Color& color);
void SetFont(Font* font);
void SetMaxLineWidth(float lineWidth);
void SetOutlineColor(const Color& color);
void SetOutlineThickness(float thickness);
void SetStyle(TextStyleFlags style);
@ -88,6 +90,7 @@ namespace Nz
mutable Vector2ui m_drawPos;
mutable bool m_colorUpdated;
mutable bool m_glyphUpdated;
float m_maxLineWidth;
float m_outlineThickness;
unsigned int m_characterSize;
};

View File

@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Utility/SimpleTextDrawer.hpp>
#include <limits>
#include <memory>
#include <Nazara/Utility/Debug.hpp>
@ -14,6 +15,7 @@ namespace Nz
m_style(TextStyle_Regular),
m_colorUpdated(true),
m_glyphUpdated(true),
m_maxLineWidth(std::numeric_limits<float>::infinity()),
m_outlineThickness(0.f),
m_characterSize(24)
{
@ -27,6 +29,7 @@ namespace Nz
m_colorUpdated(false),
m_glyphUpdated(false),
m_outlineColor(drawer.m_outlineColor),
m_maxLineWidth(drawer.m_maxLineWidth),
m_outlineThickness(drawer.m_outlineThickness),
m_characterSize(drawer.m_characterSize)
{
@ -124,6 +127,11 @@ namespace Nz
return m_lines.size();
}
float SimpleTextDrawer::GetMaxLineWidth() const
{
return m_maxLineWidth;
}
const Color& SimpleTextDrawer::GetOutlineColor() const
{
return m_outlineColor;
@ -173,6 +181,15 @@ namespace Nz
}
}
void SimpleTextDrawer::SetMaxLineWidth(float lineWidth)
{
NazaraAssert(m_maxLineWidth > 0.f, "Max line width must be positive");
m_maxLineWidth = lineWidth;
m_glyphUpdated = false;
}
void SimpleTextDrawer::SetOutlineColor(const Color& color)
{
m_outlineColor = color;
@ -230,6 +247,7 @@ namespace Nz
m_glyphs = std::move(drawer.m_glyphs);
m_glyphUpdated = std::move(drawer.m_glyphUpdated);
m_font = std::move(drawer.m_font);
m_maxLineWidth = drawer.m_maxLineWidth;
m_outlineColor = std::move(drawer.m_outlineColor);
m_outlineThickness = std::move(drawer.m_outlineThickness);
m_style = std::move(drawer.m_style);
@ -365,7 +383,18 @@ namespace Nz
break;
}
auto GenerateGlyph = [this](Glyph& glyph, char32_t character, float outlineThickness, Nz::Color color, int renderOrder, int* advance)
auto AppendNewLine = [&]()
{
// Reset cursor
//advance = 0;
m_drawPos.x = 0;
m_drawPos.y += sizeInfo.lineHeight;
m_workingBounds.ExtendTo(m_lines.back().bounds);
m_lines.emplace_back(Line{ Rectf(0.f, float(sizeInfo.lineHeight * m_lines.size()), 0.f, float(sizeInfo.lineHeight)), m_glyphs.size() + 1 });
};
auto GenerateGlyph = [&](Glyph& glyph, char32_t character, float outlineThickness, Nz::Color color, int renderOrder, int* advance)
{
const Font::Glyph& fontGlyph = m_font->GetGlyph(m_characterSize, m_style, outlineThickness, character);
if (fontGlyph.valid && fontGlyph.fauxOutlineThickness <= 0.f)
@ -377,6 +406,10 @@ namespace Nz
glyph.renderOrder = renderOrder;
glyph.bounds.Set(fontGlyph.aabb);
if (m_lines.back().glyphIndex <= m_glyphs.size() && m_lines.back().bounds.GetMaximum().x + glyph.bounds.width > m_maxLineWidth)
AppendNewLine();
glyph.bounds.x += m_drawPos.x;
glyph.bounds.y += m_drawPos.y;
@ -435,13 +468,7 @@ namespace Nz
{
case '\n':
{
// Reset cursor
advance = 0;
m_drawPos.x = 0;
m_drawPos.y += sizeInfo.lineHeight;
m_workingBounds.ExtendTo(m_lines.back().bounds);
m_lines.emplace_back(Line{Rectf(0.f, float(sizeInfo.lineHeight * m_lines.size()), 0.f, float(sizeInfo.lineHeight)), m_glyphs.size() + 1});
AppendNewLine();
break;
}