diff --git a/src/Avalonia.Base/PropertyStore/ValueStore.cs b/src/Avalonia.Base/PropertyStore/ValueStore.cs index 8790991182..d858e30212 100644 --- a/src/Avalonia.Base/PropertyStore/ValueStore.cs +++ b/src/Avalonia.Base/PropertyStore/ValueStore.cs @@ -610,8 +610,7 @@ namespace Avalonia.PropertyStore private int InsertFrame(ValueFrame frame) { - // Uncomment this line when #8549 is fixed. - //Debug.Assert(!_frames.Contains(frame)); + Debug.Assert(!_frames.Contains(frame)); var index = BinarySearchFrame(frame.Priority); _frames.Insert(index, frame); diff --git a/src/Avalonia.Base/StyledElement.cs b/src/Avalonia.Base/StyledElement.cs index bba9685ed8..c72f398fd9 100644 --- a/src/Avalonia.Base/StyledElement.cs +++ b/src/Avalonia.Base/StyledElement.cs @@ -344,29 +344,30 @@ namespace Avalonia /// Applies styling to the control if the control is initialized and styling is not /// already applied. /// + /// + /// The styling system will automatically apply styling when required, so it should not + /// usually be necessary to call this method manually. + /// /// /// A value indicating whether styling is now applied to the control. /// - protected bool ApplyStyling() + public bool ApplyStyling() { if (_initCount == 0 && !_styled) { - var styler = AvaloniaLocator.Current.GetService(); var hasPromotedTheme = _hasPromotedTheme; - if (styler is object) - { - GetValueStore().BeginStyling(); + GetValueStore().BeginStyling(); - try - { - styler.ApplyStyles(this); - } - finally - { - _styled = true; - GetValueStore().EndStyling(); - } + try + { + ApplyControlTheme(); + ApplyStyles(this); + } + finally + { + _styled = true; + GetValueStore().EndStyling(); } if (hasPromotedTheme) @@ -505,31 +506,6 @@ namespace Avalonia }; } - ControlTheme? IStyleable.GetEffectiveTheme() - { - var theme = Theme; - - // Explitly set Theme property takes precedence. - if (theme is not null) - return theme; - - // If the Theme property is not set, try to find a ControlTheme resource with our StyleKey. - if (_implicitTheme is null) - { - var key = ((IStyleable)this).StyleKey; - - if (this.TryFindResource(key, out var value) && value is ControlTheme t) - _implicitTheme = t; - else - _implicitTheme = s_invalidTheme; - } - - if (_implicitTheme != s_invalidTheme) - return _implicitTheme; - - return null; - } - void IStyleable.DetachStyles() => DetachStyles(); void IStyleHost.StylesAdded(IReadOnlyList styles) @@ -666,6 +642,31 @@ namespace Avalonia { } + internal ControlTheme? GetEffectiveTheme() + { + var theme = Theme; + + // Explitly set Theme property takes precedence. + if (theme is not null) + return theme; + + // If the Theme property is not set, try to find a ControlTheme resource with our StyleKey. + if (_implicitTheme is null) + { + var key = ((IStyleable)this).StyleKey; + + if (this.TryFindResource(key, out var value) && value is ControlTheme t) + _implicitTheme = t; + else + _implicitTheme = s_invalidTheme; + } + + if (_implicitTheme != s_invalidTheme) + return _implicitTheme; + + return null; + } + private static void DataContextNotifying(IAvaloniaObject o, bool updateStarted) { if (o is StyledElement element) @@ -730,6 +731,56 @@ namespace Avalonia } } + private void ApplyControlTheme() + { + var theme = GetEffectiveTheme(); + + if (theme is not null) + ApplyControlTheme(theme); + + if (TemplatedParent is StyledElement styleableParent && + styleableParent.GetEffectiveTheme() is { } parentTheme) + { + ApplyControlTheme(parentTheme); + } + } + + private void ApplyControlTheme(ControlTheme theme) + { + if (theme.BasedOn is ControlTheme basedOn) + ApplyControlTheme(basedOn); + + theme.TryAttach(this, null); + + if (theme.HasChildren) + { + foreach (var child in theme.Children) + ApplyStyle(child, null); + } + } + + private void ApplyStyles(IStyleHost host) + { + var parent = host.StylingParent; + if (parent != null) + ApplyStyles(parent); + + if (host.IsStylesInitialized) + { + foreach (var style in host.Styles) + ApplyStyle(style, host); + } + } + + private void ApplyStyle(IStyle style, IStyleHost? host) + { + if (style is Style s) + s.TryAttach(this, host); + + foreach (var child in style.Children) + ApplyStyle(child, host); + } + private void OnAttachedToLogicalTreeCore(LogicalTreeAttachmentEventArgs e) { if (this.GetLogicalParent() == null && !(this is ILogicalRoot)) diff --git a/src/Avalonia.Base/Styling/ControlTheme.cs b/src/Avalonia.Base/Styling/ControlTheme.cs index 46a3267f70..2971703c95 100644 --- a/src/Avalonia.Base/Styling/ControlTheme.cs +++ b/src/Avalonia.Base/Styling/ControlTheme.cs @@ -29,34 +29,27 @@ namespace Avalonia.Styling /// public ControlTheme? BasedOn { get; set; } - public override SelectorMatchResult TryAttach(IStyleable target, object? host) + public override string ToString() => TargetType?.Name ?? "ControlTheme"; + + internal override void SetParent(StyleBase? parent) + { + throw new InvalidOperationException("ControlThemes cannot be added as a nested style."); + } + + internal override SelectorMatchResult TryAttach(IStyleable target, object? host) { _ = target ?? throw new ArgumentNullException(nameof(target)); if (TargetType is null) throw new InvalidOperationException("ControlTheme has no TargetType."); - var result = BasedOn?.TryAttach(target, host) ?? SelectorMatchResult.NeverThisType; - if (HasSettersOrAnimations && TargetType.IsAssignableFrom(target.StyleKey)) { Attach(target, null); - result = SelectorMatchResult.AlwaysThisType; + return SelectorMatchResult.AlwaysThisType; } - var childResult = TryAttachChildren(target, host); - - if (childResult > result) - result = childResult; - - return result; - } - - public override string ToString() => TargetType?.Name ?? "ControlTheme"; - - internal override void SetParent(StyleBase? parent) - { - throw new InvalidOperationException("ControlThemes cannot be added as a nested style."); + return SelectorMatchResult.NeverThisType; } } } diff --git a/src/Avalonia.Base/Styling/IStyle.cs b/src/Avalonia.Base/Styling/IStyle.cs index 417739fb28..2dbaf963ee 100644 --- a/src/Avalonia.Base/Styling/IStyle.cs +++ b/src/Avalonia.Base/Styling/IStyle.cs @@ -14,15 +14,5 @@ namespace Avalonia.Styling /// Gets a collection of child styles. /// IReadOnlyList Children { get; } - - /// - /// Attaches the style and any child styles to a control if the style's selector matches. - /// - /// The control to attach to. - /// The element that hosts the style. - /// - /// A describing how the style matches the control. - /// - SelectorMatchResult TryAttach(IStyleable target, object? host); } } diff --git a/src/Avalonia.Base/Styling/IStyleable.cs b/src/Avalonia.Base/Styling/IStyleable.cs index e94fc5c4e6..dcc3988280 100644 --- a/src/Avalonia.Base/Styling/IStyleable.cs +++ b/src/Avalonia.Base/Styling/IStyleable.cs @@ -25,11 +25,6 @@ namespace Avalonia.Styling /// ITemplatedControl? TemplatedParent { get; } - /// - /// Gets the effective theme for the control as used by the syling system. - /// - ControlTheme? GetEffectiveTheme(); - void DetachStyles(); } } diff --git a/src/Avalonia.Base/Styling/IStyler.cs b/src/Avalonia.Base/Styling/IStyler.cs deleted file mode 100644 index d6477d169e..0000000000 --- a/src/Avalonia.Base/Styling/IStyler.cs +++ /dev/null @@ -1,8 +0,0 @@ - -namespace Avalonia.Styling -{ - public interface IStyler - { - void ApplyStyles(IStyleable control); - } -} diff --git a/src/Avalonia.Base/Styling/Style.cs b/src/Avalonia.Base/Styling/Style.cs index 913c437bc4..aad91824d3 100644 --- a/src/Avalonia.Base/Styling/Style.cs +++ b/src/Avalonia.Base/Styling/Style.cs @@ -1,5 +1,4 @@ using System; -using Avalonia.PropertyStore; namespace Avalonia.Styling { @@ -35,35 +34,6 @@ namespace Avalonia.Styling set => _selector = ValidateSelector(value); } - public override SelectorMatchResult TryAttach(IStyleable target, object? host) - { - _ = target ?? throw new ArgumentNullException(nameof(target)); - - var result = SelectorMatchResult.NeverThisType; - - if (HasSettersOrAnimations) - { - var match = Selector?.Match(target, Parent, true) ?? - (target == host ? - SelectorMatch.AlwaysThisInstance : - SelectorMatch.NeverThisInstance); - - if (match.IsMatch) - { - Attach(target, match.Activator); - } - - result = match.Result; - } - - var childResult = TryAttachChildren(target, host); - - if (childResult > result) - result = childResult; - - return result; - } - /// /// Returns a string representation of the style. /// @@ -88,6 +58,30 @@ namespace Avalonia.Styling base.SetParent(parent); } + internal override SelectorMatchResult TryAttach(IStyleable target, object? host) + { + _ = target ?? throw new ArgumentNullException(nameof(target)); + + var result = SelectorMatchResult.NeverThisType; + + if (HasSettersOrAnimations) + { + var match = Selector?.Match(target, Parent, true) ?? + (target == host ? + SelectorMatch.AlwaysThisInstance : + SelectorMatch.NeverThisInstance); + + if (match.IsMatch) + { + Attach(target, match.Activator); + } + + result = match.Result; + } + + return result; + } + private static Selector? ValidateSelector(Selector? selector) { if (selector is TemplateSelector) diff --git a/src/Avalonia.Base/Styling/StyleBase.cs b/src/Avalonia.Base/Styling/StyleBase.cs index c914fbf8cc..dba80df2e5 100644 --- a/src/Avalonia.Base/Styling/StyleBase.cs +++ b/src/Avalonia.Base/Styling/StyleBase.cs @@ -18,7 +18,6 @@ namespace Avalonia.Styling private IResourceDictionary? _resources; private List? _setters; private List? _animations; - private StyleCache? _childCache; private StyleInstance? _sharedInstance; public IList Children => _children ??= new(this); @@ -67,6 +66,7 @@ namespace Avalonia.Styling bool IResourceNode.HasResources => _resources?.Count > 0; IReadOnlyList IStyle.Children => (IReadOnlyList?)_children ?? Array.Empty(); + internal bool HasChildren => _children?.Count > 0; internal bool HasSettersOrAnimations => _setters?.Count > 0 || _animations?.Count > 0; public void Add(ISetter setter) => Setters.Add(setter); @@ -74,14 +74,26 @@ namespace Avalonia.Styling public event EventHandler? OwnerChanged; - public abstract SelectorMatchResult TryAttach(IStyleable target, object? host); - public bool TryGetResource(object key, out object? result) { - result = null; - return _resources?.TryGetResource(key, out result) ?? false; + if (_resources is not null && _resources.TryGetResource(key, out result)) + return true; + + if (_children is not null) + { + for (var i = 0; i < _children.Count; ++i) + { + if (_children[i].TryGetResource(key, out result)) + return true; + } + } + + result= null; + return false; } + internal abstract SelectorMatchResult TryAttach(IStyleable target, object? host); + internal ValueFrame Attach(IStyleable target, IStyleActivator? activator) { if (target is not AvaloniaObject ao) @@ -124,14 +136,6 @@ namespace Avalonia.Styling return instance; } - internal SelectorMatchResult TryAttachChildren(IStyleable target, object? host) - { - if (_children is null || _children.Count == 0) - return SelectorMatchResult.NeverThisType; - _childCache ??= new StyleCache(); - return _childCache.TryAttach(_children, target, host); - } - internal virtual void SetParent(StyleBase? parent) => Parent = parent; void IResourceProvider.AddOwner(IResourceHost owner) diff --git a/src/Avalonia.Base/Styling/StyleCache.cs b/src/Avalonia.Base/Styling/StyleCache.cs deleted file mode 100644 index 81196f6a27..0000000000 --- a/src/Avalonia.Base/Styling/StyleCache.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Avalonia.Styling -{ - /// - /// Simple cache for improving performance of applying styles. - /// - /// - /// Maps to a list of styles that are known be be possible - /// matches. - /// - internal class StyleCache : Dictionary?> - { - public SelectorMatchResult TryAttach(IList styles, IStyleable target, object? host) - { - if (TryGetValue(target.StyleKey, out var cached)) - { - if (cached is object) - { - var result = SelectorMatchResult.NeverThisType; - - foreach (var style in cached) - { - var childResult = style.TryAttach(target, host); - if (childResult > result) - result = childResult; - } - - return result; - } - else - { - return SelectorMatchResult.NeverThisType; - } - } - else - { - List? matches = null; - - foreach (var child in styles) - { - if (child.TryAttach(target, host) != SelectorMatchResult.NeverThisType) - { - matches ??= new List(); - matches.Add(child); - } - } - - Add(target.StyleKey, matches); - - return matches is null ? - SelectorMatchResult.NeverThisType : - SelectorMatchResult.AlwaysThisType; - } - } - } -} diff --git a/src/Avalonia.Base/Styling/Styler.cs b/src/Avalonia.Base/Styling/Styler.cs deleted file mode 100644 index ad5c1cd102..0000000000 --- a/src/Avalonia.Base/Styling/Styler.cs +++ /dev/null @@ -1,35 +0,0 @@ -using System; - -namespace Avalonia.Styling -{ - public class Styler : IStyler - { - public void ApplyStyles(IStyleable target) - { - _ = target ?? throw new ArgumentNullException(nameof(target)); - - // Apply the control theme. - target.GetEffectiveTheme()?.TryAttach(target, target); - - // If the control has a themed templated parent then apply the styles from the - // templated parent theme. - if (target.TemplatedParent is IStyleable styleableParent) - styleableParent.GetEffectiveTheme()?.TryAttach(target, styleableParent); - - // Apply styles from the rest of the tree. - if (target is IStyleHost styleHost) - ApplyStyles(target, styleHost); - } - - private void ApplyStyles(IStyleable target, IStyleHost host) - { - var parent = host.StylingParent; - - if (parent != null) - ApplyStyles(target, parent); - - if (host.IsStylesInitialized) - host.Styles.TryAttach(target, host); - } - } -} diff --git a/src/Avalonia.Base/Styling/Styles.cs b/src/Avalonia.Base/Styling/Styles.cs index c213475bb7..76271b9748 100644 --- a/src/Avalonia.Base/Styling/Styles.cs +++ b/src/Avalonia.Base/Styling/Styles.cs @@ -5,8 +5,6 @@ using System.Collections.Specialized; using Avalonia.Collections; using Avalonia.Controls; -#nullable enable - namespace Avalonia.Styling { /// @@ -20,7 +18,6 @@ namespace Avalonia.Styling private readonly AvaloniaList _styles = new(); private IResourceHost? _owner; private IResourceDictionary? _resources; - private StyleCache? _cache; public Styles() { @@ -116,12 +113,6 @@ namespace Avalonia.Styling set => _styles[index] = value; } - public SelectorMatchResult TryAttach(IStyleable target, object? host) - { - _cache ??= new StyleCache(); - return _cache.TryAttach(this, target, host); - } - /// public bool TryGetResource(object key, out object? value) { @@ -234,6 +225,22 @@ namespace Avalonia.Styling } } + internal SelectorMatchResult TryAttach(IStyleable target, object? host) + { + var result = SelectorMatchResult.NeverThisType; + + foreach (var s in this) + { + if (s is not Style style) + continue; + var r = style.TryAttach(target, host); + if (r > result) + result = r; + } + + return result; + } + private static IReadOnlyList ToReadOnlyList(ICollection list) { if (list is IReadOnlyList readOnlyList) @@ -246,7 +253,7 @@ namespace Avalonia.Styling return result; } - private static void InternalAdd(IList items, IResourceHost? owner, ref StyleCache? cache) + private static void InternalAdd(IList items, IResourceHost? owner) { if (owner is not null) { @@ -260,14 +267,9 @@ namespace Avalonia.Styling (owner as IStyleHost)?.StylesAdded(ToReadOnlyList(items)); } - - if (items.Count > 0) - { - cache = null; - } } - private static void InternalRemove(IList items, IResourceHost? owner, ref StyleCache? cache) + private static void InternalRemove(IList items, IResourceHost? owner) { if (owner is not null) { @@ -281,11 +283,6 @@ namespace Avalonia.Styling (owner as IStyleHost)?.StylesRemoved(ToReadOnlyList(items)); } - - if (items.Count > 0) - { - cache = null; - } } private void OnCollectionChanged(object? sender, NotifyCollectionChangedEventArgs e) @@ -300,14 +297,14 @@ namespace Avalonia.Styling switch (e.Action) { case NotifyCollectionChangedAction.Add: - InternalAdd(e.NewItems!, currentOwner, ref _cache); + InternalAdd(e.NewItems!, currentOwner); break; case NotifyCollectionChangedAction.Remove: - InternalRemove(e.OldItems!, currentOwner, ref _cache); + InternalRemove(e.OldItems!, currentOwner); break; case NotifyCollectionChangedAction.Replace: - InternalRemove(e.OldItems!, currentOwner, ref _cache); - InternalAdd(e.NewItems!, currentOwner, ref _cache); + InternalRemove(e.OldItems!, currentOwner); + InternalAdd(e.NewItems!, currentOwner); break; } diff --git a/src/Avalonia.Controls/Application.cs b/src/Avalonia.Controls/Application.cs index 69fd6cabf8..dc9a0207ad 100644 --- a/src/Avalonia.Controls/Application.cs +++ b/src/Avalonia.Controls/Application.cs @@ -39,7 +39,6 @@ namespace Avalonia private readonly Lazy _clipboard = new Lazy(() => (IClipboard?)AvaloniaLocator.Current.GetService(typeof(IClipboard))); - private readonly Styler _styler = new Styler(); private Styles? _styles; private IResourceDictionary? _resources; private bool _notifyingResourcesChanged; @@ -232,7 +231,6 @@ namespace Avalonia .Bind().ToConstant(FocusManager) .Bind().ToConstant(InputManager) .Bind().ToTransient() - .Bind().ToConstant(_styler) .Bind().ToConstant(AvaloniaScheduler.Instance) .Bind().ToConstant(DragDropDevice.Instance); diff --git a/src/Avalonia.Controls/TopLevel.cs b/src/Avalonia.Controls/TopLevel.cs index 6804c9ecb9..90af881adc 100644 --- a/src/Avalonia.Controls/TopLevel.cs +++ b/src/Avalonia.Controls/TopLevel.cs @@ -145,7 +145,6 @@ namespace Avalonia.Controls _actualTransparencyLevel = PlatformImpl.TransparencyLevel; dependencyResolver = dependencyResolver ?? AvaloniaLocator.Current; - var styler = TryGetService(dependencyResolver); _accessKeyHandler = TryGetService(dependencyResolver); _inputManager = TryGetService(dependencyResolver); @@ -183,8 +182,6 @@ namespace Avalonia.Controls _globalStyles.GlobalStylesRemoved += ((IStyleHost)this).StylesRemoved; } - styler?.ApplyStyles(this); - ClientSize = impl.ClientSize; FrameSize = impl.FrameSize; diff --git a/src/Avalonia.Controls/Window.cs b/src/Avalonia.Controls/Window.cs index 1a7dca737e..559d674c02 100644 --- a/src/Avalonia.Controls/Window.cs +++ b/src/Avalonia.Controls/Window.cs @@ -647,6 +647,7 @@ namespace Avalonia.Controls RaiseEvent(new RoutedEventArgs(WindowOpenedEvent)); EnsureInitialized(); + ApplyStyling(); IsVisible = true; var initialSize = new Size( @@ -726,6 +727,7 @@ namespace Avalonia.Controls RaiseEvent(new RoutedEventArgs(WindowOpenedEvent)); EnsureInitialized(); + ApplyStyling(); IsVisible = true; var initialSize = new Size( diff --git a/src/Avalonia.Controls/WindowBase.cs b/src/Avalonia.Controls/WindowBase.cs index 89483cd566..8f1b2198ad 100644 --- a/src/Avalonia.Controls/WindowBase.cs +++ b/src/Avalonia.Controls/WindowBase.cs @@ -149,6 +149,7 @@ namespace Avalonia.Controls try { EnsureInitialized(); + ApplyStyling(); IsVisible = true; if (!_hasExecutedInitialLayoutPass) diff --git a/src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs b/src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs index b1725245bb..8af49b5480 100644 --- a/src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs +++ b/src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs @@ -82,8 +82,6 @@ namespace Avalonia.Markup.Xaml.Styling } } - public SelectorMatchResult TryAttach(IStyleable target, object? host) => Loaded.TryAttach(target, host); - public bool TryGetResource(object key, out object? value) { if (!_isLoading) diff --git a/tests/Avalonia.Base.UnitTests/Animation/AnimatableTests.cs b/tests/Avalonia.Base.UnitTests/Animation/AnimatableTests.cs index 19ae0dc260..668b8a875c 100644 --- a/tests/Avalonia.Base.UnitTests/Animation/AnimatableTests.cs +++ b/tests/Avalonia.Base.UnitTests/Animation/AnimatableTests.cs @@ -498,7 +498,7 @@ namespace Avalonia.Base.UnitTests.Animation private static IDisposable Start() { var clock = new MockGlobalClock(); - var services = TestServices.RealStyler.With(globalClock: clock); + var services = new TestServices(globalClock: clock); return UnitTestApplication.Start(services); } diff --git a/tests/Avalonia.Base.UnitTests/Styling/StyleTests.cs b/tests/Avalonia.Base.UnitTests/Styling/StyleTests.cs index b7455f9b3f..e7ecba61a7 100644 --- a/tests/Avalonia.Base.UnitTests/Styling/StyleTests.cs +++ b/tests/Avalonia.Base.UnitTests/Styling/StyleTests.cs @@ -5,7 +5,6 @@ using Avalonia.Base.UnitTests.Animation; using Avalonia.Controls; using Avalonia.Controls.Templates; using Avalonia.Data; -using Avalonia.Diagnostics; using Avalonia.Styling; using Avalonia.UnitTests; using Moq; @@ -301,8 +300,6 @@ namespace Avalonia.Base.UnitTests.Styling [Fact] public void Inactive_Values_Should_Not_Be_Made_Active_During_Style_Attach() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); - var root = new TestRoot { Styles = @@ -337,8 +334,6 @@ namespace Avalonia.Base.UnitTests.Styling [Fact] public void Inactive_Bindings_Should_Not_Be_Made_Active_During_Style_Attach() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); - var root = new TestRoot { Styles = @@ -380,8 +375,6 @@ namespace Avalonia.Base.UnitTests.Styling [Fact] public void Inactive_Values_Should_Not_Be_Made_Active_During_Style_Detach() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); - var root = new TestRoot { Styles = @@ -417,8 +410,6 @@ namespace Avalonia.Base.UnitTests.Styling [Fact] public void Inactive_Values_Should_Not_Be_Made_Active_During_Style_Detach_2() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); - var root = new TestRoot { Styles = @@ -454,8 +445,6 @@ namespace Avalonia.Base.UnitTests.Styling [Fact] public void Inactive_Bindings_Should_Not_Be_Made_Active_During_Style_Detach() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); - var root = new TestRoot { Styles = @@ -598,41 +587,36 @@ namespace Avalonia.Base.UnitTests.Styling [Fact] public void Removing_Style_Should_Detach_From_Control() { - using (UnitTestApplication.Start(TestServices.RealStyler)) + var border = new Border(); + var root = new TestRoot { - var border = new Border(); - var root = new TestRoot - { - Styles = - { - new Style(x => x.OfType()) + Styles = + { + new Style(x => x.OfType()) + { + Setters = { - Setters = - { - new Setter(Border.BorderThicknessProperty, new Thickness(4)), - } + new Setter(Border.BorderThicknessProperty, new Thickness(4)), } - }, - Child = border, - }; + } + }, + Child = border, + }; - root.Measure(Size.Infinity); - Assert.Equal(new Thickness(4), border.BorderThickness); + root.Measure(Size.Infinity); + Assert.Equal(new Thickness(4), border.BorderThickness); - root.Styles.RemoveAt(0); - Assert.Equal(new Thickness(0), border.BorderThickness); - } + root.Styles.RemoveAt(0); + Assert.Equal(new Thickness(0), border.BorderThickness); } [Fact] public void Adding_Style_Should_Attach_To_Control() { - using (UnitTestApplication.Start(TestServices.RealStyler)) + var border = new Border(); + var root = new TestRoot { - var border = new Border(); - var root = new TestRoot - { - Styles = + Styles = { new Style(x => x.OfType()) { @@ -642,34 +626,31 @@ namespace Avalonia.Base.UnitTests.Styling } } }, - Child = border, - }; + Child = border, + }; - root.Measure(Size.Infinity); - Assert.Equal(new Thickness(4), border.BorderThickness); + root.Measure(Size.Infinity); + Assert.Equal(new Thickness(4), border.BorderThickness); - root.Styles.Add(new Style(x => x.OfType()) - { - Setters = + root.Styles.Add(new Style(x => x.OfType()) + { + Setters = { new Setter(Border.BorderThicknessProperty, new Thickness(6)), } - }); + }); - root.Measure(Size.Infinity); - Assert.Equal(new Thickness(6), border.BorderThickness); - } + root.Measure(Size.Infinity); + Assert.Equal(new Thickness(6), border.BorderThickness); } [Fact] public void Removing_Style_With_Nested_Style_Should_Detach_From_Control() { - using (UnitTestApplication.Start(TestServices.RealStyler)) + var border = new Border(); + var root = new TestRoot { - var border = new Border(); - var root = new TestRoot - { - Styles = + Styles = { new Styles { @@ -682,96 +663,89 @@ namespace Avalonia.Base.UnitTests.Styling } } }, - Child = border, - }; + Child = border, + }; - root.Measure(Size.Infinity); - Assert.Equal(new Thickness(4), border.BorderThickness); + root.Measure(Size.Infinity); + Assert.Equal(new Thickness(4), border.BorderThickness); - root.Styles.RemoveAt(0); - Assert.Equal(new Thickness(0), border.BorderThickness); - } + root.Styles.RemoveAt(0); + Assert.Equal(new Thickness(0), border.BorderThickness); } - + [Fact] public void Adding_Nested_Style_Should_Attach_To_Control() { - using (UnitTestApplication.Start(TestServices.RealStyler)) + var border = new Border(); + var root = new TestRoot { - var border = new Border(); - var root = new TestRoot + Styles = { - Styles = + new Styles { - new Styles + new Style(x => x.OfType()) { - new Style(x => x.OfType()) + Setters = { - Setters = - { - new Setter(Border.BorderThicknessProperty, new Thickness(4)), - } + new Setter(Border.BorderThicknessProperty, new Thickness(4)), } } - }, - Child = border, - }; + } + }, + Child = border, + }; - root.Measure(Size.Infinity); - Assert.Equal(new Thickness(4), border.BorderThickness); + root.Measure(Size.Infinity); + Assert.Equal(new Thickness(4), border.BorderThickness); - ((Styles)root.Styles[0]).Add(new Style(x => x.OfType()) + ((Styles)root.Styles[0]).Add(new Style(x => x.OfType()) + { + Setters = { - Setters = - { - new Setter(Border.BorderThicknessProperty, new Thickness(6)), - } - }); + new Setter(Border.BorderThicknessProperty, new Thickness(6)), + } + }); - root.Measure(Size.Infinity); - Assert.Equal(new Thickness(6), border.BorderThickness); - } + root.Measure(Size.Infinity); + Assert.Equal(new Thickness(6), border.BorderThickness); } [Fact] public void Removing_Nested_Style_Should_Detach_From_Control() { - using (UnitTestApplication.Start(TestServices.RealStyler)) + var border = new Border(); + var root = new TestRoot { - var border = new Border(); - var root = new TestRoot + Styles = { - Styles = + new Styles { - new Styles + new Style(x => x.OfType()) { - new Style(x => x.OfType()) + Setters = { - Setters = - { - new Setter(Border.BorderThicknessProperty, new Thickness(4)), - } - }, - new Style(x => x.OfType()) + new Setter(Border.BorderThicknessProperty, new Thickness(4)), + } + }, + new Style(x => x.OfType()) + { + Setters = { - Setters = - { - new Setter(Border.BorderThicknessProperty, new Thickness(6)), - } - }, - } - }, - Child = border, - }; + new Setter(Border.BorderThicknessProperty, new Thickness(6)), + } + }, + } + }, + Child = border, + }; - root.Measure(Size.Infinity); - Assert.Equal(new Thickness(6), border.BorderThickness); + root.Measure(Size.Infinity); + Assert.Equal(new Thickness(6), border.BorderThickness); - ((Styles)root.Styles[0]).RemoveAt(1); + ((Styles)root.Styles[0]).RemoveAt(1); - root.Measure(Size.Infinity); - Assert.Equal(new Thickness(4), border.BorderThickness); - } + root.Measure(Size.Infinity); + Assert.Equal(new Thickness(4), border.BorderThickness); } [Fact] diff --git a/tests/Avalonia.Base.UnitTests/Styling/StyledElementTests.cs b/tests/Avalonia.Base.UnitTests/Styling/StyledElementTests.cs index c01e22347b..65fe50b545 100644 --- a/tests/Avalonia.Base.UnitTests/Styling/StyledElementTests.cs +++ b/tests/Avalonia.Base.UnitTests/Styling/StyledElementTests.cs @@ -249,65 +249,67 @@ namespace Avalonia.Base.UnitTests.Styling } [Fact] - public void Adding_Tree_To_IStyleRoot_Should_Style_Controls() + public void Adding_Tree_To_Root_Should_Style_Controls() { - using (AvaloniaLocator.EnterScope()) + var root = new TestRoot { - var root = new TestRoot(); - var parent = new Border(); - var child = new Border(); - var grandchild = new Control(); - var styler = new Mock(); - - AvaloniaLocator.CurrentMutable.Bind().ToConstant(styler.Object); + Styles = + { + new Style(x => x.Is()) + { + Setters = { new Setter(Control.TagProperty, "foo") } + } + } + }; - parent.Child = child; - child.Child = grandchild; + var grandchild = new Control(); + var child = new Border { Child = grandchild }; + var parent = new Border { Child = child }; - styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Never()); + Assert.Null(parent.Tag); + Assert.Null(child.Tag); + Assert.Null(grandchild.Tag); - root.Child = parent; + root.Child = parent; - styler.Verify(x => x.ApplyStyles(parent), Times.Once()); - styler.Verify(x => x.ApplyStyles(child), Times.Once()); - styler.Verify(x => x.ApplyStyles(grandchild), Times.Once()); - } + Assert.Equal("foo", parent.Tag); + Assert.Equal("foo", child.Tag); + Assert.Equal("foo", grandchild.Tag); } [Fact] public void Styles_Not_Applied_Until_Initialization_Finished() { - using (AvaloniaLocator.EnterScope()) + var root = new TestRoot { - var root = new TestRoot(); - var child = new Border(); - var styler = new Mock(); + Styles = + { + new Style(x => x.Is()) + { + Setters = { new Setter(Control.TagProperty, "foo") } + } + } + }; - AvaloniaLocator.CurrentMutable.Bind().ToConstant(styler.Object); + var child = new Border(); - ((ISupportInitialize)child).BeginInit(); - root.Child = child; - styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Never()); + ((ISupportInitialize)child).BeginInit(); + root.Child = child; + Assert.Null(child.Tag); - ((ISupportInitialize)child).EndInit(); - styler.Verify(x => x.ApplyStyles(child), Times.Once()); - } + ((ISupportInitialize)child).EndInit(); + Assert.Equal("foo", child.Tag); } [Fact] public void Name_Cannot_Be_Set_After_Added_To_Logical_Tree() { - using (AvaloniaLocator.EnterScope()) - { - var root = new TestRoot(); - var child = new Border(); - - AvaloniaLocator.CurrentMutable.BindToSelf(new Styler()); + var root = new TestRoot(); + var child = new Border(); - root.Child = child; + root.Child = child; - Assert.Throws(() => child.Name = "foo"); - } + Assert.Throws(() => child.Name = "foo"); } [Fact] @@ -328,7 +330,7 @@ namespace Avalonia.Base.UnitTests.Styling [Fact] public void Style_Is_Removed_When_Control_Removed_From_Logical_Tree() { - var app = UnitTestApplication.Start(TestServices.RealStyler); + var app = UnitTestApplication.Start(); var target = new Border(); var root = new TestRoot { diff --git a/tests/Avalonia.Base.UnitTests/Styling/StyledElementTests_Theming.cs b/tests/Avalonia.Base.UnitTests/Styling/StyledElementTests_Theming.cs index 45188de6cb..a1dac931ce 100644 --- a/tests/Avalonia.Base.UnitTests/Styling/StyledElementTests_Theming.cs +++ b/tests/Avalonia.Base.UnitTests/Styling/StyledElementTests_Theming.cs @@ -19,7 +19,6 @@ public class StyledElementTests_Theming [Fact] public void Theme_Is_Applied_When_Attached_To_Logical_Tree() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); var target = CreateTarget(); Assert.Null(target.Template); @@ -37,7 +36,6 @@ public class StyledElementTests_Theming [Fact] public void Theme_Is_Applied_To_Derived_Class_When_Attached_To_Logical_Tree() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); var target = new DerivedThemedControl { Theme = CreateTheme(), @@ -58,7 +56,6 @@ public class StyledElementTests_Theming [Fact] public void Theme_Is_Detached_When_Theme_Property_Cleared() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); var target = CreateTarget(); var root = CreateRoot(target); @@ -71,8 +68,6 @@ public class StyledElementTests_Theming [Fact] public void Theme_Is_Detached_From_Template_Controls_When_Theme_Property_Cleared() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); - var theme = new ControlTheme { TargetType = typeof(ThemedControl), @@ -105,7 +100,6 @@ public class StyledElementTests_Theming [Fact] public void Theme_Is_Applied_On_Layout_After_Theme_Property_Changes() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); var target = new ThemedControl(); var root = CreateRoot(target); @@ -124,7 +118,6 @@ public class StyledElementTests_Theming [Fact] public void BasedOn_Theme_Is_Applied_When_Attached_To_Logical_Tree() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); var target = CreateTarget(CreateDerivedTheme()); Assert.Null(target.Template); @@ -163,7 +156,6 @@ public class StyledElementTests_Theming [Fact] public void Implicit_Theme_Is_Applied_When_Attached_To_Logical_Tree() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); var target = CreateTarget(); var root = CreateRoot(target); Assert.NotNull(target.Template); @@ -178,21 +170,19 @@ public class StyledElementTests_Theming [Fact] public void Implicit_Theme_Is_Cleared_When_Removed_From_Logical_Tree() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); var target = CreateTarget(); var root = CreateRoot(target); - Assert.NotNull(((IStyleable)target).GetEffectiveTheme()); + Assert.NotNull(target.GetEffectiveTheme()); root.Child = null; - Assert.Null(((IStyleable)target).GetEffectiveTheme()); + Assert.Null(target.GetEffectiveTheme()); } [Fact] public void Nested_Style_Can_Override_Property_In_Inner_Templated_Control() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); var target = new ThemedControl2 { Theme = new ControlTheme(typeof(ThemedControl2)) @@ -236,7 +226,6 @@ public class StyledElementTests_Theming [Fact] public void Theme_Is_Applied_When_Attached_To_Logical_Tree() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); var target = CreateTarget(); Assert.Null(target.Theme); @@ -248,16 +237,15 @@ public class StyledElementTests_Theming Assert.NotNull(target.Template); var border = Assert.IsType(target.VisualChild); - Assert.Equal(border.Background, Brushes.Red); + Assert.Equal(Brushes.Red, border.Background); target.Classes.Add("foo"); - Assert.Equal(border.Background, Brushes.Green); + Assert.Equal(Brushes.Green, border.Background); } [Fact] public void Theme_Can_Be_Changed_By_Style_Class() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); var target = CreateTarget(); var theme1 = CreateTheme(); var theme2 = new ControlTheme(typeof(ThemedControl)); @@ -290,7 +278,6 @@ public class StyledElementTests_Theming [Fact] public void Theme_Can_Be_Set_To_LocalValue_While_Updating_Due_To_Style_Class() { - using var app = UnitTestApplication.Start(TestServices.RealStyler); var target = CreateTarget(); var theme1 = CreateTheme(); var theme2 = new ControlTheme(typeof(ThemedControl)); diff --git a/tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs b/tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs index b16e891924..59953f457a 100644 --- a/tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs +++ b/tests/Avalonia.Benchmarks/Styling/ResourceBenchmarks.cs @@ -22,7 +22,6 @@ namespace Avalonia.Benchmarks.Styling platform: new AppBuilder().RuntimePlatform, renderInterface: new MockPlatformRenderInterface(), standardCursorFactory: Mock.Of(), - styler: new Styler(), theme: () => CreateTheme(), threadingInterface: new NullThreadingPlatform(), fontManagerImpl: new MockFontManagerImpl(), diff --git a/tests/Avalonia.Benchmarks/Styling/StyleAttachBenchmark.cs b/tests/Avalonia.Benchmarks/Styling/StyleAttachBenchmark.cs deleted file mode 100644 index 7dad517e51..0000000000 --- a/tests/Avalonia.Benchmarks/Styling/StyleAttachBenchmark.cs +++ /dev/null @@ -1,47 +0,0 @@ -using System; -using System.Runtime.CompilerServices; -using Avalonia.Controls; -using Avalonia.Styling; -using Avalonia.UnitTests; -using BenchmarkDotNet.Attributes; - -namespace Avalonia.Benchmarks.Styling -{ - [MemoryDiagnoser] - public class StyleAttachBenchmark : IDisposable - { - private readonly IDisposable _app; - private readonly TestRoot _root; - private readonly TextBox _control; - - public StyleAttachBenchmark() - { - _app = UnitTestApplication.Start( - TestServices.StyledWindow.With( - renderInterface: new NullRenderingPlatform(), - threadingInterface: new NullThreadingPlatform())); - - _root = new TestRoot(true, null) - { - Renderer = new NullRenderer(), - }; - - _control = new TextBox(); - } - - [Benchmark] - [MethodImpl(MethodImplOptions.NoInlining)] - public void AttachTextBoxStyles() - { - var styles = UnitTestApplication.Current.Styles; - - styles.TryAttach(_control, UnitTestApplication.Current); - ((IStyleable)_control).DetachStyles(); - } - - public void Dispose() - { - _app.Dispose(); - } - } -} diff --git a/tests/Avalonia.Benchmarks/Styling/Style_Apply_Detach_Complex.cs b/tests/Avalonia.Benchmarks/Styling/Style_Apply_Detach_Complex.cs new file mode 100644 index 0000000000..fa8ad00bf8 --- /dev/null +++ b/tests/Avalonia.Benchmarks/Styling/Style_Apply_Detach_Complex.cs @@ -0,0 +1,126 @@ +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using Avalonia.Controls; +using Avalonia.Styling; +using Avalonia.UnitTests; +using BenchmarkDotNet.Attributes; + +namespace Avalonia.Benchmarks.Styling +{ + [MemoryDiagnoser] + public class Style_Apply_Detach_Complex : IDisposable + { + private readonly IDisposable _app; + private readonly TestRoot _root; + private readonly TextBox _control; + + public Style_Apply_Detach_Complex() + { + _app = UnitTestApplication.Start( + TestServices.StyledWindow.With( + renderInterface: new NullRenderingPlatform(), + threadingInterface: new NullThreadingPlatform())); + + // Simulate an application with a lot of styles by creating a tree of nested panels, + // each with a bunch of styles applied. + var (rootPanel, leafPanel) = CreateNestedPanels(10); + + // We're benchmarking how long it takes to apply styles to a TextBox in this situation. + _control = new TextBox(); + leafPanel.Children.Add(_control); + + _root = new TestRoot(true, rootPanel) + { + Renderer = new NullRenderer(), + }; + } + + [Benchmark] + [MethodImpl(MethodImplOptions.NoInlining)] + public void Apply_Detach_Styles() + { + // Styles will have already been attached when attached to the logical tree, so remove + // the styles first. + if ((string)_control.Tag != "TextBox") + throw new Exception("Invalid benchmark state"); + + ((IStyleable)_control).DetachStyles(); + + if (_control.Tag is not null) + throw new Exception("Invalid benchmark state"); + + // Then re-apply the styles. + _control.ApplyStyling(); + } + + public void Dispose() + { + _app.Dispose(); + } + + private static (Panel, Panel) CreateNestedPanels(int count) + { + var root = new Panel(); + var last = root; + + for (var i = 0; i < count; ++i) + { + var panel = new Panel(); + panel.Styles.AddRange(CreateStyles()); + last.Children.Add(panel); + last = panel; + } + + return (root, last); + } + + private static IEnumerable CreateStyles() + { + var types = new[] + { + typeof(Border), + typeof(Button), + typeof(ButtonSpinner), + typeof(Carousel), + typeof(CheckBox), + typeof(ComboBox), + typeof(ContentControl), + typeof(Expander), + typeof(ItemsControl), + typeof(Label), + typeof(ListBox), + typeof(ProgressBar), + typeof(RadioButton), + typeof(RepeatButton), + typeof(ScrollViewer), + typeof(Slider), + typeof(Spinner), + typeof(SplitView), + typeof(TextBox), + typeof(ToggleSwitch), + typeof(TreeView), + typeof(Viewbox), + typeof(Window), + }; + + foreach (var type in types) + { + yield return new Style(x => x.OfType(type)) + { + Setters = { new Setter(Control.TagProperty, type.Name) } + }; + + yield return new Style(x => x.OfType(type).Class("foo")) + { + Setters = { new Setter(Control.TagProperty, type.Name + " foo") } + }; + + yield return new Style(x => x.OfType(type).Class("bar")) + { + Setters = { new Setter(Control.TagProperty, type.Name + " bar") } + }; + } + } + } +} diff --git a/tests/Avalonia.Benchmarks/Themes/FluentBenchmark.cs b/tests/Avalonia.Benchmarks/Themes/FluentBenchmark.cs index ae874b8a61..1115bc9760 100644 --- a/tests/Avalonia.Benchmarks/Themes/FluentBenchmark.cs +++ b/tests/Avalonia.Benchmarks/Themes/FluentBenchmark.cs @@ -46,7 +46,6 @@ namespace Avalonia.Benchmarks.Themes platform: new AppBuilder().RuntimePlatform, renderInterface: new MockPlatformRenderInterface(), standardCursorFactory: Mock.Of(), - styler: new Styler(), theme: () => LoadFluentTheme(), threadingInterface: new NullThreadingPlatform(), fontManagerImpl: new MockFontManagerImpl(), diff --git a/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs b/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs index c8bd289e54..9d71e3bffc 100644 --- a/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/AutoCompleteBoxTests.cs @@ -1056,6 +1056,7 @@ namespace Avalonia.Controls.UnitTests control.Items = CreateSimpleStringArray(); TextBox textBox = GetTextBox(control); var window = new Window {Content = control}; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); Dispatcher.UIThread.RunJobs(); diff --git a/tests/Avalonia.Controls.UnitTests/ContentControlTests.cs b/tests/Avalonia.Controls.UnitTests/ContentControlTests.cs index 7cc0bae97f..1e37093736 100644 --- a/tests/Avalonia.Controls.UnitTests/ContentControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ContentControlTests.cs @@ -37,11 +37,19 @@ namespace Avalonia.Controls.UnitTests [Fact] public void Templated_Children_Should_Be_Styled() { - var root = new TestRoot(); + var root = new TestRoot + { + Styles = + { + new Style(x => x.Is()) + { + Setters = { new Setter(Control.TagProperty, "foo") } + } + } + }; + var target = new ContentControl(); - var styler = new Mock(); - AvaloniaLocator.CurrentMutable.Bind().ToConstant(styler.Object); target.Content = "Foo"; target.Template = GetTemplate(); root.Child = target; @@ -49,10 +57,8 @@ namespace Avalonia.Controls.UnitTests target.ApplyTemplate(); target.Presenter.ApplyTemplate(); - styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once()); - styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once()); - styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once()); - styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once()); + foreach (Control child in target.GetTemplateChildren()) + Assert.Equal("foo", child.Tag); } [Fact] @@ -332,40 +338,37 @@ namespace Avalonia.Controls.UnitTests [Fact] public void Should_Set_Child_LogicalParent_After_Removing_And_Adding_Back_To_Logical_Tree() { - using (UnitTestApplication.Start(TestServices.RealStyler)) + var target = new ContentControl(); + var root = new TestRoot { - var target = new ContentControl(); - var root = new TestRoot + Styles = { - Styles = + new Style(x => x.OfType()) { - new Style(x => x.OfType()) + Setters = { - Setters = - { - new Setter(ContentControl.TemplateProperty, GetTemplate()), - } + new Setter(ContentControl.TemplateProperty, GetTemplate()), } - }, - Child = target - }; + } + }, + Child = target + }; - target.Content = "Foo"; - target.ApplyTemplate(); - target.Presenter.ApplyTemplate(); + target.Content = "Foo"; + target.ApplyTemplate(); + target.Presenter.ApplyTemplate(); - Assert.Equal(target, target.Presenter.Child.LogicalParent); + Assert.Equal(target, target.Presenter.Child.LogicalParent); - root.Child = null; + root.Child = null; - Assert.Null(target.Template); + Assert.Null(target.Template); - target.Content = null; - root.Child = target; - target.Content = "Bar"; + target.Content = null; + root.Child = target; + target.Content = "Bar"; - Assert.Equal(target, target.Presenter.Child.LogicalParent); - } + Assert.Equal(target, target.Presenter.Child.LogicalParent); } private FuncControlTemplate GetTemplate() diff --git a/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs b/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs index b63cbd286e..a798801f20 100644 --- a/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ContextMenuTests.cs @@ -29,6 +29,7 @@ namespace Avalonia.Controls.UnitTests }; var window = new Window { Content = target }; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -61,6 +62,7 @@ namespace Avalonia.Controls.UnitTests }; var window = new Window { Content = target }; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -130,6 +132,7 @@ namespace Avalonia.Controls.UnitTests }; var window = new Window { Content = target }; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -158,6 +161,7 @@ namespace Avalonia.Controls.UnitTests }; var window = new Window { Content = target }; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -186,6 +190,7 @@ namespace Avalonia.Controls.UnitTests }; var window = new Window { Content = target }; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -207,6 +212,7 @@ namespace Avalonia.Controls.UnitTests }; var window = new Window { Content = target }; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -390,7 +396,8 @@ namespace Avalonia.Controls.UnitTests var sp = new StackPanel { Children = { target1, target2 } }; var window = new Window { Content = sp }; - + + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -594,6 +601,7 @@ namespace Avalonia.Controls.UnitTests windowImpl.Setup(x => x.CreateRenderer(It.IsAny())).Returns(renderer.Object); var w = new Window(windowImpl.Object) { Content = content }; + w.ApplyStyling(); w.ApplyTemplate(); w.Presenter.ApplyTemplate(); return w; diff --git a/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs b/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs index f6d96edb99..7b7f0fcc98 100644 --- a/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ListBoxTests.cs @@ -99,7 +99,7 @@ namespace Avalonia.Controls.UnitTests using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface)) { var items = new[] { "Foo", "Bar", "Baz " }; - var theme = new ControlTheme(); + var theme = new ControlTheme(typeof(ListBoxItem)); var target = new ListBox { Template = ListBoxTemplate(), @@ -121,7 +121,7 @@ namespace Avalonia.Controls.UnitTests using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface)) { var items = new[] { "Foo", "Bar", "Baz " }; - var theme = new ControlTheme(); + var theme = new ControlTheme(typeof(ListBoxItem)); var target = new ListBox { Template = ListBoxTemplate(), diff --git a/tests/Avalonia.Controls.UnitTests/MenuItemTests.cs b/tests/Avalonia.Controls.UnitTests/MenuItemTests.cs index d25a790fde..c19a01facb 100644 --- a/tests/Avalonia.Controls.UnitTests/MenuItemTests.cs +++ b/tests/Avalonia.Controls.UnitTests/MenuItemTests.cs @@ -193,6 +193,7 @@ namespace Avalonia.Controls.UnitTests var target = new MenuItem(); var contextMenu = new ContextMenu { Items = new AvaloniaList { target } }; var window = new Window { Content = new Panel { ContextMenu = contextMenu } }; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -232,6 +233,7 @@ namespace Avalonia.Controls.UnitTests var flyout = new MenuFlyout { Items = new AvaloniaList { target } }; var button = new Button { Flyout = flyout }; var window = new Window { Content = button }; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -271,6 +273,7 @@ namespace Avalonia.Controls.UnitTests var parentMenuItem = new MenuItem { Items = new AvaloniaList { target } }; var contextMenu = new ContextMenu { Items = new AvaloniaList { parentMenuItem } }; var window = new Window { Content = new Panel { ContextMenu = contextMenu } }; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); contextMenu.Open(); diff --git a/tests/Avalonia.Controls.UnitTests/NumericUpDownTests.cs b/tests/Avalonia.Controls.UnitTests/NumericUpDownTests.cs index 4cef7e4d05..d50faf8be9 100644 --- a/tests/Avalonia.Controls.UnitTests/NumericUpDownTests.cs +++ b/tests/Avalonia.Controls.UnitTests/NumericUpDownTests.cs @@ -50,6 +50,7 @@ namespace Avalonia.Controls.UnitTests var control = CreateControl(); TextBox textBox = GetTextBox(control); var window = new Window { Content = control }; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); Dispatcher.UIThread.RunJobs(); diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs index 6d3351d2b2..f283681088 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupRootTests.cs @@ -51,6 +51,7 @@ namespace Avalonia.Controls.UnitTests.Primitives }; window.Content = target; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); target.ApplyTemplate(); @@ -177,6 +178,7 @@ namespace Avalonia.Controls.UnitTests.Primitives }; window.Content = target; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); target.ApplyTemplate(); diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs index 5f91f2e2a1..7e695612df 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/PopupTests.cs @@ -569,6 +569,7 @@ namespace Avalonia.Controls.UnitTests.Primitives windowImpl.Setup(x => x.CreateRenderer(It.IsAny())).Returns(renderer.Object); var window = new Window(windowImpl.Object); + window.ApplyStyling(); window.ApplyTemplate(); var target = new Popup() @@ -1090,6 +1091,7 @@ namespace Avalonia.Controls.UnitTests.Primitives private Window PreparedWindow(object content = null) { var w = new Window { Content = content }; + w.ApplyStyling(); w.ApplyTemplate(); return w; } diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs index 330cbfd7b9..100e813326 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs @@ -998,6 +998,7 @@ namespace Avalonia.Controls.UnitTests.Primitives [Fact] public void Order_Of_Setting_Items_And_SelectedIndex_During_Initialization_Should_Not_Matter() { + using var app = Start(); var items = new[] { "Foo", "Bar" }; var target = new SelectingItemsControl(); @@ -1015,6 +1016,7 @@ namespace Avalonia.Controls.UnitTests.Primitives [Fact] public void Order_Of_Setting_Items_And_SelectedItem_During_Initialization_Should_Not_Matter() { + using var app = Start(); var items = new[] { "Foo", "Bar" }; var target = new SelectingItemsControl(); @@ -1847,6 +1849,7 @@ namespace Avalonia.Controls.UnitTests.Primitives public void Preserves_SelectedItem_When_Items_Changed() { // Issue #4048 + using var app = Start(); var target = new SelectingItemsControl { Items = new[] { "foo", "bar", "baz"}, @@ -1867,6 +1870,7 @@ namespace Avalonia.Controls.UnitTests.Primitives [Fact] public void Setting_SelectedItems_Raises_PropertyChanged() { + using var app = Start(); var target = new TestSelector { Items = new[] { "foo", "bar", "baz" }, @@ -1895,6 +1899,7 @@ namespace Avalonia.Controls.UnitTests.Primitives [Fact] public void Setting_Selection_Raises_SelectedItems_PropertyChanged() { + using var app = Start(); var target = new TestSelector { Items = new[] { "foo", "bar", "baz" }, @@ -2050,6 +2055,13 @@ namespace Avalonia.Controls.UnitTests.Primitives } } + private static IDisposable Start() + { + return UnitTestApplication.Start(new TestServices( + fontManagerImpl: new MockFontManagerImpl(), + textShaperImpl: new MockTextShaperImpl())); + } + private static void Prepare(SelectingItemsControl target) { var root = new TestRoot diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/TemplatedControlTests.cs b/tests/Avalonia.Controls.UnitTests/Primitives/TemplatedControlTests.cs index 58d2eedb1f..a7609a6704 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/TemplatedControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/TemplatedControlTests.cs @@ -170,36 +170,41 @@ namespace Avalonia.Controls.UnitTests.Primitives [Fact] public void Templated_Children_Should_Be_Styled() { - using (UnitTestApplication.Start(TestServices.MockStyler)) - { - TestTemplatedControl target; + TestTemplatedControl target; - var root = new TestRoot + var root = new TestRoot + { + Styles = { - Child = target = new TestTemplatedControl + new Style(x => x.Is()) { - Template = new FuncControlTemplate((_, __) => + Setters = { - return new StackPanel - { - Children = + new Setter(Control.TagProperty, "foo") + } + } + }, + Child = target = new TestTemplatedControl + { + Template = new FuncControlTemplate((_, __) => + { + return new StackPanel + { + Children = { new TextBlock { } } - }; - }), - } - }; + }; + }), + } + }; - target.ApplyTemplate(); + target.ApplyTemplate(); - var styler = Mock.Get(UnitTestApplication.Current.Services.Styler); - styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once()); - styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once()); - styler.Verify(x => x.ApplyStyles(It.IsAny()), Times.Once()); - } + foreach (Control child in target.GetTemplateChildren()) + Assert.Equal("foo", child.Tag); } [Fact] @@ -351,166 +356,154 @@ namespace Avalonia.Controls.UnitTests.Primitives [Fact] public void Removing_From_LogicalTree_Should_Not_Remove_Child() { - using (UnitTestApplication.Start(TestServices.RealStyler)) + Border templateChild = new Border(); + TestTemplatedControl target; + var root = new TestRoot { - Border templateChild = new Border(); - TestTemplatedControl target; - var root = new TestRoot + Styles = { - Styles = + new Style(x => x.OfType()) { - new Style(x => x.OfType()) + Setters = { - Setters = - { - new Setter( - TemplatedControl.TemplateProperty, - new FuncControlTemplate((_, __) => new Decorator - { - Child = new Border(), - })) - } + new Setter( + TemplatedControl.TemplateProperty, + new FuncControlTemplate((_, __) => new Decorator + { + Child = new Border(), + })) } - }, - Child = target = new TestTemplatedControl() - }; + } + }, + Child = target = new TestTemplatedControl() + }; - Assert.NotNull(target.Template); - target.ApplyTemplate(); + Assert.NotNull(target.Template); + target.ApplyTemplate(); - root.Child = null; + root.Child = null; - Assert.Null(target.Template); - Assert.IsType(target.GetVisualChildren().Single()); - } + Assert.Null(target.Template); + Assert.IsType(target.GetVisualChildren().Single()); } [Fact] public void Re_adding_To_Same_LogicalTree_Should_Not_Recreate_Template() { - using (UnitTestApplication.Start(TestServices.RealStyler)) + TestTemplatedControl target; + var root = new TestRoot { - TestTemplatedControl target; - var root = new TestRoot + Styles = { - Styles = + new Style(x => x.OfType()) { - new Style(x => x.OfType()) + Setters = { - Setters = - { - new Setter( - TemplatedControl.TemplateProperty, - new FuncControlTemplate((_, __) => new Decorator - { - Child = new Border(), - })) - } + new Setter( + TemplatedControl.TemplateProperty, + new FuncControlTemplate((_, __) => new Decorator + { + Child = new Border(), + })) } - }, - Child = target = new TestTemplatedControl() - }; + } + }, + Child = target = new TestTemplatedControl() + }; - Assert.NotNull(target.Template); - target.ApplyTemplate(); - var expected = (Decorator)target.GetVisualChildren().Single(); + Assert.NotNull(target.Template); + target.ApplyTemplate(); + var expected = (Decorator)target.GetVisualChildren().Single(); - root.Child = null; - root.Child = target; - target.ApplyTemplate(); + root.Child = null; + root.Child = target; + target.ApplyTemplate(); - Assert.Same(expected, target.GetVisualChildren().Single()); - } + Assert.Same(expected, target.GetVisualChildren().Single()); } [Fact] public void Re_adding_To_Different_LogicalTree_Should_Recreate_Template() { - using (UnitTestApplication.Start(TestServices.RealStyler)) - { - TestTemplatedControl target; + TestTemplatedControl target; - var root = new TestRoot + var root = new TestRoot + { + Styles = { - Styles = + new Style(x => x.OfType()) { - new Style(x => x.OfType()) + Setters = { - Setters = - { - new Setter( - TemplatedControl.TemplateProperty, - new FuncControlTemplate((_, __) => new Decorator - { - Child = new Border(), - })) - } + new Setter( + TemplatedControl.TemplateProperty, + new FuncControlTemplate((_, __) => new Decorator + { + Child = new Border(), + })) } - }, - Child = target = new TestTemplatedControl() - }; + } + }, + Child = target = new TestTemplatedControl() + }; - var root2 = new TestRoot + var root2 = new TestRoot + { + Styles = { - Styles = + new Style(x => x.OfType()) { - new Style(x => x.OfType()) + Setters = { - Setters = - { - new Setter( - TemplatedControl.TemplateProperty, - new FuncControlTemplate((_, __) => new Decorator - { - Child = new Border(), - })) - } + new Setter( + TemplatedControl.TemplateProperty, + new FuncControlTemplate((_, __) => new Decorator + { + Child = new Border(), + })) } - }, - }; + } + }, + }; - Assert.NotNull(target.Template); - target.ApplyTemplate(); + Assert.NotNull(target.Template); + target.ApplyTemplate(); - var expected = (Decorator)target.GetVisualChildren().Single(); + var expected = (Decorator)target.GetVisualChildren().Single(); - root.Child = null; - root2.Child = target; - target.ApplyTemplate(); + root.Child = null; + root2.Child = target; + target.ApplyTemplate(); - var child = target.GetVisualChildren().Single(); - Assert.NotNull(target.Template); - Assert.NotNull(child); - Assert.NotSame(expected, child); - } + var child = target.GetVisualChildren().Single(); + Assert.NotNull(target.Template); + Assert.NotNull(child); + Assert.NotSame(expected, child); } [Fact] public void Moving_To_New_LogicalTree_Should_Detach_Attach_Template_Child() { - using (UnitTestApplication.Start(TestServices.RealStyler)) + TestTemplatedControl target; + var root = new TestRoot { - TestTemplatedControl target; - var root = new TestRoot + Child = target = new TestTemplatedControl { - Child = target = new TestTemplatedControl - { - Template = new FuncControlTemplate((_, __) => new Decorator()), - } - }; + Template = new FuncControlTemplate((_, __) => new Decorator()), + } + }; - Assert.NotNull(target.Template); - target.ApplyTemplate(); + Assert.NotNull(target.Template); + target.ApplyTemplate(); - var templateChild = (ILogical)target.GetVisualChildren().Single(); - Assert.True(templateChild.IsAttachedToLogicalTree); + var templateChild = (ILogical)target.GetVisualChildren().Single(); + Assert.True(templateChild.IsAttachedToLogicalTree); - root.Child = null; - Assert.False(templateChild.IsAttachedToLogicalTree); + root.Child = null; + Assert.False(templateChild.IsAttachedToLogicalTree); - var newRoot = new TestRoot { Child = target }; - Assert.True(templateChild.IsAttachedToLogicalTree); - } + var newRoot = new TestRoot { Child = target }; + Assert.True(templateChild.IsAttachedToLogicalTree); } [Fact] diff --git a/tests/Avalonia.Controls.UnitTests/TabControlTests.cs b/tests/Avalonia.Controls.UnitTests/TabControlTests.cs index c54d7efe61..d8a897d600 100644 --- a/tests/Avalonia.Controls.UnitTests/TabControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TabControlTests.cs @@ -227,28 +227,24 @@ namespace Avalonia.Controls.UnitTests }; var template = new FuncControlTemplate((x, __) => new Decorator()); - - using (UnitTestApplication.Start(TestServices.RealStyler)) + var root = new TestRoot { - var root = new TestRoot + Styles = { - Styles = + new Style(x => x.OfType()) { - new Style(x => x.OfType()) + Setters = { - Setters = - { - new Setter(TemplatedControl.TemplateProperty, template) - } + new Setter(TemplatedControl.TemplateProperty, template) } - }, - Child = new TabControl - { - Template = TabControlTemplate(), - Items = collection, } - }; - } + }, + Child = new TabControl + { + Template = TabControlTemplate(), + Items = collection, + } + }; Assert.Same(collection[0].Template, template); Assert.Same(collection[1].Template, template); diff --git a/tests/Avalonia.Controls.UnitTests/ToolTipTests.cs b/tests/Avalonia.Controls.UnitTests/ToolTipTests.cs index 25969a58e3..25f38f8665 100644 --- a/tests/Avalonia.Controls.UnitTests/ToolTipTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ToolTipTests.cs @@ -51,6 +51,7 @@ namespace Avalonia.Controls.UnitTests window.Content = panel; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -114,6 +115,7 @@ namespace Avalonia.Controls.UnitTests window.Content = target; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -140,6 +142,7 @@ namespace Avalonia.Controls.UnitTests window.Content = target; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -183,6 +186,7 @@ namespace Avalonia.Controls.UnitTests window.Content = target; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -215,6 +219,7 @@ namespace Avalonia.Controls.UnitTests window.Content = decorator; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -237,6 +242,7 @@ namespace Avalonia.Controls.UnitTests window.Content = decorator; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -261,6 +267,7 @@ namespace Avalonia.Controls.UnitTests window.Content = decorator; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); @@ -286,6 +293,7 @@ namespace Avalonia.Controls.UnitTests window.Content = target; + window.ApplyStyling(); window.ApplyTemplate(); window.Presenter.ApplyTemplate(); diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs index 9cf21423a3..9ae6fd98b5 100644 --- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs @@ -77,7 +77,7 @@ namespace Avalonia.Controls.UnitTests public void Items_Should_Be_Created_Using_ItemConatinerTheme_If_Present() { TreeView target; - var theme = new ControlTheme(); + var theme = new ControlTheme(typeof(TreeViewItem)); var root = new TestRoot { diff --git a/tests/Avalonia.Controls.UnitTests/UserControlTests.cs b/tests/Avalonia.Controls.UnitTests/UserControlTests.cs index 3d1980b0eb..6342d9d21f 100644 --- a/tests/Avalonia.Controls.UnitTests/UserControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/UserControlTests.cs @@ -13,26 +13,23 @@ namespace Avalonia.Controls.UnitTests [Fact] public void Should_Be_Styled_As_UserControl() { - using (UnitTestApplication.Start(TestServices.RealStyler)) + var target = new UserControl(); + var root = new TestRoot { - var target = new UserControl(); - var root = new TestRoot + Styles = { - Styles = + new Style(x => x.OfType()) { - new Style(x => x.OfType()) + Setters = { - Setters = - { - new Setter(TemplatedControl.TemplateProperty, GetTemplate()) - } + new Setter(TemplatedControl.TemplateProperty, GetTemplate()) } - }, - Child = target, - }; + } + }, + Child = target, + }; - Assert.NotNull(target.Template); - } + Assert.NotNull(target.Template); } private FuncControlTemplate GetTemplate() diff --git a/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs b/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs index e4d177f7ca..3202924a9d 100644 --- a/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Utils/HotKeyManagerTests.cs @@ -23,11 +23,8 @@ namespace Avalonia.Controls.UnitTests.Utils { using (AvaloniaLocator.EnterScope()) { - var styler = new Mock(); - AvaloniaLocator.CurrentMutable - .Bind().ToConstant(new WindowingPlatformMock()) - .Bind().ToConstant(styler.Object); + .Bind().ToConstant(new WindowingPlatformMock()); var gesture1 = new KeyGesture(Key.A, KeyModifiers.Control); var gesture2 = new KeyGesture(Key.B, KeyModifiers.Control); @@ -67,13 +64,11 @@ namespace Avalonia.Controls.UnitTests.Utils { using (AvaloniaLocator.EnterScope()) { - var styler = new Mock(); var target = new KeyboardDevice(); var commandResult = 0; var expectedParameter = 1; AvaloniaLocator.CurrentMutable - .Bind().ToConstant(new WindowingPlatformMock()) - .Bind().ToConstant(styler.Object); + .Bind().ToConstant(new WindowingPlatformMock()); var gesture = new KeyGesture(Key.A, KeyModifiers.Control); @@ -112,12 +107,10 @@ namespace Avalonia.Controls.UnitTests.Utils { using (AvaloniaLocator.EnterScope()) { - var styler = new Mock(); var target = new KeyboardDevice(); var isExecuted = false; AvaloniaLocator.CurrentMutable - .Bind().ToConstant(new WindowingPlatformMock()) - .Bind().ToConstant(styler.Object); + .Bind().ToConstant(new WindowingPlatformMock()); var gesture = new KeyGesture(Key.A, KeyModifiers.Control); @@ -154,12 +147,10 @@ namespace Avalonia.Controls.UnitTests.Utils { using (AvaloniaLocator.EnterScope()) { - var styler = new Mock(); var target = new KeyboardDevice(); var clickExecutedCount = 0; AvaloniaLocator.CurrentMutable - .Bind().ToConstant(new WindowingPlatformMock()) - .Bind().ToConstant(styler.Object); + .Bind().ToConstant(new WindowingPlatformMock()); var gesture = new KeyGesture(Key.A, KeyModifiers.Control); @@ -208,13 +199,11 @@ namespace Avalonia.Controls.UnitTests.Utils { using (AvaloniaLocator.EnterScope()) { - var styler = new Mock(); var target = new KeyboardDevice(); var clickExecutedCount = 0; var commandExecutedCount = 0; AvaloniaLocator.CurrentMutable - .Bind().ToConstant(new WindowingPlatformMock()) - .Bind().ToConstant(styler.Object); + .Bind().ToConstant(new WindowingPlatformMock()); var gesture = new KeyGesture(Key.A, KeyModifiers.Control); diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs index 2d7dcf4b45..88d2cc2912 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/CompiledBindingExtensionTests.cs @@ -5,6 +5,7 @@ using System.ComponentModel; using System.Globalization; using System.Linq; using System.Reactive.Subjects; +using System.Runtime.CompilerServices; using System.Threading.Tasks; using Avalonia.Controls; using Avalonia.Controls.Presenters; @@ -26,6 +27,11 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions { public class CompiledBindingExtensionTests { + static CompiledBindingExtensionTests() + { + RuntimeHelpers.RunClassConstructor(typeof(RelativeSource).TypeHandle); + } + [Fact] public void ResolvesClrPropertyBasedOnDataContextType() { diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs index 2a2e5f2478..af133cca73 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/Xaml/BasicTests.cs @@ -720,7 +720,12 @@ namespace Avalonia.Markup.Xaml.UnitTests.Xaml //ensure binding is set and operational first Assert.Equal(100.0, tracker.Tag); - Assert.Equal("EndInit 0", tracker.Order.Last()); + // EndInit should be second-to-last operation, as last operation will be + // caused by styling being applied on EndInit. + Assert.Equal("EndInit 0", tracker.Order[tracker.Order.Count - 2]); + + // Caused by styling. + Assert.Equal("Property Foreground Changed", tracker.Order[tracker.Order.Count - 1]); } } diff --git a/tests/Avalonia.UnitTests/TestServices.cs b/tests/Avalonia.UnitTests/TestServices.cs index 49da2794c1..c421adaf21 100644 --- a/tests/Avalonia.UnitTests/TestServices.cs +++ b/tests/Avalonia.UnitTests/TestServices.cs @@ -23,7 +23,6 @@ namespace Avalonia.UnitTests platform: new AppBuilder().RuntimePlatform, renderInterface: new MockPlatformRenderInterface(), standardCursorFactory: Mock.Of(), - styler: new Styler(), theme: () => CreateSimpleTheme(), threadingInterface: Mock.Of(x => x.CurrentThreadIsLoopThread == true), fontManagerImpl: new MockFontManagerImpl(), @@ -39,9 +38,6 @@ namespace Avalonia.UnitTests public static readonly TestServices MockPlatformWrapper = new TestServices( platform: Mock.Of()); - public static readonly TestServices MockStyler = new TestServices( - styler: Mock.Of()); - public static readonly TestServices MockThreadingInterface = new TestServices( threadingInterface: Mock.Of(x => x.CurrentThreadIsLoopThread == true)); @@ -58,9 +54,6 @@ namespace Avalonia.UnitTests fontManagerImpl: new MockFontManagerImpl(), textShaperImpl: new MockTextShaperImpl()); - public static readonly TestServices RealStyler = new TestServices( - styler: new Styler()); - public static readonly TestServices TextServices = new TestServices( assetLoader: new AssetLoader(), renderInterface: new MockPlatformRenderInterface(), @@ -80,7 +73,6 @@ namespace Avalonia.UnitTests IRenderTimer renderLoop = null, IScheduler scheduler = null, ICursorFactory standardCursorFactory = null, - IStyler styler = null, Func theme = null, IPlatformThreadingInterface threadingInterface = null, IFontManagerImpl fontManagerImpl = null, @@ -101,7 +93,6 @@ namespace Avalonia.UnitTests TextShaperImpl = textShaperImpl; Scheduler = scheduler; StandardCursorFactory = standardCursorFactory; - Styler = styler; Theme = theme; ThreadingInterface = threadingInterface; WindowImpl = windowImpl; @@ -121,7 +112,6 @@ namespace Avalonia.UnitTests public ITextShaperImpl TextShaperImpl { get; } public IScheduler Scheduler { get; } public ICursorFactory StandardCursorFactory { get; } - public IStyler Styler { get; } public Func Theme { get; } public IPlatformThreadingInterface ThreadingInterface { get; } public IWindowImpl WindowImpl { get; } @@ -140,8 +130,7 @@ namespace Avalonia.UnitTests IRenderTimer renderLoop = null, IScheduler scheduler = null, ICursorFactory standardCursorFactory = null, - IStyler styler = null, - Func theme = null, + Func theme = null, IPlatformThreadingInterface threadingInterface = null, IFontManagerImpl fontManagerImpl = null, ITextShaperImpl textShaperImpl = null, @@ -162,7 +151,6 @@ namespace Avalonia.UnitTests textShaperImpl: textShaperImpl ?? TextShaperImpl, scheduler: scheduler ?? Scheduler, standardCursorFactory: standardCursorFactory ?? StandardCursorFactory, - styler: styler ?? Styler, theme: theme ?? Theme, threadingInterface: threadingInterface ?? ThreadingInterface, windowingPlatform: windowingPlatform ?? WindowingPlatform, diff --git a/tests/Avalonia.UnitTests/UnitTestApplication.cs b/tests/Avalonia.UnitTests/UnitTestApplication.cs index 260771c9ab..03e19359c3 100644 --- a/tests/Avalonia.UnitTests/UnitTestApplication.cs +++ b/tests/Avalonia.UnitTests/UnitTestApplication.cs @@ -68,14 +68,13 @@ namespace Avalonia.UnitTests .Bind().ToConstant(Services.ThreadingInterface) .Bind().ToConstant(Services.Scheduler) .Bind().ToConstant(Services.StandardCursorFactory) - .Bind().ToConstant(Services.Styler) .Bind().ToConstant(Services.WindowingPlatform) .Bind().ToSingleton(); var theme = Services.Theme?.Invoke(); - if (theme is Styles styles) + if (theme is Style styles) { - Styles.AddRange(styles); + Styles.AddRange(styles.Children); } else if (theme is not null) {