Skip to content

Commit

Permalink
[Enhancement] Entry: Read-only Entry and Editor (xamarin#1972)
Browse files Browse the repository at this point in the history
- fixes xamarin#1678
- fixes xamarin#4834

* InputView BindableProperty IsReadOnly

* Android Editor and Entry setup

* MacOS Editor and Entry setup

* Tizen Editor and Entry setup

* UAP Editor and Entry setup

* WPF Editor and Entry setup

* iOS Editor and Entry setup

* Issue1678 - TestContentPage added

* Tests added

* Tizen Editor and Entry fix

* UI Test fix

* Android fix for Entry and Editor.

* Unit Tests fix.

* Android Renderer first try.

* MacOS Entry renderer small fix.

* UpdateEditable fix.

* Android Entry and Editor reduced number of calls to BP.

* fix TestAttributes conflicts

* Remove keyboard

* [macOS] relinquish first responder

* [Android] remove call to UpdateCursorSelection

* [UWP] fix tabs
  • Loading branch information
almirvuk authored and andreinitescu committed Jan 29, 2019
1 parent f7823b6 commit 5c46848
Show file tree
Hide file tree
Showing 21 changed files with 219 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Text;

using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;

namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 1678, "[Enhancement] Entry: Read-only entry", PlatformAffected.All)]
public class Issue1678
: TestContentPage
{
protected override void Init()
{
var entryText = "Entry Lorem Ipsum";
var editorText = "Editor Lorem Ipsum";

var entryDefaults = new Entry { Text = entryText };
var editorDefaults = new Editor { Text = editorText };
var entryReadOnly = new Entry { Text = entryText, IsReadOnly = true };
var editorReadOnly = new Editor { Text = editorText, IsReadOnly = true };
var entryToggleable = new Entry { Text = entryText };
var editorToggleable = new Editor { Text = editorText };

var toggle = new Switch { IsToggled = false };

var stackLayout = new StackLayout();
stackLayout.Children.Add(new Label { Text = "Defaults" });
stackLayout.Children.Add(entryDefaults);
stackLayout.Children.Add(editorDefaults);
stackLayout.Children.Add(new Label { Text = "Read Only" });
stackLayout.Children.Add(entryReadOnly);
stackLayout.Children.Add(editorReadOnly);
stackLayout.Children.Add(new Label { Text = "Toggleable is read only" });
stackLayout.Children.Add(entryToggleable);
stackLayout.Children.Add(editorToggleable);
stackLayout.Children.Add(toggle);

toggle.Toggled += (_, b) =>
{
entryToggleable.IsReadOnly = b.Value;
editorToggleable.IsReadOnly = b.Value;
};

stackLayout.Padding = new Thickness(0, 20, 0, 0);
Content = stackLayout;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Issue3788.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue1724.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue3524.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue1678.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue2004.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue3333.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue2338.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ protected override void Build(StackLayout stackLayout)

var maxLengthContainer = new ViewContainer<Editor>(Test.InputView.MaxLength, new Editor { MaxLength = 3 });

var readOnlyContainer = new ViewContainer<Editor>(Test.Editor.IsReadOnly, new Editor { Text = "This is read-only Editor", IsReadOnly = true });

Add(completedContainer);
Add(textContainer);
Add(textChangedContainer);
Expand All @@ -54,6 +56,7 @@ protected override void Build(StackLayout stackLayout)
Add(textColorDisabledContainer);
Add(keyboardContainer);
Add(maxLengthContainer);
Add(readOnlyContainer);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ protected override void Build (StackLayout stackLayout)

var maxLengthContainer = new ViewContainer<Entry>(Test.InputView.MaxLength, new Entry { MaxLength = 3 });

var readOnlyContainer = new ViewContainer<Entry>(Test.Entry.IsReadOnly, new Entry { Text = "This is read-only Entry", IsReadOnly = true });
var isPasswordInputScopeContainer = new ViewContainer<Entry>(Test.Entry.IsPasswordNumeric, new Entry { Keyboard = Keyboard.Numeric });
var switchPasswordButton = new Button
{
Expand Down Expand Up @@ -110,6 +111,7 @@ protected override void Build (StackLayout stackLayout)
Add (placeholderColorDisabledContainer);
Add (passwordColorContainer);
Add (maxLengthContainer);
Add (readOnlyContainer);
Add (isPasswordInputScopeContainer);
}
}
Expand Down
14 changes: 14 additions & 0 deletions Xamarin.Forms.Core.UnitTests/EditorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,5 +30,19 @@ public void EditorTextChangedEventArgs (string initialText, string finalText)
Assert.AreEqual (initialText, oldText);
Assert.AreEqual (finalText, newText);
}

[TestCase(true)]
public void IsReadOnlyTest(bool isReadOnly)
{
Editor editor = new Editor();
editor.SetValue(InputView.IsReadOnlyProperty, isReadOnly);
Assert.AreEqual(isReadOnly, editor.IsReadOnly);
}
[Test]
public void IsReadOnlyDefaultValueTest()
{
Editor editor = new Editor();
Assert.AreEqual(editor.IsReadOnly, false);
}
}
}
15 changes: 15 additions & 0 deletions Xamarin.Forms.Core.UnitTests/EntryUnitTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,5 +154,20 @@ public void ReturnTypeCommandNullTestIsEnabled(bool isEnabled)

Assert.True(result == isEnabled ? true : false);
}

[TestCase(true)]
public void IsReadOnlyTest(bool isReadOnly)
{
Entry entry = new Entry();
entry.SetValue(InputView.IsReadOnlyProperty, isReadOnly);
Assert.AreEqual(isReadOnly, entry.IsReadOnly);
}

[Test]
public void IsReadOnlyDefaultValueTest()
{
Entry entry = new Entry();
Assert.AreEqual(entry.IsReadOnly, false);
}
}
}
4 changes: 3 additions & 1 deletion Xamarin.Forms.Core.UnitTests/NotifiedPropertiesTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,9 @@ public override INotifyPropertyChanged CreateView ()
new PropertyTestCase<TapGestureRecognizer, int> ("NumberOfTapsRequired", t => t.NumberOfTapsRequired, (t, o) => t.NumberOfTapsRequired = o, () => 1, 3),
new PropertyTestCase<TapGestureRecognizer, object> ("CommandParameter", t => t.CommandParameter, (t, o) => t.CommandParameter = o, () => null, "Test"),
new PropertyTestCase<TapGestureRecognizer, ICommand> ("Command", t => t.Command, (t, o) => t.Command = o, () => null, new Command(()=>{})),
new PropertyTestCase<MasterDetailPage, bool> ("IsGestureEnabled", md => md.IsGestureEnabled, (md, v) => md.IsGestureEnabled = v, () => true, false)
new PropertyTestCase<MasterDetailPage, bool> ("IsGestureEnabled", md => md.IsGestureEnabled, (md, v) => md.IsGestureEnabled = v, () => true, false),
new PropertyTestCase<Entry, bool> ("IsReadOnly", v => v.IsReadOnly, (v, o) => v.IsReadOnly = o, () => false, true),
new PropertyTestCase<Editor, bool> ("IsReadOnly", v => v.IsReadOnly, (v, o) => v.IsReadOnly = o, () => false, true)
};
#pragma warning restore 0414

Expand Down
8 changes: 8 additions & 0 deletions Xamarin.Forms.Core/InputView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ public class InputView : View

public static readonly BindableProperty MaxLengthProperty = BindableProperty.Create(nameof(MaxLength), typeof(int), typeof(int), int.MaxValue);

public static readonly BindableProperty IsReadOnlyProperty = BindableProperty.Create(nameof(IsReadOnly), typeof(bool), typeof(InputView), false);

public int MaxLength
{
get { return (int)GetValue(MaxLengthProperty); }
Expand All @@ -29,5 +31,11 @@ public bool IsSpellCheckEnabled
get { return (bool)GetValue(IsSpellCheckEnabledProperty); }
set { SetValue(IsSpellCheckEnabledProperty, value); }
}

public bool IsReadOnly
{
get { return (bool)GetValue(IsReadOnlyProperty); }
set { SetValue(IsReadOnlyProperty, value); }
}
}
}
4 changes: 4 additions & 0 deletions Xamarin.Forms.CustomAttributes/TestAttributes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -507,6 +507,8 @@ public enum Editor
FontAttributes,
FontFamily,
FontSize,
MaxLength,
IsReadOnly
}

public enum Entry
Expand All @@ -530,6 +532,8 @@ public enum Entry
TextDisabledColor,
PlaceholderDisabledColor,
PasswordColor,
MaxLength,
IsReadOnly,
IsPasswordNumeric
}

Expand Down
12 changes: 12 additions & 0 deletions Xamarin.Forms.Platform.Android/Renderers/EditorRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
UpdateMaxLength();
UpdatePlaceholderColor();
UpdatePlaceholderText();
UpdateIsReadOnly();
}

protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
Expand All @@ -118,6 +119,8 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE
UpdatePlaceholderText();
else if (e.PropertyName == Editor.PlaceholderColorProperty.PropertyName)
UpdatePlaceholderColor();
else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
UpdateIsReadOnly();

base.OnElementPropertyChanged(sender, e);
}
Expand Down Expand Up @@ -249,5 +252,14 @@ void UpdateMaxLength()
if (currentControlText.Length > Element.MaxLength)
Control.Text = currentControlText.Substring(0, Element.MaxLength);
}

void UpdateIsReadOnly()
{
bool isReadOnly = !Element.IsReadOnly;

Control.FocusableInTouchMode = isReadOnly;
Control.Focusable = isReadOnly;
Control.SetCursorVisible(isReadOnly);
}
}
}
16 changes: 14 additions & 2 deletions Xamarin.Forms.Platform.Android/Renderers/EntryRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
UpdateMaxLength();
UpdateImeOptions();
UpdateReturnType();
UpdateIsReadOnly();

if (_cursorPositionChangePending || _selectionLengthChangePending)
UpdateCursorSelection();
Expand Down Expand Up @@ -210,6 +211,8 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE
UpdateCursorSelection();
else if (e.PropertyName == Entry.CursorPositionProperty.PropertyName)
UpdateCursorSelection();
else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
UpdateIsReadOnly();

base.OnElementPropertyChanged(sender, e);
}
Expand Down Expand Up @@ -358,7 +361,7 @@ void UpdateCursorSelection()
if (_nativeSelectionIsUpdating || Control == null || Element == null)
return;

if (Control.RequestFocus())
if (!Element.IsReadOnly && Control.RequestFocus())
{
try
{
Expand Down Expand Up @@ -440,5 +443,14 @@ void SetSelectionLengthFromRenderer(int selectionLength)
_nativeSelectionIsUpdating = false;
}
}

void UpdateIsReadOnly()
{
bool isReadOnly = !Element.IsReadOnly;

Control.FocusableInTouchMode = isReadOnly;
Control.Focusable = isReadOnly;
Control.SetCursorVisible(isReadOnly);
}
}
}
}
10 changes: 10 additions & 0 deletions Xamarin.Forms.Platform.MacOS/Renderers/EditorRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
UpdateTextColor();
UpdateEditable();
UpdateMaxLength();
UpdateIsReadOnly();
}

protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
Expand All @@ -62,6 +63,8 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE
UpdateFont();
else if (e.PropertyName == InputView.MaxLengthProperty.PropertyName)
UpdateMaxLength();
else if (e.PropertyName == Xamarin.Forms.InputView.IsReadOnlyProperty.PropertyName)
UpdateIsReadOnly();
}

protected override void SetBackgroundColor(Color color)
Expand Down Expand Up @@ -148,5 +151,12 @@ void UpdateMaxLength()
if (currentControlText.Length > Element?.MaxLength)
Control.StringValue = currentControlText.Substring(0, Element.MaxLength);
}

void UpdateIsReadOnly()
{
Control.Editable = !Element.IsReadOnly;
if (Element.IsReadOnly && Control.Window?.FirstResponder == Control.CurrentEditor)
Control.Window?.MakeFirstResponder(null);
}
}
}
13 changes: 12 additions & 1 deletion Xamarin.Forms.Platform.MacOS/Renderers/EntryRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE
UpdateAlignment();
else if (e.PropertyName == InputView.MaxLengthProperty.PropertyName)
UpdateMaxLength();
else if (e.PropertyName == Xamarin.Forms.InputView.IsReadOnlyProperty.PropertyName)
UpdateIsReadOnly();

base.OnElementPropertyChanged(sender, e);
}
Expand Down Expand Up @@ -201,7 +203,8 @@ void UpdateControl()
UpdateFont();
UpdateAlignment();
UpdateMaxLength();
}
UpdateIsReadOnly();
}

void TextFieldFocusChanged(object sender, BoolEventArgs e)
{
Expand Down Expand Up @@ -289,5 +292,13 @@ void UpdateMaxLength()
if (currentControlText.Length > Element?.MaxLength)
Control.StringValue = currentControlText.Substring(0, Element.MaxLength);
}


void UpdateIsReadOnly()
{
Control.Editable = !Element.IsReadOnly;
if (Element.IsReadOnly && Control.Window?.FirstResponder == Control.CurrentEditor)
Control.Window?.MakeFirstResponder(null);
}
}
}
6 changes: 6 additions & 0 deletions Xamarin.Forms.Platform.Tizen/Renderers/EditorRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ public EditorRenderer()
RegisterPropertyHandler(InputView.IsSpellCheckEnabledProperty, UpdateIsSpellCheckEnabled);
RegisterPropertyHandler(Editor.PlaceholderProperty, UpdatePlaceholder);
RegisterPropertyHandler(Editor.PlaceholderColorProperty, UpdatePlaceholderColor);
RegisterPropertyHandler(InputView.IsReadOnlyProperty, UpdateIsReadOnly);
}

protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
Expand Down Expand Up @@ -153,5 +154,10 @@ string MaxLengthFilter(ElmSharp.Entry entry, string s)

return null;
}

void UpdateIsReadOnly()
{
Control.IsEditable = !Element.IsReadOnly;
}
}
}
6 changes: 6 additions & 0 deletions Xamarin.Forms.Platform.Tizen/Renderers/EntryRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public EntryRenderer()
RegisterPropertyHandler(Entry.IsTextPredictionEnabledProperty, UpdateIsSpellCheckEnabled);
RegisterPropertyHandler(Specific.FontWeightProperty, UpdateFontWeight);
RegisterPropertyHandler(Entry.SelectionLengthProperty, UpdateSelectionLength);
RegisterPropertyHandler(InputView.IsReadOnlyProperty, UpdateIsReadOnly);
}

protected override void OnElementChanged(ElementChangedEventArgs<Entry> e)
Expand Down Expand Up @@ -198,5 +199,10 @@ int GetCursorPosition()

return Element.Text.IndexOf(selection, Math.Max(Control.CursorPosition - selection.Length, 0));
}

void UpdateIsReadOnly()
{
Control.IsEditable = !Element.IsReadOnly;
}
}
}
8 changes: 8 additions & 0 deletions Xamarin.Forms.Platform.UAP/EditorRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ protected override void OnElementChanged(ElementChangedEventArgs<Editor> e)
UpdateDetectReadingOrderFromContent();
UpdatePlaceholderText();
UpdatePlaceholderColor();
UpdateIsReadOnly();
}

base.OnElementChanged(e);
Expand Down Expand Up @@ -127,6 +128,8 @@ protected override void OnElementPropertyChanged(object sender, PropertyChangedE
UpdatePlaceholderText();
else if (e.PropertyName == Editor.PlaceholderColorProperty.PropertyName)
UpdatePlaceholderColor();
else if (e.PropertyName == InputView.IsReadOnlyProperty.PropertyName)
UpdateIsReadOnly();
}

void OnLostFocus(object sender, RoutedEventArgs e)
Expand Down Expand Up @@ -357,5 +360,10 @@ void UpdateDetectReadingOrderFromContent()
}
}
}

void UpdateIsReadOnly()
{
Control.IsReadOnly = Element.IsReadOnly;
}
}
}
Loading

0 comments on commit 5c46848

Please sign in to comment.