Browse Source

[Feature] Move LetterSpacing to TextElement as inherited attached property (#20141)

* Add LetterSpacing property to the Button

* Created attached property

* Added samples

* Updated implementation

* Updated Themes

* Updated ButtonPage LetterSpacing sample

* Updated templates

* Updated API
fixes/effect-clip-rect
Javier Suárez 2 months ago
committed by GitHub
parent
commit
7efc6d9bb0
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 26
      api/Avalonia.nupkg.xml
  2. 4
      samples/ControlCatalog/Pages/ButtonsPage.xaml
  3. 44
      src/Avalonia.Controls/Documents/TextElement.cs
  4. 15
      src/Avalonia.Controls/Presenters/ContentPresenter.cs
  5. 2
      src/Avalonia.Controls/Presenters/TextPresenter.cs
  6. 15
      src/Avalonia.Controls/Primitives/TemplatedControl.cs
  7. 12
      src/Avalonia.Controls/TextBlock.cs
  8. 15
      src/Avalonia.Controls/TextBox.cs
  9. 2
      src/Avalonia.Themes.Fluent/Controls/Label.xaml
  10. 1
      src/Avalonia.Themes.Fluent/Controls/ToolTip.xaml
  11. 134
      tests/Avalonia.Controls.UnitTests/ButtonTests.cs
  12. 37
      tests/Avalonia.Controls.UnitTests/CheckBoxTests.cs
  13. 37
      tests/Avalonia.Controls.UnitTests/LabelTests.cs
  14. 71
      tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Standalone.cs
  15. 48
      tests/Avalonia.Controls.UnitTests/Primitives/TemplatedControlTests.cs
  16. 20
      tests/Avalonia.Controls.UnitTests/RadioButtonTests.cs
  17. 6
      tests/Avalonia.Controls.UnitTests/TextBlockTests.cs

26
api/Avalonia.nupkg.xml

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- https://learn.microsoft.com/dotnet/fundamentals/package-validation/diagnostic-ids --> <!-- https://learn.microsoft.com/dotnet/fundamentals/package-validation/diagnostic-ids -->
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Suppression> <Suppression>
@ -49,6 +49,18 @@
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left> <Left>baseline/Avalonia/lib/net10.0/Avalonia.Base.dll</Left>
<Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right> <Right>current/Avalonia/lib/net10.0/Avalonia.Base.dll</Right>
</Suppression> </Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>F:Avalonia.Controls.TextBlock.LetterSpacingProperty</Target>
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll</Left>
<Right>current/Avalonia/lib/net10.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>F:Avalonia.Controls.TextBox.LetterSpacingProperty</Target>
<Left>baseline/Avalonia/lib/net10.0/Avalonia.Controls.dll</Left>
<Right>current/Avalonia/lib/net10.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression> <Suppression>
<DiagnosticId>CP0002</DiagnosticId> <DiagnosticId>CP0002</DiagnosticId>
<Target>F:Avalonia.Media.Fonts.FontCollectionBase._glyphTypefaceCache</Target> <Target>F:Avalonia.Media.Fonts.FontCollectionBase._glyphTypefaceCache</Target>
@ -103,6 +115,18 @@
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left> <Left>baseline/Avalonia/lib/net8.0/Avalonia.Base.dll</Left>
<Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right> <Right>current/Avalonia/lib/net8.0/Avalonia.Base.dll</Right>
</Suppression> </Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>F:Avalonia.Controls.TextBlock.LetterSpacingProperty</Target>
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll</Left>
<Right>current/Avalonia/lib/net8.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression>
<DiagnosticId>CP0002</DiagnosticId>
<Target>F:Avalonia.Controls.TextBox.LetterSpacingProperty</Target>
<Left>baseline/Avalonia/lib/net8.0/Avalonia.Controls.dll</Left>
<Right>current/Avalonia/lib/net8.0/Avalonia.Controls.dll</Right>
</Suppression>
<Suppression> <Suppression>
<DiagnosticId>CP0002</DiagnosticId> <DiagnosticId>CP0002</DiagnosticId>
<Target>M:Avalonia.Dialogs.Internal.ManagedFileChooserFilterViewModel.#ctor(Avalonia.Platform.Storage.FilePickerFileType)</Target> <Target>M:Avalonia.Dialogs.Internal.ManagedFileChooserFilterViewModel.#ctor(Avalonia.Platform.Storage.FilePickerFileType)</Target>

4
samples/ControlCatalog/Pages/ButtonsPage.xaml

@ -91,6 +91,8 @@
</Button.Styles> </Button.Styles>
</Button> </Button>
<Button Classes="accent">Accent</Button> <Button Classes="accent">Accent</Button>
<Button LetterSpacing="0">Normal Spacing</Button>
<Button LetterSpacing="2.0">Loose Spacing</Button>
</StackPanel> </StackPanel>
<StackPanel Orientation="Vertical" <StackPanel Orientation="Vertical"
@ -105,6 +107,8 @@
IsEnabled="False">Disabled</Button> IsEnabled="False">Disabled</Button>
<Button BorderBrush="{DynamicResource SystemAccentColor}" <Button BorderBrush="{DynamicResource SystemAccentColor}"
KeyboardNavigation.IsTabStop="False">IsTabStop=False</Button> KeyboardNavigation.IsTabStop="False">IsTabStop=False</Button>
<Button LetterSpacing="-0.5">Tight Spacing</Button>
<Button LetterSpacing="4.0">E X T R A L O O S E</Button>
</StackPanel> </StackPanel>
</StackPanel> </StackPanel>
</Border> </Border>

44
src/Avalonia.Controls/Documents/TextElement.cs

@ -76,6 +76,21 @@ namespace Avalonia.Controls.Documents
Brushes.Black, Brushes.Black,
inherits: true); inherits: true);
/// <summary>
/// Defines the <see cref="LetterSpacing"/> property.
/// </summary>
/// <remarks>
/// This is an inherited attached property that defines letter spacing for text.
/// Letter spacing is specified in pixels. Default value is 0 (normal spacing).
/// Positive values increase spacing between characters.
/// Negative values decrease spacing between characters.
/// </remarks>
public static readonly AttachedProperty<double> LetterSpacingProperty =
AvaloniaProperty.RegisterAttached<TextElement, Control, double>(
name: nameof(LetterSpacing),
defaultValue: 0.0,
inherits: true);
private IInlineHost? _inlineHost; private IInlineHost? _inlineHost;
/// <summary> /// <summary>
@ -150,6 +165,15 @@ namespace Avalonia.Controls.Documents
set => SetValue(ForegroundProperty, value); set => SetValue(ForegroundProperty, value);
} }
/// <summary>
/// Gets or sets the letter spacing.
/// </summary>
public double LetterSpacing
{
get => GetValue(LetterSpacingProperty);
set => SetValue(LetterSpacingProperty, value);
}
/// <summary> /// <summary>
/// Gets the value of the attached <see cref="FontFamilyProperty"/> on a control. /// Gets the value of the attached <see cref="FontFamilyProperty"/> on a control.
/// </summary> /// </summary>
@ -190,6 +214,26 @@ namespace Avalonia.Controls.Documents
control.SetValue(FontFeaturesProperty, value); control.SetValue(FontFeaturesProperty, value);
} }
/// <summary>
/// Gets the value of the attached <see cref="LetterSpacingProperty"/> on a control.
/// </summary>
/// <param name="control">The control.</param>
/// <returns>The letter spacing applied to the control.</returns>
public static double GetLetterSpacing(Control control)
{
return control.GetValue(LetterSpacingProperty);
}
/// <summary>
/// Sets the value of the attached <see cref="LetterSpacingProperty"/> on a control.
/// </summary>
/// <param name="control">The control.</param>
/// <param name="value">The letter spacing to apply.</param>
public static void SetLetterSpacing(Control control, double value)
{
control.SetValue(LetterSpacingProperty, value);
}
/// <summary> /// <summary>
/// Gets the value of the attached <see cref="FontSizeProperty"/> on a control. /// Gets the value of the attached <see cref="FontSizeProperty"/> on a control.
/// </summary> /// </summary>

15
src/Avalonia.Controls/Presenters/ContentPresenter.cs

@ -118,6 +118,12 @@ namespace Avalonia.Controls.Presenters
public static readonly StyledProperty<double> LineHeightProperty = public static readonly StyledProperty<double> LineHeightProperty =
TextBlock.LineHeightProperty.AddOwner<ContentPresenter>(); TextBlock.LineHeightProperty.AddOwner<ContentPresenter>();
/// <summary>
/// Defines the <see cref="LetterSpacing"/> property
/// </summary>
public static readonly StyledProperty<double> LetterSpacingProperty =
TextElement.LetterSpacingProperty.AddOwner<ContentPresenter>();
/// <summary> /// <summary>
/// Defines the <see cref="MaxLines"/> property /// Defines the <see cref="MaxLines"/> property
/// </summary> /// </summary>
@ -327,6 +333,15 @@ namespace Avalonia.Controls.Presenters
set => SetValue(LineHeightProperty, value); set => SetValue(LineHeightProperty, value);
} }
/// <summary>
/// Gets or sets the letter spacing
/// </summary>
public double LetterSpacing
{
get => GetValue(LetterSpacingProperty);
set => SetValue(LetterSpacingProperty, value);
}
/// <summary> /// <summary>
/// Gets or sets the max lines /// Gets or sets the max lines
/// </summary> /// </summary>

2
src/Avalonia.Controls/Presenters/TextPresenter.cs

@ -87,7 +87,7 @@ namespace Avalonia.Controls.Presenters
/// Defines the <see cref="LetterSpacing"/> property. /// Defines the <see cref="LetterSpacing"/> property.
/// </summary> /// </summary>
public static readonly StyledProperty<double> LetterSpacingProperty = public static readonly StyledProperty<double> LetterSpacingProperty =
TextBlock.LetterSpacingProperty.AddOwner<TextPresenter>(); TextElement.LetterSpacingProperty.AddOwner<TextPresenter>();
/// <summary> /// <summary>
/// Defines the <see cref="Background"/> property. /// Defines the <see cref="Background"/> property.

15
src/Avalonia.Controls/Primitives/TemplatedControl.cs

@ -88,6 +88,12 @@ namespace Avalonia.Controls.Primitives
public static readonly StyledProperty<IBrush?> ForegroundProperty = public static readonly StyledProperty<IBrush?> ForegroundProperty =
TextElement.ForegroundProperty.AddOwner<TemplatedControl>(); TextElement.ForegroundProperty.AddOwner<TemplatedControl>();
/// <summary>
/// Defines the <see cref="LetterSpacing"/> property.
/// </summary>
public static readonly StyledProperty<double> LetterSpacingProperty =
TextElement.LetterSpacingProperty.AddOwner<TemplatedControl>();
/// <summary> /// <summary>
/// Defines the <see cref="Padding"/> property. /// Defines the <see cref="Padding"/> property.
/// </summary> /// </summary>
@ -242,6 +248,15 @@ namespace Avalonia.Controls.Primitives
set => SetValue(ForegroundProperty, value); set => SetValue(ForegroundProperty, value);
} }
/// <summary>
/// Gets or sets the letter spacing for the control's text content.
/// </summary>
public double LetterSpacing
{
get => GetValue(LetterSpacingProperty);
set => SetValue(LetterSpacingProperty, value);
}
/// <summary> /// <summary>
/// Gets or sets the padding placed between the border of the control and its content. /// Gets or sets the padding placed between the border of the control and its content.
/// </summary> /// </summary>

12
src/Avalonia.Controls/TextBlock.cs

@ -97,11 +97,13 @@ namespace Avalonia.Controls
/// <summary> /// <summary>
/// Defines the <see cref="LetterSpacing"/> property. /// Defines the <see cref="LetterSpacing"/> property.
/// </summary> /// </summary>
public static readonly AttachedProperty<double> LetterSpacingProperty = /// <remarks>
AvaloniaProperty.RegisterAttached<TextBlock, Control, double>( /// This property uses <see cref="AvaloniaProperty.AddOwner{TOwner}(AvaloniaProperty)"/> to share the same
nameof(LetterSpacing), /// definition as <see cref="TextElement.LetterSpacingProperty"/>, ensuring consistent behavior across text
0, /// elements and templated controls.
inherits: true); /// </remarks>
public static readonly StyledProperty<double> LetterSpacingProperty =
TextElement.LetterSpacingProperty.AddOwner<TextBlock>();
/// <summary> /// <summary>
/// Defines the <see cref="MaxLines"/> property. /// Defines the <see cref="MaxLines"/> property.

15
src/Avalonia.Controls/TextBox.cs

@ -180,12 +180,6 @@ namespace Avalonia.Controls
public static readonly StyledProperty<double> LineHeightProperty = public static readonly StyledProperty<double> LineHeightProperty =
TextBlock.LineHeightProperty.AddOwner<TextBox>(new(defaultValue: double.NaN)); TextBlock.LineHeightProperty.AddOwner<TextBox>(new(defaultValue: double.NaN));
/// <summary>
/// Defines see <see cref="TextBlock.LetterSpacing"/> property.
/// </summary>
public static readonly StyledProperty<double> LetterSpacingProperty =
TextBlock.LetterSpacingProperty.AddOwner<TextBox>();
/// <summary> /// <summary>
/// Defines the <see cref="Watermark"/> property /// Defines the <see cref="Watermark"/> property
/// </summary> /// </summary>
@ -570,15 +564,6 @@ namespace Avalonia.Controls
set => SetValue(MinLinesProperty, value); set => SetValue(MinLinesProperty, value);
} }
/// <summary>
/// Gets or sets the spacing between characters
/// </summary>
public double LetterSpacing
{
get => GetValue(LetterSpacingProperty);
set => SetValue(LetterSpacingProperty, value);
}
/// <summary> /// <summary>
/// Gets or sets the line height. /// Gets or sets the line height.
/// </summary> /// </summary>

2
src/Avalonia.Themes.Fluent/Controls/Label.xaml

@ -15,7 +15,7 @@
Content="{TemplateBinding Content}" Content="{TemplateBinding Content}"
Padding="{TemplateBinding Padding}" Padding="{TemplateBinding Padding}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"/> HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" />
</ControlTemplate> </ControlTemplate>
</Setter> </Setter>

1
src/Avalonia.Themes.Fluent/Controls/ToolTip.xaml

@ -46,6 +46,7 @@
MaxWidth="{TemplateBinding MaxWidth}" MaxWidth="{TemplateBinding MaxWidth}"
Content="{TemplateBinding Content}" Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}" ContentTemplate="{TemplateBinding ContentTemplate}"
TextBlock.LetterSpacing="{TemplateBinding LetterSpacing}"
TextBlock.TextWrapping="Wrap"/> TextBlock.TextWrapping="Wrap"/>
</Border> </Border>
</ControlTemplate> </ControlTemplate>

134
tests/Avalonia.Controls.UnitTests/ButtonTests.cs

@ -619,6 +619,140 @@ namespace Avalonia.Controls.UnitTests
[Fact]
public void Button_LetterSpacing_Default_Value_Is_Zero()
{
var button = new Button();
Assert.Equal(0, button.LetterSpacing);
}
[Fact]
public void Button_LetterSpacing_Can_Be_Set_And_Retrieved()
{
var button = new Button { LetterSpacing = 2.5 };
Assert.Equal(2.5, button.LetterSpacing);
}
[Fact]
public void Button_LetterSpacing_Can_Be_Set_To_Negative_Value()
{
var button = new Button { LetterSpacing = -1.5 };
Assert.Equal(-1.5, button.LetterSpacing);
}
[Fact]
public void Button_LetterSpacing_Can_Be_Set_To_Zero()
{
var button = new Button { LetterSpacing = 5.0 };
button.LetterSpacing = 0;
Assert.Equal(0, button.LetterSpacing);
}
[Fact]
public void Button_LetterSpacing_Propagates_To_ContentPresenter()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var button = new Button
{
Content = "Test",
LetterSpacing = 3.0
};
var root = new TestRoot { Child = button };
button.ApplyTemplate();
var presenter = button.Presenter;
Assert.NotNull(presenter);
Assert.Equal(3.0, presenter.LetterSpacing);
}
}
[Fact]
public void Button_LetterSpacing_Updates_ContentPresenter_When_Changed()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var button = new Button
{
Content = "Test",
LetterSpacing = 1.0
};
var root = new TestRoot { Child = button };
button.ApplyTemplate();
var presenter = button.Presenter;
button.LetterSpacing = 5.0;
Assert.Equal(5.0, presenter.LetterSpacing);
}
}
[Fact]
public void Button_LetterSpacing_Works_With_Large_Values()
{
var button = new Button { LetterSpacing = 100.0 };
Assert.Equal(100.0, button.LetterSpacing);
}
[Fact]
public void Button_LetterSpacing_Property_Inherits_Through_Visual_Tree()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var button = new Button
{
Content = "Test",
LetterSpacing = 2.0
};
var root = new TestRoot { Child = button };
button.ApplyTemplate();
button.Presenter?.UpdateChild();
// Verify the property value is accessible on the presenter
var presenter = button.Presenter;
Assert.NotNull(presenter);
Assert.Equal(2.0, presenter.LetterSpacing);
}
}
[Fact]
public void Button_LetterSpacing_Affects_TextBlock_Child_In_ContentPresenter()
{
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
var button = new Button
{
Content = "Test Text",
LetterSpacing = 3.5
};
var root = new TestRoot { Child = button };
button.ApplyTemplate();
button.Presenter?.UpdateChild();
// Find the TextBlock that was created by ContentPresenter
var presenter = button.Presenter;
Assert.NotNull(presenter);
var textBlock = presenter.Child as TextBlock;
Assert.NotNull(textBlock);
// Verify LetterSpacing inherited to the TextBlock
Assert.Equal(3.5, textBlock.LetterSpacing);
// Force a measure to create TextLayout
textBlock.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
// Verify the TextLayout actually has the LetterSpacing value
var textLayout = textBlock.TextLayout;
Assert.NotNull(textLayout);
Assert.Equal(3.5, textLayout.LetterSpacing);
}
}
private class TestTopLevel : TopLevel private class TestTopLevel : TopLevel
{ {
private readonly ILayoutManager _layoutManager; private readonly ILayoutManager _layoutManager;

37
tests/Avalonia.Controls.UnitTests/CheckBoxTests.cs

@ -0,0 +1,37 @@
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Controls.UnitTests
{
public class CheckBoxTests : ScopedTestBase
{
[Fact]
public void CheckBox_LetterSpacing_Default_Value_Is_Zero()
{
var checkBox = new CheckBox();
Assert.Equal(0, checkBox.LetterSpacing);
}
[Fact]
public void CheckBox_LetterSpacing_Can_Be_Set_And_Retrieved()
{
var checkBox = new CheckBox { LetterSpacing = 2.5 };
Assert.Equal(2.5, checkBox.LetterSpacing);
}
[Fact]
public void CheckBox_LetterSpacing_Inherits_From_TemplatedControl()
{
var checkBox = new CheckBox { LetterSpacing = 3.0 };
// LetterSpacing is inherited from TemplatedControl
Assert.Equal(3.0, checkBox.LetterSpacing);
}
[Fact]
public void CheckBox_LetterSpacing_Can_Be_Negative()
{
var checkBox = new CheckBox { LetterSpacing = -1.5 };
Assert.Equal(-1.5, checkBox.LetterSpacing);
}
}
}

37
tests/Avalonia.Controls.UnitTests/LabelTests.cs

@ -0,0 +1,37 @@
using Avalonia.UnitTests;
using Xunit;
namespace Avalonia.Controls.UnitTests
{
public class LabelTests : ScopedTestBase
{
[Fact]
public void Label_LetterSpacing_Default_Value_Is_Zero()
{
var label = new Label();
Assert.Equal(0, label.LetterSpacing);
}
[Fact]
public void Label_LetterSpacing_Can_Be_Set_And_Retrieved()
{
var label = new Label { LetterSpacing = 2.5 };
Assert.Equal(2.5, label.LetterSpacing);
}
[Fact]
public void Label_LetterSpacing_Inherits_From_TemplatedControl()
{
var label = new Label { LetterSpacing = 3.0 };
// LetterSpacing is inherited from TemplatedControl
Assert.Equal(3.0, label.LetterSpacing);
}
[Fact]
public void Label_LetterSpacing_Can_Be_Negative()
{
var label = new Label { LetterSpacing = -1.5 };
Assert.Equal(-1.5, label.LetterSpacing);
}
}
}

71
tests/Avalonia.Controls.UnitTests/Presenters/ContentPresenterTests_Standalone.cs

@ -12,6 +12,7 @@ using Xunit;
using Avalonia.Rendering; using Avalonia.Rendering;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Data; using Avalonia.Data;
using Avalonia.Controls.Documents;
namespace Avalonia.Controls.UnitTests.Presenters namespace Avalonia.Controls.UnitTests.Presenters
{ {
@ -333,5 +334,75 @@ namespace Avalonia.Controls.UnitTests.Presenters
Assert.NotNull(target.Child); Assert.NotNull(target.Child);
} }
[Fact]
public void ContentPresenter_LetterSpacing_Default_Value_Is_Zero()
{
var presenter = new ContentPresenter();
Assert.Equal(0, presenter.LetterSpacing);
}
[Fact]
public void ContentPresenter_LetterSpacing_Can_Be_Set_And_Retrieved()
{
var presenter = new ContentPresenter { LetterSpacing = 3.5 };
Assert.Equal(3.5, presenter.LetterSpacing);
}
[Fact]
public void ContentPresenter_LetterSpacing_Can_Be_Negative()
{
var presenter = new ContentPresenter { LetterSpacing = -2.0 };
Assert.Equal(-2.0, presenter.LetterSpacing);
}
[Fact]
public void ContentPresenter_LetterSpacing_Propagates_To_TextBlock_Child()
{
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
var presenter = new ContentPresenter
{
Content = "Test Content",
LetterSpacing = 4.0
};
var root = new TestRoot { Child = presenter };
presenter.UpdateChild();
var textBlock = presenter.Child as TextBlock;
Assert.NotNull(textBlock);
Assert.Equal(4.0, textBlock.LetterSpacing);
}
}
[Fact]
public void ContentPresenter_LetterSpacing_Updates_TextBlock_When_Changed()
{
using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface))
{
var presenter = new ContentPresenter
{
Content = "Test Content",
LetterSpacing = 1.0
};
var root = new TestRoot { Child = presenter };
presenter.UpdateChild();
var textBlock = presenter.Child as TextBlock;
presenter.LetterSpacing = 6.0;
Assert.NotNull(textBlock);
Assert.Equal(6.0, textBlock.LetterSpacing);
}
}
[Fact]
public void ContentPresenter_LetterSpacing_Property_Inherits_From_TextBlock()
{
// Verify that ContentPresenter's LetterSpacing uses the TextElement letter spacing definition
Assert.Same(TextElement.LetterSpacingProperty, ContentPresenter.LetterSpacingProperty);
}
} }
} }

48
tests/Avalonia.Controls.UnitTests/Primitives/TemplatedControlTests.cs

@ -11,6 +11,7 @@ using Avalonia.UnitTests;
using Avalonia.VisualTree; using Avalonia.VisualTree;
using Xunit; using Xunit;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Controls.Documents;
namespace Avalonia.Controls.UnitTests.Primitives namespace Avalonia.Controls.UnitTests.Primitives
{ {
@ -597,5 +598,52 @@ namespace Avalonia.Controls.UnitTests.Primitives
return result; return result;
} }
[Fact]
public void TemplatedControl_LetterSpacing_Default_Value_Is_Zero()
{
var target = new TestTemplatedControl();
Assert.Equal(0, target.LetterSpacing);
}
[Fact]
public void TemplatedControl_LetterSpacing_Uses_TextElement_Property()
{
Assert.Same(TextElement.LetterSpacingProperty, TemplatedControl.LetterSpacingProperty);
}
[Fact]
public void TemplatedControl_LetterSpacing_Can_Be_Set_And_Retrieved()
{
var target = new TestTemplatedControl { LetterSpacing = 2.5 };
Assert.Equal(2.5, target.LetterSpacing);
}
[Fact]
public void TemplatedControl_LetterSpacing_Can_Be_Negative()
{
var target = new TestTemplatedControl { LetterSpacing = -1.5 };
Assert.Equal(-1.5, target.LetterSpacing);
}
[Fact]
public void TemplatedControl_LetterSpacing_Inherits_To_ContentPresenter()
{
using (UnitTestApplication.Start(TestServices.StyledWindow))
{
var target = new ContentControl
{
LetterSpacing = 3.0,
Content = "Test",
};
var root = new TestRoot { Child = target };
target.ApplyTemplate();
var presenter = target.Presenter;
Assert.NotNull(presenter);
Assert.Equal(3.0, presenter.LetterSpacing);
}
}
} }
} }

20
tests/Avalonia.Controls.UnitTests/RadioButtonTests.cs

@ -106,8 +106,28 @@ namespace Avalonia.Controls.UnitTests
Assert.False(radioButton2.IsChecked); Assert.False(radioButton2.IsChecked);
Assert.True(radioButton3.IsChecked); Assert.True(radioButton3.IsChecked);
Assert.False(radioButton4.IsChecked); Assert.False(radioButton4.IsChecked);
}
[Fact]
public void RadioButton_LetterSpacing_Default_Value_Is_Zero()
{
var radioButton = new RadioButton();
Assert.Equal(0, radioButton.LetterSpacing);
}
[Fact]
public void RadioButton_LetterSpacing_Can_Be_Set_And_Retrieved()
{
var radioButton = new RadioButton { LetterSpacing = 2.5 };
Assert.Equal(2.5, radioButton.LetterSpacing);
}
[Fact]
public void RadioButton_LetterSpacing_Inherits_From_TemplatedControl()
{
var radioButton = new RadioButton { LetterSpacing = 3.0 };
// LetterSpacing is inherited from TemplatedControl
Assert.Equal(3.0, radioButton.LetterSpacing);
} }
} }
} }

6
tests/Avalonia.Controls.UnitTests/TextBlockTests.cs

@ -28,6 +28,12 @@ namespace Avalonia.Controls.UnitTests
Assert.Equal(null, textBlock.Text); Assert.Equal(null, textBlock.Text);
} }
[Fact]
public void LetterSpacing_Property_Uses_TextElement_Definition()
{
Assert.Same(TextElement.LetterSpacingProperty, TextBlock.LetterSpacingProperty);
}
[Fact] [Fact]
public void Calling_Measure_Should_Update_TextLayout() public void Calling_Measure_Should_Update_TextLayout()
{ {

Loading…
Cancel
Save