Browse Source

Merge 6eba5592d6 into 3068850405

pull/16910/merge
Thomas Bailly 21 hours ago
committed by GitHub
parent
commit
63fe693327
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 6
      samples/ControlCatalog/Pages/TextBoxPage.xaml
  2. 23
      src/Avalonia.Base/Media/CharacterCasing.cs
  3. 44
      src/Avalonia.Controls/TextBox.cs
  4. 31
      tests/Avalonia.Controls.UnitTests/TextBoxTests.cs

6
samples/ControlCatalog/Pages/TextBoxPage.xaml

@ -96,6 +96,12 @@
<TextBox Width="200" Text="Custom font italic" FontWeight="Normal" FontStyle="Italic" FontFamily="/Assets/Fonts/SourceSansPro-Italic.ttf#Source Sans Pro"/>
<TextBox Width="200" Text="Custom font italic bold" FontWeight="Bold" FontStyle="Italic" FontFamily="/Assets/Fonts/SourceSansPro-*.ttf#Source Sans Pro"/>
</StackPanel>
<StackPanel Orientation="Vertical" Spacing="8" Margin="8">
<TextBox Width="200" Text="Default casing" />
<TextBox Width="200" Text="Upper casing" CharacterCasing="Upper" />
<TextBox Width="200" Text="Lower casing" CharacterCasing="Lower" />
</StackPanel>
</WrapPanel>
<TextBox AcceptsReturn="True" TextWrapping="Wrap" Height="200" MaxWidth="400"
FontFamily="avares://ControlCatalog/Assets/Fonts#WenQuanYi Micro Hei"

23
src/Avalonia.Base/Media/CharacterCasing.cs

@ -0,0 +1,23 @@
namespace Avalonia.Media
{
/// <summary>
/// Defines how text is cased.
/// </summary>
public enum CharacterCasing
{
/// <summary>
/// The text casing is normal.
/// </summary>
Normal,
/// <summary>
/// The text casing is upper.
/// </summary>
Upper,
/// <summary>
/// The text casing is lower.
/// </summary>
Lower
}
}

44
src/Avalonia.Controls/TextBox.cs

@ -159,6 +159,9 @@ namespace Avalonia.Controls
public static readonly StyledProperty<TextAlignment> TextAlignmentProperty =
TextBlock.TextAlignmentProperty.AddOwner<TextBox>();
public static readonly StyledProperty<CharacterCasing> CharacterCasingProperty =
AvaloniaProperty.Register<TextBox, CharacterCasing>(nameof(CharacterCasing), defaultValue: CharacterCasing.Normal);
/// <summary>
/// Defines the <see cref="HorizontalAlignment"/> property.
/// </summary>
@ -455,6 +458,14 @@ namespace Avalonia.Controls
set => SetValue(CaretIndexProperty, value);
}
private void OnCharacterCasingChanged(AvaloniaPropertyChangedEventArgs e)
{
var tb = (TextBox)e.Sender;
var newValue = AdjustCasing(tb.Text, e.GetNewValue<CharacterCasing>());
SetCurrentValue(TextProperty, newValue);
}
private void OnCaretIndexChanged(AvaloniaPropertyChangedEventArgs e)
{
UndoRedoState state;
@ -638,8 +649,8 @@ namespace Avalonia.Controls
{
SnapshotUndoRedo();
}
return value;
return AdjustCasing(value, textBox.CharacterCasing);
}
/// <summary>
@ -691,6 +702,15 @@ namespace Avalonia.Controls
set => SetValue(TextAlignmentProperty, value);
}
/// <summary>
/// Gets or sets the <see cref="CharacterCasing"/> of the TextBox.
/// </summary>
public CharacterCasing CharacterCasing
{
get => GetValue(CharacterCasingProperty);
set => SetValue(CharacterCasingProperty, value);
}
/// <summary>
/// Gets or sets the placeholder or descriptive text that is displayed even if the <see cref="Text"/>
/// property is not yet set.
@ -1036,12 +1056,15 @@ namespace Avalonia.Controls
CoerceValue(CaretIndexProperty);
CoerceValue(SelectionStartProperty);
CoerceValue(SelectionEndProperty);
RaiseTextChangeEvents();
UpdatePseudoclasses();
UpdateCommandStates();
}
else if (change.Property == CharacterCasingProperty)
{
OnCharacterCasingChanged(change);
}
else if (change.Property == CaretIndexProperty)
{
OnCaretIndexChanged(change);
@ -1158,6 +1181,7 @@ namespace Avalonia.Controls
}
input = SanitizeInputText(input);
input = AdjustCasing(input, CharacterCasing);
if (string.IsNullOrEmpty(input))
{
@ -2272,6 +2296,20 @@ namespace Avalonia.Controls
return text.Substring(start, end - start);
}
/// <summary>
/// Adjust the text casing.
/// </summary>
/// <param name="text">The text to adjust.</param>
/// <param name="characterCasing">The character casing we want.</param>
/// <returns></returns>
private static string? AdjustCasing(string? text, CharacterCasing characterCasing) => characterCasing switch
{
CharacterCasing.Lower => text?.ToLower(System.Globalization.CultureInfo.CurrentCulture),
CharacterCasing.Upper => text?.ToUpper(System.Globalization.CultureInfo.CurrentCulture),
CharacterCasing.Normal => text,
_ => text
};
/// <summary>
/// Returns the sum of any vertical whitespace added between the <see cref="ScrollViewer"/> and <see cref="TextPresenter"/> in the control template.
/// </summary>

31
tests/Avalonia.Controls.UnitTests/TextBoxTests.cs

@ -1517,6 +1517,37 @@ namespace Avalonia.Controls.UnitTests
}
}
[Theory]
[InlineData(CharacterCasing.Lower, "LoWer", "lower")]
[InlineData(CharacterCasing.Upper, "uppEr", "UPPER")]
[InlineData(CharacterCasing.Normal, "NorMal", "NorMal")]
public void Should_Respect_Casing(CharacterCasing casing, string value, string expected)
{
var target = new TextBox
{
Template = CreateTemplate(),
CharacterCasing = casing,
Text = value
};
Assert.Equal(target.Text, expected);
}
[Fact]
public void Should_Update_Casing_After_First_Render()
{
var tb = new TextBox
{
Template = CreateTemplate(),
Text = "abc"
};
tb.Measure(Size.Infinity);
tb.CharacterCasing = CharacterCasing.Upper;
Assert.Equal("ABC", tb.Text);
}
[Fact]
public void Should_Move_Caret_To_EndOfLine()
{

Loading…
Cancel
Save