Widgets/TextAreaWidgets: Keep selections active (and visible) when losing focus

This commit is contained in:
SirLynix 2023-08-23 17:56:36 +02:00
parent 8f0890f719
commit 98c0a47dcc
3 changed files with 61 additions and 21 deletions

View File

@ -86,11 +86,13 @@ namespace Nz
NazaraSignal(OnTextAreaSelection, const AbstractTextAreaWidget* /*textArea*/, Vector2ui* /*start*/, Vector2ui* /*end*/);
protected:
virtual AbstractTextDrawer& GetTextDrawer() = 0;
virtual const AbstractTextDrawer& GetTextDrawer() const = 0;
Color GetCursorColor() const;
virtual void CopySelectionToClipboard(const Vector2ui& selectionBegin, const Vector2ui& selectionEnd) = 0;
virtual AbstractTextDrawer& GetTextDrawer() = 0;
virtual const AbstractTextDrawer& GetTextDrawer() const = 0;
virtual void HandleIndentation(bool add) = 0;
virtual void HandleSelectionIndentation(bool add) = 0;
virtual void HandleWordCursorMove(bool left) = 0;
@ -113,7 +115,8 @@ namespace Nz
virtual void PasteFromClipboard(const Vector2ui& targetPosition) = 0;
void RefreshCursor();
void RefreshCursorColor();
void RefreshCursorSize();
inline void SetCursorPositionInternal(std::size_t glyphIndex);
inline void SetCursorPositionInternal(Vector2ui cursorPosition);

View File

@ -226,7 +226,8 @@ namespace Nz
m_cursorPositionBegin = NormalizeCursorPosition(fromPosition);
m_cursorPositionEnd = NormalizeCursorPosition(toPosition);
RefreshCursor();
RefreshCursorColor();
RefreshCursorSize();
}
}
@ -250,7 +251,8 @@ namespace Nz
m_cursorPositionBegin = cursorPosition;
m_cursorPositionEnd = m_cursorPositionBegin;
RefreshCursor();
RefreshCursorColor();
RefreshCursorSize();
}
}

View File

@ -59,7 +59,8 @@ namespace Nz
m_cursorPositionBegin = Vector2ui::Zero();
m_cursorPositionEnd = Vector2ui::Zero();
RefreshCursor();
RefreshCursorColor();
RefreshCursorSize();
}
void AbstractTextAreaWidget::EnableLineWrap(bool enable)
@ -120,6 +121,16 @@ namespace Nz
return Vector2ui::Zero();
}
Color AbstractTextAreaWidget::GetCursorColor() const
{
if (m_cursorPositionBegin == m_cursorPositionEnd)
return Color::Black();
else if (HasFocus())
return Color(0.f, 0.f, 0.f, 0.2f);
else
return Color(0.5f, 0.5f, 0.5f, 0.2f);
}
bool AbstractTextAreaWidget::IsFocusable() const
{
return !m_readOnly;
@ -137,26 +148,17 @@ namespace Nz
}
UpdateTextSprite();
RefreshCursor();
RefreshCursorSize();
}
void AbstractTextAreaWidget::OnFocusLost()
{
// Hide cursors
auto& registry = GetRegistry();
for (auto& cursor : m_cursors)
registry.get<GraphicsComponent>(cursor.entity).Hide();
RefreshCursorColor();
}
void AbstractTextAreaWidget::OnFocusReceived()
{
if (!m_readOnly)
{
// Show cursors
auto& registry = GetRegistry();
for (auto& cursor : m_cursors)
registry.get<GraphicsComponent>(cursor.entity).Show();
}
RefreshCursorColor();
}
bool AbstractTextAreaWidget::OnKeyPressed(const WindowEvent::KeyEvent& key)
@ -508,7 +510,40 @@ namespace Nz
return true;
}
void AbstractTextAreaWidget::RefreshCursor()
void AbstractTextAreaWidget::RefreshCursorColor()
{
Color cursorColor = GetCursorColor();
if (m_cursorPositionBegin == m_cursorPositionEnd)
{
auto& registry = GetRegistry();
// Show or hide cursor depending on state
if (HasFocus())
{
if (!m_readOnly)
{
for (auto& cursor : m_cursors)
{
cursor.sprite->SetColor(cursorColor);
registry.get<GraphicsComponent>(cursor.entity).Show();
}
}
}
else
{
for (auto& cursor : m_cursors)
registry.get<GraphicsComponent>(cursor.entity).Hide();
}
}
else
{
for (auto& cursor : m_cursors)
cursor.sprite->SetColor(cursorColor);
}
}
void AbstractTextAreaWidget::RefreshCursorSize()
{
if (m_readOnly)
return;
@ -563,6 +598,7 @@ namespace Nz
std::size_t oldSpriteCount = m_cursors.size();
if (m_cursors.size() < selectionLineCount)
{
Color cursorColor = GetCursorColor();
Recti scissorBox = GetScissorBox();
bool isVisible = IsVisible() && HasFocus();
@ -570,6 +606,7 @@ namespace Nz
for (std::size_t i = oldSpriteCount; i < m_cursors.size(); ++i)
{
m_cursors[i].sprite = std::make_shared<Sprite>(Widgets::Instance()->GetTransparentMaterial());
m_cursors[i].sprite->SetColor(cursorColor);
m_cursors[i].sprite->UpdateRenderLayer(GetBaseRenderLayer() + 1);
m_cursors[i].entity = CreateEntity();
@ -618,7 +655,6 @@ namespace Nz
float endX = (i == m_cursorPositionEnd.y) ? GetGlyphPos({ m_cursorPositionEnd.x, i }) : lineInfo.bounds.width;
float spriteSize = std::max(endX - beginX, 1.f);
cursor.sprite->SetColor((m_cursorPositionBegin == m_cursorPositionEnd) ? Color::Black() : Color(0.f, 0.f, 0.f, 0.2f));
cursor.sprite->SetSize(Vector2f(spriteSize, lineInfo.bounds.height));
registry.get<NodeComponent>(cursor.entity).SetPosition(beginX, textHeight - lineInfo.bounds.y - lineInfo.bounds.height);
@ -626,7 +662,6 @@ namespace Nz
else
{
// Full line selection
cursor.sprite->SetColor(Color(0.f, 0.f, 0.f, 0.2f));
cursor.sprite->SetSize(Vector2f(lineInfo.bounds.width, lineInfo.bounds.height));
registry.get<NodeComponent>(cursor.entity).SetPosition(0.f, textHeight - lineInfo.bounds.y - lineInfo.bounds.height);