Widgets/TextAreaWidgets: Keep selections active (and visible) when losing focus
This commit is contained in:
parent
8f0890f719
commit
98c0a47dcc
|
|
@ -86,11 +86,13 @@ namespace Nz
|
||||||
NazaraSignal(OnTextAreaSelection, const AbstractTextAreaWidget* /*textArea*/, Vector2ui* /*start*/, Vector2ui* /*end*/);
|
NazaraSignal(OnTextAreaSelection, const AbstractTextAreaWidget* /*textArea*/, Vector2ui* /*start*/, Vector2ui* /*end*/);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual AbstractTextDrawer& GetTextDrawer() = 0;
|
Color GetCursorColor() const;
|
||||||
virtual const AbstractTextDrawer& GetTextDrawer() const = 0;
|
|
||||||
|
|
||||||
virtual void CopySelectionToClipboard(const Vector2ui& selectionBegin, const Vector2ui& selectionEnd) = 0;
|
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 HandleIndentation(bool add) = 0;
|
||||||
virtual void HandleSelectionIndentation(bool add) = 0;
|
virtual void HandleSelectionIndentation(bool add) = 0;
|
||||||
virtual void HandleWordCursorMove(bool left) = 0;
|
virtual void HandleWordCursorMove(bool left) = 0;
|
||||||
|
|
@ -113,7 +115,8 @@ namespace Nz
|
||||||
|
|
||||||
virtual void PasteFromClipboard(const Vector2ui& targetPosition) = 0;
|
virtual void PasteFromClipboard(const Vector2ui& targetPosition) = 0;
|
||||||
|
|
||||||
void RefreshCursor();
|
void RefreshCursorColor();
|
||||||
|
void RefreshCursorSize();
|
||||||
|
|
||||||
inline void SetCursorPositionInternal(std::size_t glyphIndex);
|
inline void SetCursorPositionInternal(std::size_t glyphIndex);
|
||||||
inline void SetCursorPositionInternal(Vector2ui cursorPosition);
|
inline void SetCursorPositionInternal(Vector2ui cursorPosition);
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,8 @@ namespace Nz
|
||||||
m_cursorPositionBegin = NormalizeCursorPosition(fromPosition);
|
m_cursorPositionBegin = NormalizeCursorPosition(fromPosition);
|
||||||
m_cursorPositionEnd = NormalizeCursorPosition(toPosition);
|
m_cursorPositionEnd = NormalizeCursorPosition(toPosition);
|
||||||
|
|
||||||
RefreshCursor();
|
RefreshCursorColor();
|
||||||
|
RefreshCursorSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -250,7 +251,8 @@ namespace Nz
|
||||||
m_cursorPositionBegin = cursorPosition;
|
m_cursorPositionBegin = cursorPosition;
|
||||||
m_cursorPositionEnd = m_cursorPositionBegin;
|
m_cursorPositionEnd = m_cursorPositionBegin;
|
||||||
|
|
||||||
RefreshCursor();
|
RefreshCursorColor();
|
||||||
|
RefreshCursorSize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,8 @@ namespace Nz
|
||||||
m_cursorPositionBegin = Vector2ui::Zero();
|
m_cursorPositionBegin = Vector2ui::Zero();
|
||||||
m_cursorPositionEnd = Vector2ui::Zero();
|
m_cursorPositionEnd = Vector2ui::Zero();
|
||||||
|
|
||||||
RefreshCursor();
|
RefreshCursorColor();
|
||||||
|
RefreshCursorSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractTextAreaWidget::EnableLineWrap(bool enable)
|
void AbstractTextAreaWidget::EnableLineWrap(bool enable)
|
||||||
|
|
@ -120,6 +121,16 @@ namespace Nz
|
||||||
return Vector2ui::Zero();
|
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
|
bool AbstractTextAreaWidget::IsFocusable() const
|
||||||
{
|
{
|
||||||
return !m_readOnly;
|
return !m_readOnly;
|
||||||
|
|
@ -137,26 +148,17 @@ namespace Nz
|
||||||
}
|
}
|
||||||
|
|
||||||
UpdateTextSprite();
|
UpdateTextSprite();
|
||||||
RefreshCursor();
|
RefreshCursorSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractTextAreaWidget::OnFocusLost()
|
void AbstractTextAreaWidget::OnFocusLost()
|
||||||
{
|
{
|
||||||
// Hide cursors
|
RefreshCursorColor();
|
||||||
auto& registry = GetRegistry();
|
|
||||||
for (auto& cursor : m_cursors)
|
|
||||||
registry.get<GraphicsComponent>(cursor.entity).Hide();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AbstractTextAreaWidget::OnFocusReceived()
|
void AbstractTextAreaWidget::OnFocusReceived()
|
||||||
{
|
{
|
||||||
if (!m_readOnly)
|
RefreshCursorColor();
|
||||||
{
|
|
||||||
// Show cursors
|
|
||||||
auto& registry = GetRegistry();
|
|
||||||
for (auto& cursor : m_cursors)
|
|
||||||
registry.get<GraphicsComponent>(cursor.entity).Show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AbstractTextAreaWidget::OnKeyPressed(const WindowEvent::KeyEvent& key)
|
bool AbstractTextAreaWidget::OnKeyPressed(const WindowEvent::KeyEvent& key)
|
||||||
|
|
@ -508,7 +510,40 @@ namespace Nz
|
||||||
return true;
|
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)
|
if (m_readOnly)
|
||||||
return;
|
return;
|
||||||
|
|
@ -563,6 +598,7 @@ namespace Nz
|
||||||
std::size_t oldSpriteCount = m_cursors.size();
|
std::size_t oldSpriteCount = m_cursors.size();
|
||||||
if (m_cursors.size() < selectionLineCount)
|
if (m_cursors.size() < selectionLineCount)
|
||||||
{
|
{
|
||||||
|
Color cursorColor = GetCursorColor();
|
||||||
Recti scissorBox = GetScissorBox();
|
Recti scissorBox = GetScissorBox();
|
||||||
bool isVisible = IsVisible() && HasFocus();
|
bool isVisible = IsVisible() && HasFocus();
|
||||||
|
|
||||||
|
|
@ -570,6 +606,7 @@ namespace Nz
|
||||||
for (std::size_t i = oldSpriteCount; i < m_cursors.size(); ++i)
|
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 = std::make_shared<Sprite>(Widgets::Instance()->GetTransparentMaterial());
|
||||||
|
m_cursors[i].sprite->SetColor(cursorColor);
|
||||||
m_cursors[i].sprite->UpdateRenderLayer(GetBaseRenderLayer() + 1);
|
m_cursors[i].sprite->UpdateRenderLayer(GetBaseRenderLayer() + 1);
|
||||||
|
|
||||||
m_cursors[i].entity = CreateEntity();
|
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 endX = (i == m_cursorPositionEnd.y) ? GetGlyphPos({ m_cursorPositionEnd.x, i }) : lineInfo.bounds.width;
|
||||||
float spriteSize = std::max(endX - beginX, 1.f);
|
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));
|
cursor.sprite->SetSize(Vector2f(spriteSize, lineInfo.bounds.height));
|
||||||
|
|
||||||
registry.get<NodeComponent>(cursor.entity).SetPosition(beginX, textHeight - lineInfo.bounds.y - lineInfo.bounds.height);
|
registry.get<NodeComponent>(cursor.entity).SetPosition(beginX, textHeight - lineInfo.bounds.y - lineInfo.bounds.height);
|
||||||
|
|
@ -626,7 +662,6 @@ namespace Nz
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Full line selection
|
// 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));
|
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);
|
registry.get<NodeComponent>(cursor.entity).SetPosition(0.f, textHeight - lineInfo.bounds.y - lineInfo.bounds.height);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue