From 75d210913ea23a156d7ce6a9411a269b9b6c82ab Mon Sep 17 00:00:00 2001
From: Thomas Bailly <3940727+Authfix@users.noreply.github.com>
Date: Tue, 3 Sep 2024 22:57:10 +0200
Subject: [PATCH 1/6] feat(textbox): add character casing to TextBox
---
samples/ControlCatalog/Pages/TextBoxPage.xaml | 6 +++++
src/Avalonia.Base/Media/CharacterCasing.cs | 23 +++++++++++++++++++
src/Avalonia.Controls/TextBox.cs | 22 ++++++++++++++++++
3 files changed, 51 insertions(+)
create mode 100644 src/Avalonia.Base/Media/CharacterCasing.cs
diff --git a/samples/ControlCatalog/Pages/TextBoxPage.xaml b/samples/ControlCatalog/Pages/TextBoxPage.xaml
index 7408399873..f5f45797d3 100644
--- a/samples/ControlCatalog/Pages/TextBoxPage.xaml
+++ b/samples/ControlCatalog/Pages/TextBoxPage.xaml
@@ -88,6 +88,12 @@
+
+
+
+
+
+
+ /// Defines how text is cased.
+ ///
+ public enum CharacterCasing
+ {
+ ///
+ /// The text casing is normal.
+ ///
+ Normal,
+
+ ///
+ /// The text casing is upper.
+ ///
+ Upper,
+
+ ///
+ /// The text casing is lower.
+ ///
+ Lower
+ }
+}
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index b12c23c597..a4a982641e 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -146,6 +146,9 @@ namespace Avalonia.Controls
public static readonly StyledProperty TextAlignmentProperty =
TextBlock.TextAlignmentProperty.AddOwner();
+ public static readonly StyledProperty CharacterCasingProperty =
+ AvaloniaProperty.Register(nameof(CharacterCasing), defaultValue: CharacterCasing.Normal);
+
///
/// Defines the property.
///
@@ -632,6 +635,12 @@ namespace Avalonia.Controls
set => SetValue(TextAlignmentProperty, value);
}
+ public CharacterCasing CharacterCasing
+ {
+ get => GetValue(CharacterCasingProperty);
+ set => SetValue(CharacterCasingProperty, value);
+ }
+
///
/// Gets or sets the placeholder or descriptive text that is displayed even if the
/// property is not yet set.
@@ -915,6 +924,10 @@ namespace Avalonia.Controls
UpdatePseudoclasses();
UpdateCommandStates();
}
+ else if (change.Property == CharacterCasingProperty)
+ {
+ Text = AdjustCasing(Text);
+ }
else if (change.Property == CaretIndexProperty)
{
OnCaretIndexChanged(change);
@@ -1017,6 +1030,7 @@ namespace Avalonia.Controls
}
input = SanitizeInputText(input);
+ input = AdjustCasing(input);
if (string.IsNullOrEmpty(input))
{
@@ -2112,6 +2126,14 @@ namespace Avalonia.Controls
return text.Substring(start, end - start);
}
+ private string? AdjustCasing(string? text) => CharacterCasing switch
+ {
+ CharacterCasing.Lower => text?.ToLower(System.Globalization.CultureInfo.CurrentCulture),
+ CharacterCasing.Upper => text?.ToUpper(System.Globalization.CultureInfo.CurrentCulture),
+ CharacterCasing.Normal => text,
+ _ => text
+ };
+
///
/// Returns the sum of any vertical whitespace added between the and in the control template.
///
From 2e006302ff164197b6fb8b7e316b6146a9e8da47 Mon Sep 17 00:00:00 2001
From: Thomas Bailly <3940727+Authfix@users.noreply.github.com>
Date: Wed, 4 Sep 2024 00:24:33 +0200
Subject: [PATCH 2/6] refactor(textbox): update code to match existing
conventions
---
src/Avalonia.Controls/TextBox.cs | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index a4a982641e..efb59f7f10 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -403,6 +403,14 @@ namespace Avalonia.Controls
set => SetValue(CaretIndexProperty, value);
}
+ private void OnCharacterCasingChanged(AvaloniaPropertyChangedEventArgs e)
+ {
+ var tb = (TextBox)e.Sender;
+ var newValue = AdjustCasing(tb.Text);
+
+ SetCurrentValue(TextProperty, newValue);
+ }
+
private void OnCaretIndexChanged(AvaloniaPropertyChangedEventArgs e)
{
UndoRedoState state;
@@ -926,7 +934,7 @@ namespace Avalonia.Controls
}
else if (change.Property == CharacterCasingProperty)
{
- Text = AdjustCasing(Text);
+ OnCharacterCasingChanged(change);
}
else if (change.Property == CaretIndexProperty)
{
From 1254f13e5cc6019b40620e4867b2d8d3558464cc Mon Sep 17 00:00:00 2001
From: Thomas Bailly <3940727+Authfix@users.noreply.github.com>
Date: Wed, 4 Sep 2024 01:12:10 +0200
Subject: [PATCH 3/6] feat(textbox): use coerce and input
---
src/Avalonia.Controls/TextBox.cs | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index efb59f7f10..d7b30ea2f6 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -406,7 +406,7 @@ namespace Avalonia.Controls
private void OnCharacterCasingChanged(AvaloniaPropertyChangedEventArgs e)
{
var tb = (TextBox)e.Sender;
- var newValue = AdjustCasing(tb.Text);
+ var newValue = AdjustCasing(tb.Text, e.GetNewValue());
SetCurrentValue(TextProperty, newValue);
}
@@ -591,8 +591,8 @@ namespace Avalonia.Controls
{
textBox.SnapshotUndoRedo();
}
-
- return value;
+
+ return AdjustCasing(value, textBox.CharacterCasing);
}
///
@@ -643,6 +643,9 @@ namespace Avalonia.Controls
set => SetValue(TextAlignmentProperty, value);
}
+ ///
+ /// Gets or sets the of the TextBox.
+ ///
public CharacterCasing CharacterCasing
{
get => GetValue(CharacterCasingProperty);
@@ -926,7 +929,7 @@ namespace Avalonia.Controls
CoerceValue(CaretIndexProperty);
CoerceValue(SelectionStartProperty);
CoerceValue(SelectionEndProperty);
-
+
RaiseTextChangeEvents();
UpdatePseudoclasses();
@@ -1038,7 +1041,7 @@ namespace Avalonia.Controls
}
input = SanitizeInputText(input);
- input = AdjustCasing(input);
+ input = AdjustCasing(input, CharacterCasing);
if (string.IsNullOrEmpty(input))
{
@@ -2134,7 +2137,13 @@ namespace Avalonia.Controls
return text.Substring(start, end - start);
}
- private string? AdjustCasing(string? text) => CharacterCasing switch
+ ///
+ /// Adjust the text casing.
+ ///
+ /// The text to adjust.
+ /// The character casing we want.
+ ///
+ 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),
From fb76189f1c5ab28d534bb803cfb24a679d7f28c0 Mon Sep 17 00:00:00 2001
From: Thomas Bailly <3940727+Authfix@users.noreply.github.com>
Date: Wed, 4 Sep 2024 01:14:57 +0200
Subject: [PATCH 4/6] refactor: remove typo
---
src/Avalonia.Controls/TextBox.cs | 1 -
1 file changed, 1 deletion(-)
diff --git a/src/Avalonia.Controls/TextBox.cs b/src/Avalonia.Controls/TextBox.cs
index d7b30ea2f6..5576e6a496 100644
--- a/src/Avalonia.Controls/TextBox.cs
+++ b/src/Avalonia.Controls/TextBox.cs
@@ -929,7 +929,6 @@ namespace Avalonia.Controls
CoerceValue(CaretIndexProperty);
CoerceValue(SelectionStartProperty);
CoerceValue(SelectionEndProperty);
-
RaiseTextChangeEvents();
UpdatePseudoclasses();
From 0f103271c7dc5bec299f9b6bdd70f6417c3e9075 Mon Sep 17 00:00:00 2001
From: Thomas Bailly <3940727+Authfix@users.noreply.github.com>
Date: Wed, 4 Sep 2024 01:20:42 +0200
Subject: [PATCH 5/6] tests(textbox): add tests for casing
---
.../Avalonia.Controls.UnitTests/TextBoxTests.cs | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
index 30f82533ce..bcc444c6bd 100644
--- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
@@ -1385,6 +1385,22 @@ 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_Move_Caret_To_EndOfLine()
{
From 6eba5592d6779eb8fb5735be6565b6ec85b1a491 Mon Sep 17 00:00:00 2001
From: Thomas Bailly <3940727+Authfix@users.noreply.github.com>
Date: Wed, 4 Sep 2024 01:25:14 +0200
Subject: [PATCH 6/6] tests(textbox): check casing update
---
tests/Avalonia.Controls.UnitTests/TextBoxTests.cs | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
index bcc444c6bd..1338592e5a 100644
--- a/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
+++ b/tests/Avalonia.Controls.UnitTests/TextBoxTests.cs
@@ -1401,6 +1401,21 @@ namespace Avalonia.Controls.UnitTests
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()
{