Ver código fonte

Refactored most of Style into StyleBase.

Ready for `ControlTheme` class, which is a style without a selector.
Steven Kirk 3 anos atrás
pai
commit
c02439aaaf

+ 9 - 139
src/Avalonia.Base/Styling/Style.cs

@@ -1,23 +1,12 @@
 using System;
-using System.Collections.Generic;
-using Avalonia.Animation;
-using Avalonia.Controls;
-using Avalonia.Metadata;
 
 namespace Avalonia.Styling
 {
     /// <summary>
     /// Defines a style.
     /// </summary>
-    public class Style : AvaloniaObject, IStyle, IResourceProvider
+    public class Style : StyleBase
     {
-        private IResourceHost? _owner;
-        private StyleChildren? _children;
-        private IResourceDictionary? _resources;
-        private List<ISetter>? _setters;
-        private List<IAnimation>? _animations;
-        private StyleCache? _childCache;
-
         /// <summary>
         /// Initializes a new instance of the <see cref="Style"/> class.
         /// </summary>
@@ -34,114 +23,11 @@ namespace Avalonia.Styling
             Selector = selector(null);
         }
 
-        /// <summary>
-        /// Gets the children of the style.
-        /// </summary>
-        public IList<IStyle> Children => _children ??= new(this);
-
-        /// <summary>
-        /// Gets the <see cref="StyledElement"/> or Application that hosts the style.
-        /// </summary>
-        public IResourceHost? Owner
-        {
-            get => _owner;
-            private set
-            {
-                if (_owner != value)
-                {
-                    _owner = value;
-                    OwnerChanged?.Invoke(this, EventArgs.Empty);
-                }
-            }
-        }
-
-        /// <summary>
-        /// Gets the parent style if this style is hosted in a <see cref="Style.Children"/> collection.
-        /// </summary>
-        public Style? Parent { get; private set; }
-
-        /// <summary>
-        /// Gets or sets a dictionary of style resources.
-        /// </summary>
-        public IResourceDictionary Resources
-        {
-            get => _resources ?? (Resources = new ResourceDictionary());
-            set
-            {
-                value = value ?? throw new ArgumentNullException(nameof(value));
-
-                var hadResources = _resources?.HasResources ?? false;
-
-                _resources = value;
-
-                if (Owner is object)
-                {
-                    _resources.AddOwner(Owner);
-
-                    if (hadResources || _resources.HasResources)
-                    {
-                        Owner.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty);
-                    }
-                }
-            }
-        }
-
         /// <summary>
         /// Gets or sets the style's selector.
         /// </summary>
         public Selector? Selector { get; set; }
 
-        /// <summary>
-        /// Gets the style's setters.
-        /// </summary>
-        public IList<ISetter> Setters => _setters ??= new List<ISetter>();
-
-        /// <summary>
-        /// Gets the style's animations.
-        /// </summary>
-        public IList<IAnimation> Animations => _animations ??= new List<IAnimation>();
-
-        bool IResourceNode.HasResources => _resources?.Count > 0;
-        IReadOnlyList<IStyle> IStyle.Children => (IReadOnlyList<IStyle>?)_children ?? Array.Empty<IStyle>();
-
-        public event EventHandler? OwnerChanged;
-
-        public void Add(ISetter setter) => Setters.Add(setter);
-        public void Add(IStyle style) => Children.Add(style);
-
-        public SelectorMatchResult TryAttach(IStyleable target, IStyleHost? host)
-        {
-            target = target ?? throw new ArgumentNullException(nameof(target));
-
-            var match = Selector is object ? Selector.Match(target, Parent) :
-                target == host ? SelectorMatch.AlwaysThisInstance : SelectorMatch.NeverThisInstance;
-
-            if (match.IsMatch && (_setters is object || _animations is object))
-            {
-                var instance = new StyleInstance(this, target, _setters, _animations, match.Activator);
-                target.StyleApplied(instance);
-                instance.Start();
-            }
-
-            var result = match.Result;
-
-            if (_children is not null)
-            {
-                _childCache ??= new StyleCache();
-                var childResult = _childCache.TryAttach(_children, target, host);
-                if (childResult > result)
-                    result = childResult;
-            }
-
-            return result;
-        }
-
-        public bool TryGetResource(object key, out object? result)
-        {
-            result = null;
-            return _resources?.TryGetResource(key, out result) ?? false;
-        }
-
         /// <summary>
         /// Returns a string representation of the style.
         /// </summary>
@@ -158,33 +44,17 @@ namespace Avalonia.Styling
             }
         }
 
-        void IResourceProvider.AddOwner(IResourceHost owner)
-        {
-            owner = owner ?? throw new ArgumentNullException(nameof(owner));
-
-            if (Owner != null)
-            {
-                throw new InvalidOperationException("The Style already has a parent.");
-            }
-
-            Owner = owner;
-            _resources?.AddOwner(owner);
-        }
-
-        void IResourceProvider.RemoveOwner(IResourceHost owner)
+        protected override SelectorMatch Matches(IStyleable target, IStyleHost? host)
         {
-            owner = owner ?? throw new ArgumentNullException(nameof(owner));
-
-            if (Owner == owner)
-            {
-                Owner = null;
-                _resources?.RemoveOwner(owner);
-            }
+            return Selector?.Match(target, Parent) ??
+                (target == host ?
+                    SelectorMatch.AlwaysThisInstance :
+                    SelectorMatch.NeverThisInstance);
         }
 
-        internal void SetParent(Style? parent)
+        internal override void SetParent(StyleBase? parent)
         {
-            if (parent?.Selector is not null)
+            if (parent is Style parentStyle && parentStyle.Selector is not null)
             {
                 if (Selector is null)
                     throw new InvalidOperationException("Child styles must have a selector.");
@@ -192,7 +62,7 @@ namespace Avalonia.Styling
                     throw new InvalidOperationException("Child styles must have a nesting selector.");
             }
 
-            Parent = parent;
+            base.SetParent(parent);
         }
     }
 }

+ 137 - 0
src/Avalonia.Base/Styling/StyleBase.cs

@@ -0,0 +1,137 @@
+using System;
+using System.Collections.Generic;
+using Avalonia.Animation;
+using Avalonia.Controls;
+using Avalonia.Metadata;
+
+namespace Avalonia.Styling
+{
+    /// <summary>
+    /// Base class for <see cref="Style"/> and <see cref="ControlTheme"/>.
+    /// </summary>
+    public abstract class StyleBase : AvaloniaObject, IStyle, IResourceProvider
+    {
+        private IResourceHost? _owner;
+        private StyleChildren? _children;
+        private IResourceDictionary? _resources;
+        private List<ISetter>? _setters;
+        private List<IAnimation>? _animations;
+        private StyleCache? _childCache;
+
+        public IList<IStyle> Children => _children ??= new(this);
+
+        public IResourceHost? Owner
+        {
+            get => _owner;
+            private set
+            {
+                if (_owner != value)
+                {
+                    _owner = value;
+                    OwnerChanged?.Invoke(this, EventArgs.Empty);
+                }
+            }
+        }
+
+        public IStyle? Parent { get; private set; }
+
+        public IResourceDictionary Resources
+        {
+            get => _resources ?? (Resources = new ResourceDictionary());
+            set
+            {
+                value = value ?? throw new ArgumentNullException(nameof(value));
+
+                var hadResources = _resources?.HasResources ?? false;
+
+                _resources = value;
+
+                if (Owner is object)
+                {
+                    _resources.AddOwner(Owner);
+
+                    if (hadResources || _resources.HasResources)
+                    {
+                        Owner.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty);
+                    }
+                }
+            }
+        }
+
+        public IList<ISetter> Setters => _setters ??= new List<ISetter>();
+        public IList<IAnimation> Animations => _animations ??= new List<IAnimation>();
+
+        bool IResourceNode.HasResources => _resources?.Count > 0;
+        IReadOnlyList<IStyle> IStyle.Children => (IReadOnlyList<IStyle>?)_children ?? Array.Empty<IStyle>();
+
+        public void Add(ISetter setter) => Setters.Add(setter);
+        public void Add(IStyle style) => Children.Add(style);
+
+        public event EventHandler? OwnerChanged;
+
+        public SelectorMatchResult TryAttach(IStyleable target, IStyleHost? host)
+        {
+            target = target ?? throw new ArgumentNullException(nameof(target));
+
+            var result = SelectorMatchResult.NeverThisType;
+
+            if (_setters?.Count > 0 || _animations?.Count > 0)
+            {
+                var match = Matches(target, host);
+
+                if (match.IsMatch)
+                {
+                    var instance = new StyleInstance(this, target, _setters, _animations, match.Activator);
+                    target.StyleApplied(instance);
+                    instance.Start();
+                }
+
+                result = match.Result;
+            }
+
+            if (_children is not null)
+            {
+                _childCache ??= new StyleCache();
+                var childResult = _childCache.TryAttach(_children, target, host);
+                if (childResult > result)
+                    result = childResult;
+            }
+
+            return result;
+        }
+
+        public bool TryGetResource(object key, out object? result)
+        {
+            result = null;
+            return _resources?.TryGetResource(key, out result) ?? false;
+        }
+
+        protected abstract SelectorMatch Matches(IStyleable target, IStyleHost? host);
+
+        internal virtual void SetParent(StyleBase? parent) => Parent = parent;
+
+        void IResourceProvider.AddOwner(IResourceHost owner)
+        {
+            owner = owner ?? throw new ArgumentNullException(nameof(owner));
+
+            if (Owner != null)
+            {
+                throw new InvalidOperationException("The Style already has a parent.");
+            }
+
+            Owner = owner;
+            _resources?.AddOwner(owner);
+        }
+
+        void IResourceProvider.RemoveOwner(IResourceHost owner)
+        {
+            owner = owner ?? throw new ArgumentNullException(nameof(owner));
+
+            if (Owner == owner)
+            {
+                Owner = null;
+                _resources?.RemoveOwner(owner);
+            }
+        }
+    }
+}

+ 5 - 5
src/Avalonia.Base/Styling/StyleChildren.cs

@@ -5,20 +5,20 @@ namespace Avalonia.Styling
 {
     internal class StyleChildren : Collection<IStyle>
     {
-        private readonly Style _owner;
+        private readonly StyleBase _owner;
 
-        public StyleChildren(Style owner) => _owner = owner;
+        public StyleChildren(StyleBase owner) => _owner = owner;
 
         protected override void InsertItem(int index, IStyle item)
         {
-            (item as Style)?.SetParent(_owner);
+            (item as StyleBase)?.SetParent(_owner);
             base.InsertItem(index, item);
         }
 
         protected override void RemoveItem(int index)
         {
             var item = Items[index];
-            (item as Style)?.SetParent(null);
+            (item as StyleBase)?.SetParent(null);
             if (_owner.Owner is IResourceHost host)
                 (item as IResourceProvider)?.RemoveOwner(host);
             base.RemoveItem(index);
@@ -26,7 +26,7 @@ namespace Avalonia.Styling
 
         protected override void SetItem(int index, IStyle item)
         {
-            (item as Style)?.SetParent(_owner);
+            (item as StyleBase)?.SetParent(_owner);
             base.SetItem(index, item);
             if (_owner.Owner is IResourceHost host)
                 (item as IResourceProvider)?.AddOwner(host);