diff --git a/samples/Sandbox/Sandbox.csproj b/samples/Sandbox/Sandbox.csproj index 20c7f29201..eab654acb6 100644 --- a/samples/Sandbox/Sandbox.csproj +++ b/samples/Sandbox/Sandbox.csproj @@ -10,7 +10,6 @@ - diff --git a/src/Avalonia.Controls/RichTextBlock.cs b/src/Avalonia.Controls/RichTextBlock.cs index 6a40144137..3011cc7bd9 100644 --- a/src/Avalonia.Controls/RichTextBlock.cs +++ b/src/Avalonia.Controls/RichTextBlock.cs @@ -338,6 +338,8 @@ namespace Avalonia.Controls e.Handled = handled; } + private bool _hasWordSelection; + protected override void OnPointerPressed(PointerPressedEventArgs e) { base.OnPointerPressed(e); @@ -363,8 +365,6 @@ namespace Avalonia.Controls var hit = TextLayout.HitTestPoint(point); var index = hit.TextPosition; - SelectionStart = SelectionEnd = index; - #pragma warning disable CS0618 // Type or member is obsolete switch (e.ClickCount) #pragma warning restore CS0618 // Type or member is obsolete @@ -372,16 +372,27 @@ namespace Avalonia.Controls case 1: if (clickToSelect) { - SelectionStart = Math.Min(oldIndex, index); - SelectionEnd = Math.Max(oldIndex, index); + if (_hasWordSelection) + { + SelectionEnd = StringUtils.NextWord(text, index); + } + else + { + SelectionStart = Math.Min(oldIndex, index); + SelectionEnd = Math.Max(oldIndex, index); + } } else { + _hasWordSelection = false; + SelectionStart = SelectionEnd = index; } break; case 2: + _hasWordSelection = true; + if (!StringUtils.IsStartOfWord(text, index)) { SelectionStart = StringUtils.PreviousWord(text, index); @@ -390,6 +401,8 @@ namespace Avalonia.Controls SelectionEnd = StringUtils.NextWord(text, index); break; case 3: + _hasWordSelection = false; + SelectAll(); break; } @@ -411,6 +424,7 @@ namespace Avalonia.Controls // selection should not change during pointer move if the user right clicks if (e.Pointer.Captured == this && e.GetCurrentPoint(this).Properties.IsLeftButtonPressed) { + var text = Text; var padding = Padding; var point = e.GetPosition(this) - new Point(padding.Left, padding.Top); @@ -421,7 +435,16 @@ namespace Avalonia.Controls var hit = TextLayout.HitTestPoint(point); - SelectionEnd = hit.TextPosition; + if (text != null && _hasWordSelection) + { + SelectionEnd = StringUtils.NextWord(text, hit.TextPosition); + } + else + { + SelectionEnd = hit.TextPosition; + } + + } } diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs index 9531f719b9..0946404f3b 100644 --- a/src/Avalonia.Controls/TextBox.cs +++ b/src/Avalonia.Controls/TextBox.cs @@ -202,6 +202,7 @@ namespace Avalonia.Controls private string _newLine = Environment.NewLine; private static readonly string[] invalidCharacters = new String[1] { "\u007f" }; + private bool _hasWordSelection; private int _selectedTextChangesMadeSinceLastUndoSnapshot; private bool _hasDoneSnapshotOnce; private const int _maxCharsBeforeUndoSnapshot = 7; @@ -1170,16 +1171,27 @@ namespace Avalonia.Controls case 1: if (clickToSelect) { - SelectionStart = Math.Min(oldIndex, index); - SelectionEnd = Math.Max(oldIndex, index); + if (_hasWordSelection) + { + SelectionEnd = StringUtils.NextWord(text, index); + } + else + { + SelectionStart = Math.Min(oldIndex, index); + SelectionEnd = Math.Max(oldIndex, index); + } } else { + _hasWordSelection = false; + SelectionStart = SelectionEnd = index; } break; case 2: + _hasWordSelection = true; + if (!StringUtils.IsStartOfWord(text, index)) { SelectionStart = StringUtils.PreviousWord(text, index); @@ -1188,6 +1200,8 @@ namespace Avalonia.Controls SelectionEnd = StringUtils.NextWord(text, index); break; case 3: + _hasWordSelection = false; + SelectAll(); break; } @@ -1215,7 +1229,16 @@ namespace Avalonia.Controls _presenter.MoveCaretToPoint(point); - SelectionEnd = _presenter.CaretIndex; + var text = Text; + + if (text != null && _hasWordSelection) + { + SelectionEnd = StringUtils.NextWord(text, _presenter.CaretIndex); + } + else + { + SelectionEnd = _presenter.CaretIndex; + } } }