diff --git a/api/Avalonia.Themes.Fluent.nupkg.xml b/api/Avalonia.Themes.Fluent.nupkg.xml new file mode 100644 index 0000000000..717b64f81e --- /dev/null +++ b/api/Avalonia.Themes.Fluent.nupkg.xml @@ -0,0 +1,16 @@ + + + + + CP0007 + T:Avalonia.Themes.Fluent.ColorPaletteResources + baseline/netstandard2.0/Avalonia.Themes.Fluent.dll + target/netstandard2.0/Avalonia.Themes.Fluent.dll + + + CP0008 + T:Avalonia.Themes.Fluent.ColorPaletteResources + baseline/netstandard2.0/Avalonia.Themes.Fluent.dll + target/netstandard2.0/Avalonia.Themes.Fluent.dll + + \ No newline at end of file diff --git a/src/Avalonia.Base/Controls/ResourceProvider.cs b/src/Avalonia.Base/Controls/ResourceProvider.cs index f10a816845..0760191d1e 100644 --- a/src/Avalonia.Base/Controls/ResourceProvider.cs +++ b/src/Avalonia.Base/Controls/ResourceProvider.cs @@ -7,7 +7,7 @@ namespace Avalonia.Controls; /// Base implementation for IResourceProvider interface. /// Includes Owner property management. /// -public abstract class ResourceProvider : IResourceProvider +public abstract class ResourceProvider : AvaloniaObject, IResourceProvider { private IResourceHost? _owner; diff --git a/src/Avalonia.Themes.Fluent/ColorPaletteResources.cs b/src/Avalonia.Themes.Fluent/ColorPaletteResources.cs index ce52f51752..b5b7c80514 100644 --- a/src/Avalonia.Themes.Fluent/ColorPaletteResources.cs +++ b/src/Avalonia.Themes.Fluent/ColorPaletteResources.cs @@ -14,13 +14,13 @@ namespace Avalonia.Themes.Fluent; /// /// This class can only be used in . /// -public partial class ColorPaletteResources : AvaloniaObject, IResourceNode +public partial class ColorPaletteResources : ResourceProvider { private readonly Dictionary _colors = new(StringComparer.InvariantCulture); - public bool HasResources => _hasAccentColor || _colors.Count > 0; + public override bool HasResources => _hasAccentColor || _colors.Count > 0; - public bool TryGetResource(object key, ThemeVariant? theme, out object? value) + public override bool TryGetResource(object key, ThemeVariant? theme, out object? value) { if (key is string strKey) { @@ -86,7 +86,7 @@ public partial class ColorPaletteResources : AvaloniaObject, IResourceNode return default; } - + private void SetColor(string key, Color value) { if (value == default) @@ -113,6 +113,7 @@ public partial class ColorPaletteResources : AvaloniaObject, IResourceNode _accentColorLight1, _accentColorLight2, _accentColorLight3) = SystemAccentColors.CalculateAccentShades(_accentColor); } + RaiseResourcesChanged(); } } } diff --git a/src/Avalonia.Themes.Fluent/ColorPaletteResourcesCollection.cs b/src/Avalonia.Themes.Fluent/ColorPaletteResourcesCollection.cs index 6eb465d399..828cb2e899 100644 --- a/src/Avalonia.Themes.Fluent/ColorPaletteResourcesCollection.cs +++ b/src/Avalonia.Themes.Fluent/ColorPaletteResourcesCollection.cs @@ -1,20 +1,26 @@ using System; +using System.Collections; +using System.Collections.Generic; +using System.Diagnostics.CodeAnalysis; using Avalonia.Collections; using Avalonia.Controls; using Avalonia.Styling; namespace Avalonia.Themes.Fluent; -internal class ColorPaletteResourcesCollection : AvaloniaDictionary, IResourceProvider +internal sealed class ColorPaletteResourcesCollection : ResourceProvider, IDictionary { - public ColorPaletteResourcesCollection() : base(2) + private readonly AvaloniaDictionary _inner; + + public ColorPaletteResourcesCollection() { - this.ForEachItem( + _inner = new AvaloniaDictionary(2); + _inner.ForEachItem( (key, x) => { if (Owner is not null) { - x.PropertyChanged += Palette_PropertyChanged; + ((IResourceProvider)x).AddOwner(Owner); } if (key != ThemeVariant.Dark && key != ThemeVariant.Light) @@ -27,21 +33,21 @@ internal class ColorPaletteResourcesCollection : AvaloniaDictionary throw new NotSupportedException("Dictionary reset not supported")); } - public bool HasResources => Count > 0; - public bool TryGetResource(object key, ThemeVariant? theme, out object? value) + public override bool HasResources => _inner.Count > 0; + public override bool TryGetResource(object key, ThemeVariant? theme, out object? value) { if (theme == null || theme == ThemeVariant.Default) { theme = ThemeVariant.Light; } - if (base.TryGetValue(theme, out var themePaletteResources) + if (_inner.TryGetValue(theme, out var themePaletteResources) && themePaletteResources.TryGetResource(key, theme, out value)) { return true; @@ -51,25 +57,94 @@ internal class ColorPaletteResourcesCollection : AvaloniaDictionary> IEnumerable>.GetEnumerator() + { + return _inner.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)_inner).GetEnumerator(); + } + + void ICollection>.Add(KeyValuePair item) + { + ((ICollection>)_inner).Add(item); + } + + void ICollection>.Clear() + { + _inner.Clear(); + } + + bool ICollection>.Contains(KeyValuePair item) + { + return ((ICollection>)_inner).Contains(item); + } + + void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) + { + _inner.CopyTo(array, arrayIndex); + } + + bool ICollection>.Remove(KeyValuePair item) + { + return ((ICollection>)_inner).Remove(item); + } + + int ICollection>.Count => _inner.Count; + + bool ICollection>.IsReadOnly => _inner.IsReadOnly; + + void IDictionary.Add(ThemeVariant key, ColorPaletteResources value) + { + _inner.Add(key, value); + } + + bool IDictionary.ContainsKey(ThemeVariant key) + { + return _inner.ContainsKey(key); + } + + bool IDictionary.Remove(ThemeVariant key) + { + return _inner.Remove(key); + } + + bool IDictionary.TryGetValue(ThemeVariant key, +#if NET6_0_OR_GREATER + [MaybeNullWhen(false)] +#endif + out ColorPaletteResources value) + { + return _inner.TryGetValue(key, out value); + } + + ColorPaletteResources IDictionary.this[ThemeVariant key] + { + get => _inner[key]; + set => _inner[key] = value; + } + + ICollection IDictionary.Keys => _inner.Keys; + + ICollection IDictionary.Values => _inner.Values; } diff --git a/src/Avalonia.Themes.Fluent/FluentTheme.xaml.cs b/src/Avalonia.Themes.Fluent/FluentTheme.xaml.cs index 378041356a..53cd36215c 100644 --- a/src/Avalonia.Themes.Fluent/FluentTheme.xaml.cs +++ b/src/Avalonia.Themes.Fluent/FluentTheme.xaml.cs @@ -54,7 +54,7 @@ namespace Avalonia.Themes.Fluent get => _densityStyle; set => SetAndRaise(DensityStyleProperty, ref _densityStyle, value); } - + public IDictionary Palettes { get; } protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change) diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs index 05b77b5325..1106e7bb99 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/DynamicResourceExtensionTests.cs @@ -991,18 +991,11 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions } } - public class TrackingResourceProvider : IResourceProvider + public class TrackingResourceProvider : ResourceProvider { - public IResourceHost Owner { get; private set; } - public bool HasResources => true; + public override bool HasResources => true; public List RequestedResources { get; } = new List(); - - public event EventHandler OwnerChanged { add { } remove { } } - - public void AddOwner(IResourceHost owner) => Owner = owner; - public void RemoveOwner(IResourceHost owner) => Owner = null; - - public bool TryGetResource(object key, ThemeVariant themeVariant, out object value) + public override bool TryGetResource(object key, ThemeVariant themeVariant, out object value) { RequestedResources.Add(key); value = key; diff --git a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/ResourceIncludeTests.cs b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/ResourceIncludeTests.cs index 76ba5f9c35..624e14899b 100644 --- a/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/ResourceIncludeTests.cs +++ b/tests/Avalonia.Markup.Xaml.UnitTests/MarkupExtensions/ResourceIncludeTests.cs @@ -127,25 +127,13 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions } // See https://github.com/AvaloniaUI/Avalonia/issues/11172 - public class LocaleCollection : IResourceProvider + public class LocaleCollection : ResourceProvider { private readonly Dictionary _langs = new(); + + public override bool HasResources => true; - public IResourceHost? Owner { get; private set; } - - public bool HasResources => true; - - public event EventHandler? OwnerChanged - { - add { } - remove { } - } - - public void AddOwner(IResourceHost owner) => Owner = owner; - - public void RemoveOwner(IResourceHost owner) => Owner = null; - - public bool TryGetResource(object key, ThemeVariant? theme, out object? value) + public override bool TryGetResource(object key, ThemeVariant? theme, out object? value) { if (_langs.TryGetValue("English", out var res)) {