Skip to content

Commit a05ca79

Browse files
committed
fix(Wasm): Changing TextBox.Text in code should reset the caret
fix(Wasm): Changing TextBox.Text in code should reset the caret to the begging fix(Wasm): Changing TextBox.Text in code should reset the caret to the begging fix(Wasm): Changing TextBox.Text in code should reset the caret to the begging fix(Wasm): Changing TextBox.Text in code should reset the caret to the beginning fix(Wasm): Changing TextBox.Text in code should reset the caret to the beginning fix(Wasm): Changing TextBox.Text in code should reset the caret to the beginning fix(Wasm): Changing TextBox.Text in code should reset the caret to the begining fix(Wasm): Changing TextBox.Text in code should reset the caret to the beginning refactor: adjusted reset carret refactor: setted just to WASM refactor: resolved PR comments refactor: commit PR recomendation. refactor: Changed for specific code the WASM logic. refactor: adjustes algorithm fix(Wasm): Changing TextBox.Text in code should reset the caret to the beginning refactor: adjusted reset carret refactor: setted just to WASM refactor: resolved PR comments refactor: commit PR recomendation. refactor: Changed for specific code the WASM logic. refactor: resolved the comment on PR. refactor: adjust resetcarret implementation refactor: adjust unit test refactor: adjust unit tests refactor: adjust unit tests. refactor: test adjustment refactor: adjusted unit test. refactor: adjuste android cursor position
1 parent 9f8e75d commit a05ca79

File tree

6 files changed

+91
-50
lines changed

6 files changed

+91
-50
lines changed

src/Uno.UI.Runtime.Skia.Wpf/Extensions/UI/Xaml/Controls/TextBoxViewExtension.cs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,11 @@ public void StartEntry()
3838
_contentElement = textBox.ContentElement;
3939

4040
EnsureWidgetForAcceptsReturn();
41-
textInputLayer.Children.Add(_currentInputWidget!);
41+
42+
if (textInputLayer.Children.Count == 0)
43+
{
44+
textInputLayer.Children.Add(_currentInputWidget!);
45+
}
4246

4347
UpdateNativeView();
4448
SetTextNative(textBox.Text);
@@ -160,7 +164,17 @@ public void SetIsPassword(bool isPassword)
160164
// No support for now.
161165
}
162166

163-
public void Select(int start, int length) => _currentInputWidget?.Select(start, length);
167+
public void Select(int start, int length)
168+
{
169+
_currentInputWidget?.Select(start, length);
170+
171+
if (_currentInputWidget == null)
172+
{
173+
this.StartEntry();
174+
175+
_currentInputWidget!.Select(start, length);
176+
}
177+
}
164178

165179
public int GetSelectionStart() => _currentInputWidget?.SelectionStart ?? 0;
166180

src/Uno.UI.RuntimeTests/Tests/Windows_UI_Xaml_Controls/Given_TextBox.cs

Lines changed: 6 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -134,12 +134,8 @@ public async Task When_Calling_Select_With_In_Range_Values()
134134

135135
WindowHelper.WindowContent = textBox;
136136
await WindowHelper.WaitForLoaded(textBox);
137-
#if __WASM__ // Wasm is behaving differently than UWP and other platforms. https://github.com/unoplatform/uno/issues/7016
138-
Assert.AreEqual(10, textBox.SelectionStart);
139-
#else
140-
Assert.AreEqual(0, textBox.SelectionStart);
141-
#endif
142-
137+
textBox.Focus(FocusState.Programmatic);
138+
Assert.AreEqual(textBox.Text.Length, textBox.SelectionStart);
143139
Assert.AreEqual(0, textBox.SelectionLength);
144140
textBox.Select(1, 7);
145141
Assert.AreEqual(1, textBox.SelectionStart);
@@ -156,12 +152,8 @@ public async Task When_Calling_Select_With_Out_Of_Range_Length()
156152

157153
WindowHelper.WindowContent = textBox;
158154
await WindowHelper.WaitForLoaded(textBox);
159-
160-
#if __WASM__ // Wasm is behaving differently than UWP and other platforms. https://github.com/unoplatform/uno/issues/7016
161-
Assert.AreEqual(10, textBox.SelectionStart);
162-
#else
163-
Assert.AreEqual(0, textBox.SelectionStart);
164-
#endif
155+
textBox.Focus(FocusState.Programmatic);
156+
Assert.AreEqual(textBox.Text.Length, textBox.SelectionStart);
165157
Assert.AreEqual(0, textBox.SelectionLength);
166158
textBox.Select(1, 20);
167159
Assert.AreEqual(1, textBox.SelectionStart);
@@ -178,12 +170,8 @@ public async Task When_Calling_Select_With_Out_Of_Range_Start()
178170

179171
WindowHelper.WindowContent = textBox;
180172
await WindowHelper.WaitForLoaded(textBox);
181-
182-
#if __WASM__ // Wasm is behaving differently than UWP and other platforms. https://github.com/unoplatform/uno/issues/7016
183-
Assert.AreEqual(10, textBox.SelectionStart);
184-
#else
185-
Assert.AreEqual(0, textBox.SelectionStart);
186-
#endif
173+
textBox.Focus(FocusState.Programmatic);
174+
Assert.AreEqual(textBox.Text.Length, textBox.SelectionStart);
187175
Assert.AreEqual(0, textBox.SelectionLength);
188176
textBox.Select(20, 5);
189177
Assert.AreEqual(10, textBox.SelectionStart);

src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.Android.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,15 @@ partial void OnFocusStateChangedPartial(FocusState focusState)
169169
using (focusState == FocusState.Programmatic ? PreventKeyboardDisplayIfSet() : null)
170170
{
171171
_textBoxView.RequestFocus();
172+
173+
var selectionStart = this.SelectionStart;
174+
175+
if (selectionStart == 0)
176+
{
177+
int cursorPosition = selectionStart + _textBoxView?.Text?.Length ?? 0;
178+
179+
this.Select(cursorPosition, 0);
180+
}
172181
}
173182
}
174183
}

src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.cs

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,12 @@ private void RaiseTextChanged()
264264
_isTextChangedPending = false;
265265
}
266266
}
267-
267+
268268
_textBoxView?.SetTextNative(Text);
269+
269270
}
270271

272+
271273
private void UpdatePlaceholderVisibility()
272274
{
273275
if (_placeHolder != null)
@@ -303,9 +305,9 @@ private object CoerceText(object baseValue)
303305
return baseString;
304306
}
305307

306-
#endregion
308+
#endregion
307309

308-
#region Description DependencyProperty
310+
#region Description DependencyProperty
309311

310312
public
311313
#if __IOS__ || __MACOS__
@@ -342,7 +344,7 @@ private void UpdateDescriptionVisibility(bool initialization)
342344
descriptionPresenter.Visibility = Description != null ? Visibility.Visible : Visibility.Collapsed;
343345
}
344346
}
345-
#endregion
347+
#endregion
346348

347349
protected override void OnFontSizeChanged(double oldValue, double newValue)
348350
{
@@ -374,7 +376,7 @@ protected override void OnFontWeightChanged(FontWeight oldValue, FontWeight newV
374376

375377
partial void OnForegroundColorChangedPartial(Brush newValue);
376378

377-
#region PlaceholderText DependencyProperty
379+
#region PlaceholderText DependencyProperty
378380

379381
public string PlaceholderText
380382
{
@@ -390,9 +392,9 @@ public string PlaceholderText
390392
new FrameworkPropertyMetadata(defaultValue: string.Empty)
391393
);
392394

393-
#endregion
395+
#endregion
394396

395-
#region InputScope DependencyProperty
397+
#region InputScope DependencyProperty
396398

397399
public InputScope InputScope
398400
{
@@ -423,9 +425,9 @@ public InputScope InputScope
423425
protected void OnInputScopeChanged(DependencyPropertyChangedEventArgs e) => OnInputScopeChangedPartial(e);
424426
partial void OnInputScopeChangedPartial(DependencyPropertyChangedEventArgs e);
425427

426-
#endregion
428+
#endregion
427429

428-
#region MaxLength DependencyProperty
430+
#region MaxLength DependencyProperty
429431

430432
public int MaxLength
431433
{
@@ -448,9 +450,9 @@ public int MaxLength
448450

449451
partial void OnMaxLengthChangedPartial(DependencyPropertyChangedEventArgs e);
450452

451-
#endregion
453+
#endregion
452454

453-
#region AcceptsReturn DependencyProperty
455+
#region AcceptsReturn DependencyProperty
454456

455457
public bool AcceptsReturn
456458
{
@@ -487,9 +489,9 @@ private void OnAcceptsReturnChanged(DependencyPropertyChangedEventArgs e)
487489

488490
partial void OnAcceptsReturnChangedPartial(DependencyPropertyChangedEventArgs e);
489491

490-
#endregion
492+
#endregion
491493

492-
#region TextWrapping DependencyProperty
494+
#region TextWrapping DependencyProperty
493495
public TextWrapping TextWrapping
494496
{
495497
get => (TextWrapping)this.GetValue(TextWrappingProperty);
@@ -514,7 +516,7 @@ private void OnTextWrappingChanged(DependencyPropertyChangedEventArgs args)
514516

515517
partial void OnTextWrappingChangedPartial(DependencyPropertyChangedEventArgs e);
516518

517-
#endregion
519+
#endregion
518520

519521
#if __IOS__ || NET461 || __WASM__ || __SKIA__ || __NETSTD_REFERENCE__ || __MACOS__
520522
[Uno.NotImplemented("__IOS__", "NET461", "__WASM__", "__SKIA__", "__NETSTD_REFERENCE__", "__MACOS__")]
@@ -545,7 +547,7 @@ private void OnTextCharacterCasingChanged(DependencyPropertyChangedEventArgs e)
545547

546548
partial void OnTextCharacterCasingChangedPartial(DependencyPropertyChangedEventArgs e);
547549

548-
#region IsReadOnly DependencyProperty
550+
#region IsReadOnly DependencyProperty
549551

550552
public bool IsReadOnly
551553
{
@@ -572,9 +574,9 @@ private void OnIsReadonlyChanged(DependencyPropertyChangedEventArgs e)
572574

573575
partial void OnIsReadonlyChangedPartial(DependencyPropertyChangedEventArgs e);
574576

575-
#endregion
577+
#endregion
576578

577-
#region Header DependencyProperties
579+
#region Header DependencyProperties
578580

579581
public object Header
580582
{
@@ -618,9 +620,9 @@ private void OnHeaderChanged()
618620
}
619621
}
620622

621-
#endregion
623+
#endregion
622624

623-
#region IsSpellCheckEnabled DependencyProperty
625+
#region IsSpellCheckEnabled DependencyProperty
624626

625627
public bool IsSpellCheckEnabled
626628
{
@@ -643,9 +645,9 @@ public bool IsSpellCheckEnabled
643645

644646
partial void OnIsSpellCheckEnabledChangedPartial(DependencyPropertyChangedEventArgs e);
645647

646-
#endregion
648+
#endregion
647649

648-
#region IsTextPredictionEnabled DependencyProperty
650+
#region IsTextPredictionEnabled DependencyProperty
649651

650652
[Uno.NotImplemented]
651653
public bool IsTextPredictionEnabled
@@ -670,9 +672,9 @@ public bool IsTextPredictionEnabled
670672

671673
partial void OnIsTextPredictionEnabledChangedPartial(DependencyPropertyChangedEventArgs e);
672674

673-
#endregion
675+
#endregion
674676

675-
#region TextAlignment DependencyProperty
677+
#region TextAlignment DependencyProperty
676678

677679
#if XAMARIN_ANDROID
678680
public new TextAlignment TextAlignment
@@ -704,7 +706,7 @@ public string SelectedText
704706
throw new ArgumentNullException();
705707
}
706708

707-
var actual = (string)this.GetValue(TextProperty);
709+
var actual = (string)this.GetValue(TextProperty);
708710
actual = actual.Remove(SelectionStart, SelectionLength);
709711
actual = actual.Insert(SelectionStart, value);
710712

@@ -908,7 +910,11 @@ private void DeleteButtonClick()
908910

909911
partial void OnDeleteButtonClickPartial();
910912

911-
internal void OnSelectionChanged() => SelectionChanged?.Invoke(this, new RoutedEventArgs(this));
913+
internal void OnSelectionChanged()
914+
{
915+
SelectionChanged?.Invoke(this, new RoutedEventArgs(this));
916+
}
917+
912918

913919
public void OnTemplateRecycled()
914920
{
@@ -989,7 +995,7 @@ internal override void UpdateThemeBindings(Data.ResourceUpdateReason updateReaso
989995
UpdateKeyboardThemePartial();
990996
}
991997

992-
partial void UpdateKeyboardThemePartial();
998+
partial void UpdateKeyboardThemePartial();
993999

9941000
private protected override void OnIsEnabledChanged(IsEnabledChangedEventArgs e)
9951001
{
@@ -1000,10 +1006,10 @@ private protected override void OnIsEnabledChanged(IsEnabledChangedEventArgs e)
10001006

10011007
partial void OnIsEnabledChangedPartial(IsEnabledChangedEventArgs e);
10021008

1003-
private bool ShouldFocusOnPointerPressed(PointerRoutedEventArgs args)
1009+
private bool ShouldFocusOnPointerPressed(PointerRoutedEventArgs args) =>
10041010
// For mouse and pen, the TextBox should focus on pointer press
10051011
// (and then capture pointer to make sure to handle the whol down->move->up sequence).
10061012
// For touch we wait for the release to focus (avoid flickering in case of cancel due to scroll for instance).
1007-
=> args.Pointer.PointerDeviceType != PointerDeviceType.Touch;
1013+
args.Pointer.PointerDeviceType != PointerDeviceType.Touch;
10081014
}
10091015
}

src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.wasm.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ private void UpdateTextBoxView()
4343
}
4444
}
4545
}
46-
46+
4747
partial void InitializePropertiesPartial()
4848
{
4949
if (_header != null)
@@ -59,6 +59,21 @@ partial void OnTappedPartial()
5959
FocusTextView();
6060
}
6161

62+
63+
private void ResetCaret()
64+
{
65+
66+
this.SelectionStart = 0;
67+
this.SelectionLength = 0;
68+
69+
if (_textBoxView != null)
70+
{
71+
_textBoxView.SelectionStart = 0;
72+
_textBoxView.SelectionEnd = 0;
73+
74+
}
75+
}
76+
6277
private void OnHeaderClick(object sender, object args)
6378
{
6479
FocusTextView();

src/Uno.UI/UI/Xaml/Controls/TextBox/TextBoxView.skia.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,20 @@ internal void OnFocusStateChanged(FocusState focusState)
8787
{
8888
DisplayBlock.Opacity = 0;
8989
_textBoxExtension?.StartEntry();
90+
91+
var selectionStart = this.GetSelectionStart();
92+
93+
if (selectionStart == 0)
94+
{
95+
int cursorPosition = selectionStart + TextBox?.Text?.Length ?? 0;
96+
97+
_textBoxExtension?.Select(cursorPosition, 0);
98+
}
9099
}
91100
else
92101
{
93102
_textBoxExtension?.EndEntry();
94-
DisplayBlock.Opacity = 1;
103+
DisplayBlock.Opacity = 1;
95104
}
96105
}
97106

0 commit comments

Comments
 (0)