зеркало из https://github.com/AvaloniaUI/Avalonia.git
ResourceProvider upgrade (#16928)
* Implement AvaloniaObject on ResourceProvider * ColorPaletteResources and ColorPaletteResourcesCollection should inherit ResourceProvider * Use ResourceProvider in tests too * Adjust API diff --------- Co-authored-by: Steven Kirk <grokys@users.noreply.github.com>
This commit is contained in:
Родитель
932f54316b
Коммит
c50e731d8d
|
@ -0,0 +1,16 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- https://learn.microsoft.com/en-us/dotnet/fundamentals/package-validation/diagnostic-ids -->
|
||||||
|
<Suppressions xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||||
|
<Suppression>
|
||||||
|
<DiagnosticId>CP0007</DiagnosticId>
|
||||||
|
<Target>T:Avalonia.Themes.Fluent.ColorPaletteResources</Target>
|
||||||
|
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
|
||||||
|
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
|
||||||
|
</Suppression>
|
||||||
|
<Suppression>
|
||||||
|
<DiagnosticId>CP0008</DiagnosticId>
|
||||||
|
<Target>T:Avalonia.Themes.Fluent.ColorPaletteResources</Target>
|
||||||
|
<Left>baseline/netstandard2.0/Avalonia.Themes.Fluent.dll</Left>
|
||||||
|
<Right>target/netstandard2.0/Avalonia.Themes.Fluent.dll</Right>
|
||||||
|
</Suppression>
|
||||||
|
</Suppressions>
|
|
@ -7,7 +7,7 @@ namespace Avalonia.Controls;
|
||||||
/// Base implementation for IResourceProvider interface.
|
/// Base implementation for IResourceProvider interface.
|
||||||
/// Includes Owner property management.
|
/// Includes Owner property management.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public abstract class ResourceProvider : IResourceProvider
|
public abstract class ResourceProvider : AvaloniaObject, IResourceProvider
|
||||||
{
|
{
|
||||||
private IResourceHost? _owner;
|
private IResourceHost? _owner;
|
||||||
|
|
||||||
|
|
|
@ -14,13 +14,13 @@ namespace Avalonia.Themes.Fluent;
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This class can only be used in <see cref="FluentTheme.Palettes"/>.
|
/// This class can only be used in <see cref="FluentTheme.Palettes"/>.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
public partial class ColorPaletteResources : AvaloniaObject, IResourceNode
|
public partial class ColorPaletteResources : ResourceProvider
|
||||||
{
|
{
|
||||||
private readonly Dictionary<string, Color> _colors = new(StringComparer.InvariantCulture);
|
private readonly Dictionary<string, Color> _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)
|
if (key is string strKey)
|
||||||
{
|
{
|
||||||
|
@ -86,7 +86,7 @@ public partial class ColorPaletteResources : AvaloniaObject, IResourceNode
|
||||||
|
|
||||||
return default;
|
return default;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetColor(string key, Color value)
|
private void SetColor(string key, Color value)
|
||||||
{
|
{
|
||||||
if (value == default)
|
if (value == default)
|
||||||
|
@ -113,6 +113,7 @@ public partial class ColorPaletteResources : AvaloniaObject, IResourceNode
|
||||||
_accentColorLight1, _accentColorLight2, _accentColorLight3) =
|
_accentColorLight1, _accentColorLight2, _accentColorLight3) =
|
||||||
SystemAccentColors.CalculateAccentShades(_accentColor);
|
SystemAccentColors.CalculateAccentShades(_accentColor);
|
||||||
}
|
}
|
||||||
|
RaiseResourcesChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,20 +1,26 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Avalonia.Collections;
|
using Avalonia.Collections;
|
||||||
using Avalonia.Controls;
|
using Avalonia.Controls;
|
||||||
using Avalonia.Styling;
|
using Avalonia.Styling;
|
||||||
|
|
||||||
namespace Avalonia.Themes.Fluent;
|
namespace Avalonia.Themes.Fluent;
|
||||||
|
|
||||||
internal class ColorPaletteResourcesCollection : AvaloniaDictionary<ThemeVariant, ColorPaletteResources>, IResourceProvider
|
internal sealed class ColorPaletteResourcesCollection : ResourceProvider, IDictionary<ThemeVariant, ColorPaletteResources>
|
||||||
{
|
{
|
||||||
public ColorPaletteResourcesCollection() : base(2)
|
private readonly AvaloniaDictionary<ThemeVariant, ColorPaletteResources> _inner;
|
||||||
|
|
||||||
|
public ColorPaletteResourcesCollection()
|
||||||
{
|
{
|
||||||
this.ForEachItem(
|
_inner = new AvaloniaDictionary<ThemeVariant, ColorPaletteResources>(2);
|
||||||
|
_inner.ForEachItem(
|
||||||
(key, x) =>
|
(key, x) =>
|
||||||
{
|
{
|
||||||
if (Owner is not null)
|
if (Owner is not null)
|
||||||
{
|
{
|
||||||
x.PropertyChanged += Palette_PropertyChanged;
|
((IResourceProvider)x).AddOwner(Owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key != ThemeVariant.Dark && key != ThemeVariant.Light)
|
if (key != ThemeVariant.Dark && key != ThemeVariant.Light)
|
||||||
|
@ -27,21 +33,21 @@ internal class ColorPaletteResourcesCollection : AvaloniaDictionary<ThemeVariant
|
||||||
{
|
{
|
||||||
if (Owner is not null)
|
if (Owner is not null)
|
||||||
{
|
{
|
||||||
x.PropertyChanged -= Palette_PropertyChanged;
|
((IResourceProvider)x).RemoveOwner(Owner);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
() => throw new NotSupportedException("Dictionary reset not supported"));
|
() => throw new NotSupportedException("Dictionary reset not supported"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasResources => Count > 0;
|
public override bool HasResources => _inner.Count > 0;
|
||||||
public bool TryGetResource(object key, ThemeVariant? theme, out object? value)
|
public override bool TryGetResource(object key, ThemeVariant? theme, out object? value)
|
||||||
{
|
{
|
||||||
if (theme == null || theme == ThemeVariant.Default)
|
if (theme == null || theme == ThemeVariant.Default)
|
||||||
{
|
{
|
||||||
theme = ThemeVariant.Light;
|
theme = ThemeVariant.Light;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (base.TryGetValue(theme, out var themePaletteResources)
|
if (_inner.TryGetValue(theme, out var themePaletteResources)
|
||||||
&& themePaletteResources.TryGetResource(key, theme, out value))
|
&& themePaletteResources.TryGetResource(key, theme, out value))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -51,25 +57,94 @@ internal class ColorPaletteResourcesCollection : AvaloniaDictionary<ThemeVariant
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IResourceHost? Owner { get; private set; }
|
protected override void OnAddOwner(IResourceHost owner)
|
||||||
public event EventHandler? OwnerChanged;
|
|
||||||
public void AddOwner(IResourceHost owner)
|
|
||||||
{
|
{
|
||||||
Owner = owner;
|
base.OnAddOwner(owner);
|
||||||
OwnerChanged?.Invoke(this, EventArgs.Empty);
|
foreach (var palette in _inner.Values)
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveOwner(IResourceHost owner)
|
|
||||||
{
|
|
||||||
Owner = null;
|
|
||||||
OwnerChanged?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Palette_PropertyChanged(object? sender, AvaloniaPropertyChangedEventArgs e)
|
|
||||||
{
|
|
||||||
if (e.Property == ColorPaletteResources.AccentProperty)
|
|
||||||
{
|
{
|
||||||
Owner?.NotifyHostedResourcesChanged(ResourcesChangedEventArgs.Empty);
|
((IResourceProvider)palette).AddOwner(owner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnRemoveOwner(IResourceHost owner)
|
||||||
|
{
|
||||||
|
base.OnRemoveOwner(owner);
|
||||||
|
foreach (var palette in _inner.Values)
|
||||||
|
{
|
||||||
|
((IResourceProvider)palette).RemoveOwner(owner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator<KeyValuePair<ThemeVariant, ColorPaletteResources>> IEnumerable<KeyValuePair<ThemeVariant, ColorPaletteResources>>.GetEnumerator()
|
||||||
|
{
|
||||||
|
return _inner.GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
{
|
||||||
|
return ((IEnumerable)_inner).GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICollection<KeyValuePair<ThemeVariant, ColorPaletteResources>>.Add(KeyValuePair<ThemeVariant, ColorPaletteResources> item)
|
||||||
|
{
|
||||||
|
((ICollection<KeyValuePair<ThemeVariant, ColorPaletteResources>>)_inner).Add(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICollection<KeyValuePair<ThemeVariant, ColorPaletteResources>>.Clear()
|
||||||
|
{
|
||||||
|
_inner.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ICollection<KeyValuePair<ThemeVariant, ColorPaletteResources>>.Contains(KeyValuePair<ThemeVariant, ColorPaletteResources> item)
|
||||||
|
{
|
||||||
|
return ((ICollection<KeyValuePair<ThemeVariant, ColorPaletteResources>>)_inner).Contains(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ICollection<KeyValuePair<ThemeVariant, ColorPaletteResources>>.CopyTo(KeyValuePair<ThemeVariant, ColorPaletteResources>[] array, int arrayIndex)
|
||||||
|
{
|
||||||
|
_inner.CopyTo(array, arrayIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ICollection<KeyValuePair<ThemeVariant, ColorPaletteResources>>.Remove(KeyValuePair<ThemeVariant, ColorPaletteResources> item)
|
||||||
|
{
|
||||||
|
return ((ICollection<KeyValuePair<ThemeVariant, ColorPaletteResources>>)_inner).Remove(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ICollection<KeyValuePair<ThemeVariant, ColorPaletteResources>>.Count => _inner.Count;
|
||||||
|
|
||||||
|
bool ICollection<KeyValuePair<ThemeVariant, ColorPaletteResources>>.IsReadOnly => _inner.IsReadOnly;
|
||||||
|
|
||||||
|
void IDictionary<ThemeVariant, ColorPaletteResources>.Add(ThemeVariant key, ColorPaletteResources value)
|
||||||
|
{
|
||||||
|
_inner.Add(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IDictionary<ThemeVariant, ColorPaletteResources>.ContainsKey(ThemeVariant key)
|
||||||
|
{
|
||||||
|
return _inner.ContainsKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IDictionary<ThemeVariant, ColorPaletteResources>.Remove(ThemeVariant key)
|
||||||
|
{
|
||||||
|
return _inner.Remove(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IDictionary<ThemeVariant, ColorPaletteResources>.TryGetValue(ThemeVariant key,
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
[MaybeNullWhen(false)]
|
||||||
|
#endif
|
||||||
|
out ColorPaletteResources value)
|
||||||
|
{
|
||||||
|
return _inner.TryGetValue(key, out value);
|
||||||
|
}
|
||||||
|
|
||||||
|
ColorPaletteResources IDictionary<ThemeVariant, ColorPaletteResources>.this[ThemeVariant key]
|
||||||
|
{
|
||||||
|
get => _inner[key];
|
||||||
|
set => _inner[key] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
ICollection<ThemeVariant> IDictionary<ThemeVariant, ColorPaletteResources>.Keys => _inner.Keys;
|
||||||
|
|
||||||
|
ICollection<ColorPaletteResources> IDictionary<ThemeVariant, ColorPaletteResources>.Values => _inner.Values;
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ namespace Avalonia.Themes.Fluent
|
||||||
get => _densityStyle;
|
get => _densityStyle;
|
||||||
set => SetAndRaise(DensityStyleProperty, ref _densityStyle, value);
|
set => SetAndRaise(DensityStyleProperty, ref _densityStyle, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDictionary<ThemeVariant, ColorPaletteResources> Palettes { get; }
|
public IDictionary<ThemeVariant, ColorPaletteResources> Palettes { get; }
|
||||||
|
|
||||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||||
|
|
|
@ -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 override bool HasResources => true;
|
||||||
public bool HasResources => true;
|
|
||||||
public List<object> RequestedResources { get; } = new List<object>();
|
public List<object> RequestedResources { get; } = new List<object>();
|
||||||
|
public override bool TryGetResource(object key, ThemeVariant themeVariant, out object value)
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
RequestedResources.Add(key);
|
RequestedResources.Add(key);
|
||||||
value = key;
|
value = key;
|
||||||
|
|
|
@ -127,25 +127,13 @@ namespace Avalonia.Markup.Xaml.UnitTests.MarkupExtensions
|
||||||
}
|
}
|
||||||
|
|
||||||
// See https://github.com/AvaloniaUI/Avalonia/issues/11172
|
// See https://github.com/AvaloniaUI/Avalonia/issues/11172
|
||||||
public class LocaleCollection : IResourceProvider
|
public class LocaleCollection : ResourceProvider
|
||||||
{
|
{
|
||||||
private readonly Dictionary<object, IResourceProvider> _langs = new();
|
private readonly Dictionary<object, IResourceProvider> _langs = new();
|
||||||
|
|
||||||
|
public override bool HasResources => true;
|
||||||
|
|
||||||
public IResourceHost? Owner { get; private set; }
|
public override bool TryGetResource(object key, ThemeVariant? theme, out object? value)
|
||||||
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
if (_langs.TryGetValue("English", out var res))
|
if (_langs.TryGetValue("English", out var res))
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче