Browse Source

Merge pull request #11013 from AvaloniaUI/refactor/readonly-classes

Make Classes properties readonly.
pull/11020/head
Dan Walmsley 3 years ago
committed by GitHub
parent
commit
19adcd0d4b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 18
      src/Avalonia.Base/StyledElement.cs
  2. 2
      src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs
  3. 12
      src/Avalonia.Controls/Flyouts/Flyout.cs
  4. 3
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs
  5. 9
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs
  6. 46
      src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXAmlIlClassesTransformer.cs
  7. 32
      tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs

18
src/Avalonia.Base/StyledElement.cs

@ -78,7 +78,7 @@ namespace Avalonia
private static readonly ControlTheme s_invalidTheme = new ControlTheme();
private int _initCount;
private string? _name;
private readonly Classes _classes = new Classes();
private Classes? _classes;
private ILogicalRoot? _logicalRoot;
private IAvaloniaList<ILogical>? _logicalChildren;
private IResourceDictionary? _resources;
@ -183,21 +183,7 @@ namespace Avalonia
/// collection.
/// </para>
/// </remarks>
public Classes Classes
{
get
{
return _classes;
}
set
{
if (_classes != value)
{
_classes.Replace(value);
}
}
}
public Classes Classes => _classes ??= new();
/// <summary>
/// Gets or sets the control's data context.

2
src/Avalonia.Controls/DateTimePickers/DateTimePickerPanel.cs

@ -454,7 +454,7 @@ namespace Avalonia.Controls.Primitives
children.Add(new ListBoxItem
{
Height = ItemHeight,
Classes = new Classes($"{PanelType}Item"),
Classes = { $"{PanelType}Item" },
VerticalContentAlignment = Avalonia.Layout.VerticalAlignment.Center,
Focusable = false
});

12
src/Avalonia.Controls/Flyouts/Flyout.cs

@ -18,17 +18,7 @@ namespace Avalonia.Controls
/// <summary>
/// Gets the Classes collection to apply to the FlyoutPresenter this Flyout is hosting
/// </summary>
public Classes FlyoutPresenterClasses
{
get => _classes ??= new Classes();
set
{
if (_classes is null)
_classes = value;
else if (_classes != value)
_classes.Replace(value);
}
}
public Classes FlyoutPresenterClasses => _classes ??= new Classes();
/// <summary>
/// Defines the <see cref="FlyoutPresenterTheme"/> property.

3
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlCompiler.cs

@ -43,7 +43,8 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
new AvaloniaXamlIlTransformSyntheticCompiledBindingMembers());
InsertAfter<PropertyReferenceResolver>(
new AvaloniaXamlIlAvaloniaPropertyResolver(),
new AvaloniaXamlIlReorderClassesPropertiesTransformer()
new AvaloniaXamlIlReorderClassesPropertiesTransformer(),
new AvaloniaXamlIlClassesTransformer()
);
InsertBefore<ContentConvertTransformer>(

9
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/AvaloniaXamlIlLanguageParseIntrinsics.cs

@ -221,15 +221,6 @@ namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions
return ConvertDefinitionList(node, text, types, types.RowDefinitions, types.RowDefinition, "row definitions", out result);
}
if (type.Equals(types.Classes))
{
var classes = text.Split(' ');
var classNodes = classes.Select(c => new XamlAstTextNode(node, c, type: types.XamlIlTypes.String)).ToArray();
result = new AvaloniaXamlIlAvaloniaListConstantAstNode(node, types, types.Classes, types.XamlIlTypes.String, classNodes);
return true;
}
if (types.IBrush.IsAssignableFrom(type))
{
if (Color.TryParse(text, out Color color))

46
src/Markup/Avalonia.Markup.Xaml.Loader/CompilerExtensions/Transformers/AvaloniaXAmlIlClassesTransformer.cs

@ -0,0 +1,46 @@
using System.Linq;
using XamlX.Ast;
using XamlX.Transform;
namespace Avalonia.Markup.Xaml.XamlIl.CompilerExtensions.Transformers
{
/// <summary>
/// Converts an attribute syntax property value assignment to a collection syntax property
/// assignment.
/// </summary>
/// <remarks>
/// Converts the property assignment `Classes="foo bar"` to:
///
/// <code>
/// <StyledElement.Classes>
/// <x:String>foo</String>
/// <x:String>bar</String>
/// </StyledElement.Classes>
/// </code>
/// </remarks>
class AvaloniaXamlIlClassesTransformer : IXamlAstTransformer
{
public IXamlAstNode Transform(AstTransformationContext context, IXamlAstNode node)
{
var types = context.GetAvaloniaTypes();
if (node is XamlAstXamlPropertyValueNode propertyValue &&
propertyValue.IsAttributeSyntax &&
propertyValue.Property is XamlAstClrProperty property &&
property.Getter?.ReturnType.Equals(types.Classes) == true &&
propertyValue.Values.Count == 1 &&
propertyValue.Values[0] is XamlAstTextNode value)
{
var classes = value.Text.Split(' ');
var stringType = context.Configuration.WellKnownTypes.String;
return new XamlAstXamlPropertyValueNode(
node,
property,
classes.Select(x => new XamlAstTextNode(node, x, type: stringType)),
false);
}
return node;
}
}
}

32
tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs

@ -1,24 +1,20 @@
using System;
using System.Collections;
using System.ComponentModel;
using System.Linq;
using System.Xml;
using Avalonia.Collections;
using Avalonia.Controls;
using Avalonia.Controls.Documents;
using Avalonia.Controls.Presenters;
using Avalonia.Data;
using Avalonia.Data.Converters;
using Avalonia.Markup.Data;
using Avalonia.Markup.Xaml.Styling;
using Avalonia.Markup.Xaml.Templates;
using Avalonia.Media;
using Avalonia.Media.Immutable;
using Avalonia.Metadata;
using Avalonia.Styling;
using Avalonia.UnitTests;
using System.Collections;
using System.ComponentModel;
using System.Linq;
using System.Xml;
using Xunit;
using Avalonia.Controls.Documents;
using Avalonia.Metadata;
using Avalonia.Themes.Simple;
namespace Avalonia.Markup.Xaml.UnitTests.Xaml
{
@ -920,6 +916,22 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml
Assert.Equal(new[] { "foo", "bar" }, target.Classes);
}
[Fact]
public void Can_Specify_Button_Classes_Longform()
{
var xaml = @"
<Button xmlns='https://github.com/avaloniaui'
xmlns:x='http://schemas.microsoft.com/winfx/2006/xaml'>
<Button.Classes>
<x:String>foo</x:String>
<x:String>bar</x:String>
</Button.Classes>
</Button>";
var target = (Button)AvaloniaRuntimeXamlLoader.Load(xaml);
Assert.Equal(new[] { "foo", "bar" }, target.Classes);
}
[Fact]
public void Can_Specify_Flyout_FlyoutPresenterClasses()
{

Loading…
Cancel
Save