Widgets/TextAreaWidget: Add support for double/triple click selection

This commit is contained in:
Jérôme Leclercq 2021-11-30 12:39:53 +01:00
parent e73489e958
commit 86071eae88
6 changed files with 95 additions and 4 deletions

View File

@ -94,6 +94,7 @@ namespace Nz
virtual void HandleIndentation(bool add) = 0;
virtual void HandleSelectionIndentation(bool add) = 0;
virtual void HandleWordCursorMove(bool left) = 0;
virtual void HandleWordSelection(const Vector2ui& position) = 0;
bool IsFocusable() const override;
void Layout() override;
@ -102,8 +103,10 @@ namespace Nz
void OnFocusReceived() override;
bool OnKeyPressed(const WindowEvent::KeyEvent& key) override;
void OnKeyReleased(const WindowEvent::KeyEvent& key) override;
void OnMouseButtonPress(int /*x*/, int /*y*/, Mouse::Button button) override;
void OnMouseButtonRelease(int /*x*/, int /*y*/, Mouse::Button button) override;
void OnMouseButtonDoublePress(int x, int y, Mouse::Button button) override;
void OnMouseButtonPress(int x, int y, Mouse::Button button) override;
void OnMouseButtonRelease(int x, int y, Mouse::Button button) override;
void OnMouseButtonTriplePress(int x, int y, Mouse::Button button) override;
void OnMouseEnter() override;
void OnMouseMoved(int x, int y, int deltaX, int deltaY) override;
void OnTextEntered(char32_t character, bool repeated) override;

View File

@ -44,7 +44,7 @@ namespace Nz
{
const AbstractTextDrawer& textDrawer = GetTextDrawer();
glyphIndex = std::min(glyphIndex, GetTextDrawer().GetGlyphCount());
glyphIndex = std::min(glyphIndex, textDrawer.GetGlyphCount());
std::size_t lineCount = textDrawer.GetLineCount();
std::size_t line = 0U;

View File

@ -58,6 +58,7 @@ namespace Nz
void HandleIndentation(bool add) override;
void HandleSelectionIndentation(bool add) override;
void HandleWordCursorMove(bool left) override;
void HandleWordSelection(const Vector2ui& position) override;
void PasteFromClipboard(const Vector2ui& targetPosition) override;

View File

@ -397,6 +397,23 @@ namespace Nz
{
}
void AbstractTextAreaWidget::OnMouseButtonDoublePress(int x, int y, Mouse::Button button)
{
if (button == Mouse::Left)
{
// Shift double click is handled as single click
if (Keyboard::IsKeyPressed(Keyboard::VKey::LShift) || Keyboard::IsKeyPressed(Keyboard::VKey::RShift))
return OnMouseButtonPress(x, y, button);
SetFocus();
Vector2ui hoveredGlyph = GetHoveredGlyph(float(x), float(y));
HandleWordSelection(hoveredGlyph);
m_isMouseButtonDown = true;
}
}
void AbstractTextAreaWidget::OnMouseButtonPress(int x, int y, Mouse::Button button)
{
if (button == Mouse::Left)
@ -424,6 +441,23 @@ namespace Nz
m_isMouseButtonDown = false;
}
void AbstractTextAreaWidget::OnMouseButtonTriplePress(int x, int y, Mouse::Button button)
{
if (button == Mouse::Left)
{
// Shift triple click is handled as single click
if (Keyboard::IsKeyPressed(Keyboard::VKey::LShift) || Keyboard::IsKeyPressed(Keyboard::VKey::RShift))
return OnMouseButtonPress(x, y, button);
SetFocus();
Vector2ui hoveredGlyph = GetHoveredGlyph(float(x), float(y));
SetSelection(Vector2ui(0, hoveredGlyph.y), Vector2ui(std::numeric_limits<unsigned int>::max(), hoveredGlyph.y));
m_isMouseButtonDown = true;
}
}
void AbstractTextAreaWidget::OnMouseEnter()
{
if (!Mouse::IsButtonPressed(Mouse::Left))

View File

@ -171,14 +171,22 @@ namespace Nz
void RichTextAreaWidget::HandleIndentation(bool add)
{
// TODO
}
void RichTextAreaWidget::HandleSelectionIndentation(bool add)
{
// TODO
}
void RichTextAreaWidget::HandleWordCursorMove(bool left)
{
// TODO
}
void RichTextAreaWidget::HandleWordSelection(const Vector2ui& position)
{
// TODO
}
void RichTextAreaWidget::PasteFromClipboard(const Vector2ui& targetPosition)

View File

@ -12,6 +12,25 @@
namespace Nz
{
namespace
{
bool IsSpace(char32_t character)
{
switch (character)
{
case '\f':
case '\n':
case '\r':
case '\t':
case '\v':
return true;
default:
return Unicode::GetCategory(character) & Unicode::Category_Separator;
}
}
}
TextAreaWidget::TextAreaWidget(BaseWidget* parent) :
AbstractTextAreaWidget(parent)
{
@ -188,7 +207,7 @@ namespace Nz
if (index == 0)
return;
std::size_t spaceIndex = m_text.rfind(' ', index - 2);
std::size_t spaceIndex = m_text.rfind(' ', index - 1);
std::size_t endlIndex = m_text.rfind('\n', index - 1);
if ((spaceIndex > endlIndex || endlIndex == std::string::npos) && spaceIndex != std::string::npos)
@ -228,6 +247,32 @@ namespace Nz
}
}
void TextAreaWidget::HandleWordSelection(const Vector2ui& position)
{
std::size_t index = GetGlyphIndex(m_cursorPositionEnd);
// FIXME: Handle Unicode properly
std::size_t startIndex = index;
for (std::string::reverse_iterator it { m_text.begin() + index }; it != m_text.rend(); ++it)
{
if (IsSpace(*it))
break;
--startIndex;
}
std::size_t endIndex = index;
for (auto it = m_text.begin() + index; it != m_text.end(); ++it)
{
if (IsSpace(*it))
break;
++endIndex;
}
SetSelection(GetCursorPosition(GetCharacterPosition(m_text, startIndex)), GetCursorPosition(GetCharacterPosition(m_text, endIndex)));
}
void TextAreaWidget::PasteFromClipboard(const Vector2ui& targetPosition)
{
std::size_t glyphCount = ComputeCharacterCount(m_text);