Skip to content
This repository was archived by the owner on May 1, 2024. It is now read-only.

Commit

Permalink
[Android,iOS,UWP] Allow Entry CursorPosition/SelectionLength to be se…
Browse files Browse the repository at this point in the history
…t in ctor (#3402) fixes #3343 fixes #3633

* Add repro for #3343 + unit tests

* [Core] Disallow negative values for CursorPosition/SelectionLength

* [All] CursorPosition/SelectionLength can bindin ctor & clear value

fixes #3343

* typo

* cleanup

* [iOS] Cursor snaps to end

* try/catch
  • Loading branch information
samhouts authored and rmarinho committed Aug 31, 2018
1 parent 8f03f5e commit a8260b0
Show file tree
Hide file tree
Showing 7 changed files with 544 additions and 102 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using System.Threading.Tasks;
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;

namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 3343, "[Android] Cursor position in entry and selection length not working on 3.2.0-pre1", PlatformAffected.Android | PlatformAffected.iOS)]
public class Issue3343 : TestContentPage
{
protected override void Init()
{
Entry entry = new Entry()
{
Text = "Initialized",
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.StartAndExpand,
WidthRequest = 150
};

entry.CursorPosition = 4;
entry.SelectionLength = entry.Text.Length;

Label entryLabel = new Label { VerticalOptions = LayoutOptions.Center, FontSize = 8 };
entryLabel.SetBinding(Label.TextProperty, new Binding(nameof(Entry.CursorPosition), stringFormat: "CursorPosition: {0}", source: entry));

Label entryLabel2 = new Label { VerticalOptions = LayoutOptions.Center, FontSize = 8 };
entryLabel2.SetBinding(Label.TextProperty, new Binding(nameof(Entry.SelectionLength), stringFormat: "SelectionLength: {0}", source: entry));

Entry entry2 = new Entry()
{
Text = "Click Button",
VerticalOptions = LayoutOptions.Center,
HorizontalOptions = LayoutOptions.StartAndExpand,
WidthRequest = 150
};

Label entry2Label = new Label { VerticalOptions = LayoutOptions.Center, FontSize = 8 };
entry2Label.SetBinding(Label.TextProperty, new Binding(nameof(Entry.CursorPosition), stringFormat: "CursorPosition: {0}", source: entry2));

Label entry2Label2 = new Label { VerticalOptions = LayoutOptions.Center, FontSize = 8 };
entry2Label2.SetBinding(Label.TextProperty, new Binding(nameof(Entry.SelectionLength), stringFormat: "SelectionLength: {0}", source: entry2));

// When the Entry is in a NavPage, the Entry doesn't get first focus on UWP
string uwp_instructions = Device.RuntimePlatform == Device.UWP ? "Press Tab to focus the first entry. " : "";

Content = new StackLayout()
{
Padding = 20,
Children =
{
new StackLayout{ Children = { entry, entryLabel, entryLabel2 }, Orientation = StackOrientation.Horizontal },
new StackLayout{ Children = { entry2, entry2Label, entry2Label2 }, Orientation = StackOrientation.Horizontal },
new Button()
{
Text = "Click Me",
Command = new Command(() =>
{
entry2.CursorPosition = 4;
entry2.SelectionLength = entry2.Text.Length;
})
},
new Button()
{
Text = "Click Me After",
Command = new Command(() =>
{
entry2.CursorPosition = 2;
})
},
new Button()
{
Text = "Click Me Last",
Command = new Command(async () =>
{
entry2.ClearValue(Entry.SelectionLengthProperty);

await Task.Delay(500);

entry2.ClearValue(Entry.CursorPositionProperty);
})
},
new Label{ Text = $"{uwp_instructions}The first Entry should have all text selected starting at character 4. Click the first button to trigger the same selection in the second Entry. Click the second button to move the cursor position but keep the selection length to the end. Click the third button to clear the selection length and then the cursor position." }
}
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Issue2837.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue2740.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue1939.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue3343.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue3342.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue3415.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue3049.cs" />
Expand Down
92 changes: 75 additions & 17 deletions Xamarin.Forms.Core.UnitTests/EntryUnitTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,24 @@ public void ValueChangedFromSetValue()
const string value = "Foo";

bool signaled = false;
entry.TextChanged += (sender, args) => {
entry.TextChanged += (sender, args) =>
{
signaled = true;
Assert.AreEqual (value, args.NewTextValue);
Assert.AreEqual(value, args.NewTextValue);
};

entry.SetValue (Entry.TextProperty, value);
entry.SetValue(Entry.TextProperty, value);

Assert.IsTrue (signaled, "ValueChanged did not fire");
Assert.IsTrue(signaled, "ValueChanged did not fire");
}

[TestCase (null, "foo")]
[TestCase ("foo", "bar")]
[TestCase ("foo", null)]
public void ValueChangedArgs (string initial, string final)
[TestCase(null, "foo")]
[TestCase("foo", "bar")]
[TestCase("foo", null)]
public void ValueChangedArgs(string initial, string final)
{
var entry = new Entry {
var entry = new Entry
{
Text = initial
};

Expand All @@ -39,17 +41,73 @@ public void ValueChangedArgs (string initial, string final)

Entry entryFromSender = null;

entry.TextChanged += (s, e) => {
entry.TextChanged += (s, e) =>
{
entryFromSender = (Entry)s;
oldValue = e.OldTextValue;
newValue = e.NewTextValue;
};

entry.Text = final;

Assert.AreEqual (entry, entryFromSender);
Assert.AreEqual (initial, oldValue);
Assert.AreEqual (final, newValue);
Assert.AreEqual(entry, entryFromSender);
Assert.AreEqual(initial, oldValue);
Assert.AreEqual(final, newValue);
}


[TestCase(1)]
[TestCase(0)]
[TestCase(9999)]
public void CursorPositionValid(int val)
{
var entry = new Entry
{
CursorPosition = val
};

var target = entry.CursorPosition;

Assert.AreEqual(target, val);
}

[Test]
public void CursorPositionInvalid()
{
Assert.Throws<System.ArgumentException>(() =>
{
var entry = new Entry
{
CursorPosition = -1
};
});
}

[TestCase(1)]
[TestCase(0)]
[TestCase(9999)]
public void SelectionLengthValid(int val)
{
var entry = new Entry
{
SelectionLength = val
};

var target = entry.SelectionLength;

Assert.AreEqual(target, val);
}

[Test]
public void SelectionLengthInvalid()
{
Assert.Throws<System.ArgumentException>(() =>
{
var entry = new Entry
{
SelectionLength = -1
};
});
}

[TestCase(true)]
Expand All @@ -63,8 +121,7 @@ public void ReturnTypeCommand(bool isEnabled)

bool result = false;

var bindingContext = new
{
var bindingContext = new {
Command = new Command(() => { result = true; }, () => true)
};

Expand All @@ -86,10 +143,11 @@ public void ReturnTypeCommandNullTestIsEnabled(bool isEnabled)
};

bool result = false;

entry.SetBinding(Entry.ReturnCommandProperty, "Command");
entry.BindingContext = null;
entry.Completed += (s, e) => {
entry.Completed += (s, e) =>
{
result = true;
};
entry.SendCompleted();
Expand Down
4 changes: 2 additions & 2 deletions Xamarin.Forms.Core/Entry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,9 @@ public class Entry : InputView, IFontElement, ITextElement, ITextAlignmentElemen

public static readonly BindableProperty IsTextPredictionEnabledProperty = BindableProperty.Create(nameof(IsTextPredictionEnabled), typeof(bool), typeof(Entry), true, BindingMode.OneTime);

public static readonly BindableProperty CursorPositionProperty = BindableProperty.Create(nameof(CursorPosition), typeof(int), typeof(Entry), 0);
public static readonly BindableProperty CursorPositionProperty = BindableProperty.Create(nameof(CursorPosition), typeof(int), typeof(Entry), 0, validateValue: (b, v) => (int)v >= 0);

public static readonly BindableProperty SelectionLengthProperty = BindableProperty.Create(nameof(SelectionLength), typeof(int), typeof(Entry), 0);
public static readonly BindableProperty SelectionLengthProperty = BindableProperty.Create(nameof(SelectionLength), typeof(int), typeof(Entry), 0, validateValue: (b, v) => (int)v >= 0);

readonly Lazy<PlatformConfigurationRegistry<Entry>> _platformConfigurationRegistry;

Expand Down
Loading

0 comments on commit a8260b0

Please sign in to comment.