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

[Core] Added TextTransform property #3690

Merged
merged 10 commits into from
May 8, 2020
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using Xamarin.Forms.CustomAttributes;
using Xamarin.Forms.Internals;

#if UITEST
using NUnit.Framework;
using Xamarin.UITest;
#endif

namespace Xamarin.Forms.Controls.Issues
{
[Preserve(AllMembers = true)]
[Issue(IssueTracker.Github, 3667, "[Enhancement] Add text-transforms to Label", PlatformAffected.All)]
public class Issue3667 : TestContentPage
{
string text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.";

protected override void Init()
{
var text2 = "Malesuada fames ac turpis egestas maecenas pharetra convallis. Dictum varius duis at consectetur lorem donec massa. Augue interdum velit euismod in pellentesque.";
var transform = TextTransform.None;

var list = new ITextElement[] {
new Label { Text = text },
new Entry { Text = "Entry text" },
new Editor { Text = "Editor text" },
new SearchBar { Text = "SearchBar text" },
new Button { Text = "Button text" },
};

var statusLabel = new Label
{
Text = "Current TextTransform is None",
BackgroundColor = Color.Aqua,
TextTransform = transform
};
var but = new Button
{
Text = "Change TextTransform",
Command = new Command(() =>
{
if (++transform > TextTransform.Uppercase)
transform = TextTransform.None;
foreach (var item in list)
item.TextTransform = transform;
statusLabel.Text = $"Current TextTransform is {transform}";
})
};

var layout = new StackLayout
{
Children = {
statusLabel,
but
}
};

foreach (var item in list)
{
item.TextTransform = transform;
layout.Children.Add(item as View);
}

layout.Children.Add(new Label
{
Text = "[Lowercase] " + text2,
TextTransform = TextTransform.Lowercase
});
layout.Children.Add(new Label
{
Text = "[Uppercase] " + text2,
TextTransform = TextTransform.Uppercase
});

Content = layout;
}

#if UITEST
[Test]
public void Issue3667Tests ()
{
RunningApp.WaitForElement(query => query.Text(text));
RunningApp.Tap("Change TextTransform");
RunningApp.WaitForElement(query => query.Text(text));
RunningApp.Tap("Change TextTransform");
RunningApp.WaitForElement(query => query.Text(text.ToLowerInvariant()));
RunningApp.Tap("Change TextTransform");
RunningApp.WaitForElement(query => query.Text(text.ToUpperInvariant()));
RunningApp.Tap("Change TextTransform");
RunningApp.WaitForElement(query => query.Text(text));
}
#endif
}
}


Original file line number Diff line number Diff line change
Expand Up @@ -1201,6 +1201,7 @@
<Compile Include="$(MSBuildThisFileDirectory)GitHub1776.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue3408.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue3413.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue3667.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue3525.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue3275.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Issue3884.cs" />
Expand Down
12 changes: 12 additions & 0 deletions Xamarin.Forms.Core.UnitTests/LabelTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,18 @@ public void InvalidateMeasureWhenTextChanges ()
label.Text = "Foo";
Assert.IsTrue (fired);

fired = false;
label.TextTransform = TextTransform.Lowercase;
Assert.IsTrue(fired);

fired = false;
label.TextTransform = TextTransform.Uppercase;
Assert.IsTrue(fired);

fired = false;
label.TextTransform = TextTransform.None;
Assert.IsTrue(fired);

var fs = new FormattedString ();

fired = false;
Expand Down
13 changes: 13 additions & 0 deletions Xamarin.Forms.Core/Button.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ public class Button : View, IFontElement, ITextElement, IBorderElement, IButtonC

public static readonly BindableProperty FontSizeProperty = FontElement.FontSizeProperty;

public static readonly BindableProperty TextTransformProperty = TextElement.TextTransformProperty;

public static readonly BindableProperty FontAttributesProperty = FontElement.FontAttributesProperty;

public static readonly BindableProperty BorderWidthProperty = BindableProperty.Create("BorderWidth", typeof(double), typeof(Button), -1d);
Expand Down Expand Up @@ -209,6 +211,12 @@ public double FontSize
set { SetValue(FontSizeProperty, value); }
}

public TextTransform TextTransform
{
get => (TextTransform)GetValue(TextTransformProperty);
set => SetValue(TextTransformProperty, value);
}

public event EventHandler Clicked;
public event EventHandler Pressed;

Expand Down Expand Up @@ -361,6 +369,11 @@ void IImageController.SetIsLoading(bool isLoading)
bool IBorderElement.IsBorderColorSet() => IsSet(BorderColorProperty);
bool IBorderElement.IsBorderWidthSet() => IsSet(BorderWidthProperty);

void ITextElement.OnTextTransformChanged(TextTransform oldValue, TextTransform newValue)
=> InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);

public virtual string UpdateFormsText(string source, TextTransform textTransform)
=> TextTransformUtilites.GetTransformedText(source, textTransform);

[DebuggerDisplay("Image Position = {Position}, Spacing = {Spacing}")]
[TypeConverter(typeof(ButtonContentTypeConverter))]
Expand Down
15 changes: 15 additions & 0 deletions Xamarin.Forms.Core/DatePicker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ public class DatePicker : View, IFontElement, ITextElement, IElementConfiguratio

public static readonly BindableProperty FontAttributesProperty = FontElement.FontAttributesProperty;

public static readonly BindableProperty TextTransformProperty = TextElement.TextTransformProperty;

readonly Lazy<PlatformConfigurationRegistry<DatePicker>> _platformConfigurationRegistry;

public DatePicker()
Expand All @@ -49,6 +51,12 @@ public string Format
set { SetValue(FormatProperty, value); }
}

public TextTransform TextTransform
{
get { return (TextTransform)GetValue(TextTransformProperty); }
set { SetValue(TextTransformProperty, value); }
}

public DateTime MaximumDate
{
get { return (DateTime)GetValue(MaximumDateProperty); }
Expand Down Expand Up @@ -107,6 +115,13 @@ double IFontElement.FontSizeDefaultValueCreator() =>
void IFontElement.OnFontAttributesChanged(FontAttributes oldValue, FontAttributes newValue) =>
InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);

void ITextElement.OnTextTransformChanged(TextTransform oldValue, TextTransform newValue)
{
}

public virtual string UpdateFormsText(string source, TextTransform textTransform)
=> TextTransformUtilites.GetTransformedText(source, textTransform);

public event EventHandler<DateChangedEventArgs> DateSelected;

static object CoerceDate(BindableObject bindable, object value)
Expand Down
9 changes: 8 additions & 1 deletion Xamarin.Forms.Core/ITextElement.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Xamarin.Forms.Internals;

namespace Xamarin.Forms
{
Expand All @@ -14,5 +15,11 @@ interface ITextElement

//note to implementor: but implement these methods explicitly
void OnCharacterSpacingPropertyChanged(double oldValue, double newValue);

TextTransform TextTransform { get; set; }

void OnTextTransformChanged(TextTransform oldValue, TextTransform newValue);

string UpdateFormsText(string original, TextTransform transform);
}
}
}
19 changes: 19 additions & 0 deletions Xamarin.Forms.Core/InputView.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using Xamarin.Forms.Internals;

namespace Xamarin.Forms
{
Expand All @@ -24,6 +25,8 @@ public class InputView : View, IPlaceholderElement, ITextElement

public static readonly BindableProperty CharacterSpacingProperty = TextElement.CharacterSpacingProperty;

public static readonly BindableProperty TextTransformProperty = TextElement.TextTransformProperty;

public int MaxLength
{
get => (int)GetValue(MaxLengthProperty);
Expand Down Expand Up @@ -82,6 +85,12 @@ public double CharacterSpacing
set => SetValue(CharacterSpacingProperty, value);
}

public TextTransform TextTransform
{
get => (TextTransform)GetValue(TextTransformProperty);
set => SetValue(TextTransformProperty, value);
}

public event EventHandler<TextChangedEventArgs> TextChanged;

protected virtual void OnTextChanged(string oldValue, string newValue)
Expand All @@ -97,6 +106,16 @@ void ITextElement.OnCharacterSpacingPropertyChanged(double oldValue, double newV
{
InvalidateMeasure();
}

public void OnTextTransformChanged(TextTransform oldValue, TextTransform newValue)
{
InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);
}

public string UpdateFormsText(string original, TextTransform transform)
{
return TextTransformUtilites.GetTransformedText(original, transform);
}
}

public enum ClearButtonVisibility
Expand Down
46 changes: 46 additions & 0 deletions Xamarin.Forms.Core/Internals/TextTransformUtilites.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using System.ComponentModel;

namespace Xamarin.Forms.Internals
{
[EditorBrowsable(EditorBrowsableState.Never)]
public static class TextTransformUtilites
{
[EditorBrowsable(EditorBrowsableState.Never)]
public static string GetTransformedText(string source, TextTransform textTransform)
{
if (string.IsNullOrEmpty(source))
return string.Empty;

switch (textTransform)
{
case TextTransform.None:
default:
return source;
case TextTransform.Lowercase:
return source.ToLowerInvariant();
case TextTransform.Uppercase:
return source.ToUpperInvariant();
}
}


[EditorBrowsable(EditorBrowsableState.Never)]
public static void SetPlainText(InputView inputView, string nativeText)
{
if (inputView == null)
return;

var textTransform = inputView.TextTransform;
var nativeTextWithTransform = inputView.UpdateFormsText(nativeText, textTransform);
var formsText = inputView.UpdateFormsText(inputView.Text, textTransform);

if ((string.IsNullOrEmpty(formsText) && nativeText.Length == 0))
return;

if (formsText == nativeTextWithTransform)
return;

inputView.SetValueFromRenderer(InputView.TextProperty, nativeText);
}
}
}
16 changes: 16 additions & 0 deletions Xamarin.Forms.Core/Label.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Collections.Specialized;
using System.ComponentModel;
using System.Linq;
using System.Text;
using Xamarin.Forms.Internals;
using Xamarin.Forms.Platform;

Expand Down Expand Up @@ -40,6 +41,8 @@ public class Label : View, IFontElement, ITextElement, ITextAlignmentElement, IL

public static readonly BindableProperty FontAttributesProperty = FontElement.FontAttributesProperty;

public static readonly BindableProperty TextTransformProperty = TextElement.TextTransformProperty;

public static readonly BindableProperty TextDecorationsProperty = DecorableTextElement.TextDecorationsProperty;

public static readonly BindableProperty FormattedTextProperty = BindableProperty.Create(nameof(FormattedText), typeof(FormattedString), typeof(Label), default(FormattedString),
Expand Down Expand Up @@ -75,6 +78,15 @@ public class Label : View, IFontElement, ITextElement, ITextAlignmentElement, IL
label.Text = null;
});

public TextTransform TextTransform
{
get { return (TextTransform)GetValue(TextTransformProperty); }
set { SetValue(TextTransformProperty, value); }
}

public virtual string UpdateFormsText(string source, TextTransform textTransform)
=> TextTransformUtilites.GetTransformedText(source, textTransform);

public static readonly BindableProperty LineBreakModeProperty = BindableProperty.Create(nameof(LineBreakMode), typeof(LineBreakMode), typeof(Label), LineBreakMode.WordWrap,
propertyChanged: (bindable, oldvalue, newvalue) => ((Label)bindable).InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged));

Expand Down Expand Up @@ -244,6 +256,10 @@ void OnFormattedTextChanging(object sender, PropertyChangingEventArgs e)
{
OnPropertyChanging("FormattedText");
}

void ITextElement.OnTextTransformChanged(TextTransform oldValue, TextTransform newValue) =>
InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);

void OnFormattedTextChanged(object sender, PropertyChangedEventArgs e)
{
OnPropertyChanged("FormattedText");
Expand Down
16 changes: 15 additions & 1 deletion Xamarin.Forms.Core/Picker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ public class Picker : View, IFontElement, ITextElement, IElementConfiguration<Pi
public static readonly BindableProperty FontSizeProperty = FontElement.FontSizeProperty;

public static readonly BindableProperty FontAttributesProperty = FontElement.FontAttributesProperty;


public static readonly BindableProperty TextTransformProperty = TextElement.TextTransformProperty;

readonly Lazy<PlatformConfigurationRegistry<Picker>> _platformConfigurationRegistry;

public Picker()
Expand All @@ -67,6 +69,15 @@ public double FontSize
set { SetValue(FontSizeProperty, value); }
}

public TextTransform TextTransform
{
get => (TextTransform)GetValue(TextTransformProperty);
set => SetValue(TextTransformProperty, value);
}

public virtual string UpdateFormsText(string source, TextTransform textTransform)
=> TextTransformUtilites.GetTransformedText(source, textTransform);

void IFontElement.OnFontFamilyChanged(string oldValue, string newValue) =>
InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);

Expand All @@ -82,6 +93,9 @@ double IFontElement.FontSizeDefaultValueCreator() =>
void IFontElement.OnFontAttributesChanged(FontAttributes oldValue, FontAttributes newValue) =>
InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);

void ITextElement.OnTextTransformChanged(TextTransform oldValue, TextTransform newValue) =>
InvalidateMeasureInternal(InvalidationTrigger.MeasureChanged);

public IList<string> Items { get; } = new LockableObservableListWrapper();

public IList ItemsSource
Expand Down
1 change: 1 addition & 0 deletions Xamarin.Forms.Core/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
[assembly: StyleProperty("border-width", typeof(IBorderElement), nameof(BorderElement.BorderWidthProperty))]
[assembly: StyleProperty("color", typeof(IColorElement), nameof(ColorElement.ColorProperty), Inherited = true)]
[assembly: StyleProperty("color", typeof(ITextElement), nameof(TextElement.TextColorProperty), Inherited = true)]
[assembly: StyleProperty("text-transform", typeof(ITextElement), nameof(TextElement.TextTransformProperty), Inherited = true)]
[assembly: StyleProperty("color", typeof(ProgressBar), nameof(ProgressBar.ProgressColorProperty))]
[assembly: StyleProperty("color", typeof(Switch), nameof(Switch.OnColorProperty))]
[assembly: StyleProperty("column-gap", typeof(Grid), nameof(Grid.ColumnSpacingProperty))]
Expand Down
Loading