Skip to content

Commit

Permalink
Update IResourceNode interface
Browse files Browse the repository at this point in the history
  • Loading branch information
maxkatz6 committed May 22, 2022
1 parent 5c56e3f commit a96fb54
Show file tree
Hide file tree
Showing 19 changed files with 85 additions and 153 deletions.
2 changes: 1 addition & 1 deletion samples/IntegrationTestApp/App.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="IntegrationTestApp.App">
<Application.Styles>
<FluentTheme Mode="Light"/>
<FluentTheme />
</Application.Styles>
</Application>
2 changes: 1 addition & 1 deletion samples/Sandbox/App.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Sandbox.App">
<Application.Styles>
<FluentTheme Mode="Dark"/>
<FluentTheme />
</Application.Styles>
</Application>
3 changes: 3 additions & 0 deletions src/Avalonia.Base/Controls/IResourceDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ public interface IResourceDictionary : IResourceProvider, IDictionary<object, ob
/// </summary>
IList<IResourceProvider> MergedDictionaries { get; }

/// <summary>
/// Gets a collection of merged resource dictionaries that are specifically keyed and composed to address theme scenarios.
/// </summary>
IDictionary<ElementTheme, IResourceProvider> ThemeDictionaries { get; }
}
}
8 changes: 3 additions & 5 deletions src/Avalonia.Base/Controls/IResourceNode.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using Avalonia.Metadata;
using Avalonia.Metadata;

namespace Avalonia.Controls
{
Expand All @@ -23,15 +22,14 @@ public interface IResourceNode
/// Tries to find a resource within the object.
/// </summary>
/// <param name="key">The resource key.</param>
/// <param name="theme">Theme used to select theme dictionary.</param>
/// <param name="value">
/// When this method returns, contains the value associated with the specified key,
/// if the key is found; otherwise, null.
/// </param>
/// <returns>
/// True if the resource if found, otherwise false.
/// </returns>
bool TryGetResource(object key, out object? value);

bool TryGetResource(ElementTheme theme, object key, out object? value);
bool TryGetResource(object key, ElementTheme? theme, out object? value);
}
}
32 changes: 6 additions & 26 deletions src/Avalonia.Base/Controls/ResourceDictionary.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,44 +132,24 @@ bool IResourceNode.HasResources

public event EventHandler? OwnerChanged;

public bool TryGetResource(object key, out object? value)
/// <inheritdoc/>
public bool TryGetResource(object key, ElementTheme? theme, out object? value)
{
if (TryGetValue(key, out value))
{
return true;
}

if (_mergedDictionaries != null)
{
for (var i = _mergedDictionaries.Count - 1; i >= 0; --i)
{
if (_mergedDictionaries[i].TryGetResource(key, out value))
{
return true;
}
}
}

return false;
}

public bool TryGetResource(ElementTheme theme, object key, out object? value)
{
if (TryGetValue(key, out value))
{
return true;
}

if (_themeDictionary is not null)
if (_themeDictionary is not null && theme is not null)
{
if (_themeDictionary.TryGetValue(theme, out var themeResourceProvider)
&& themeResourceProvider.TryGetResource(key, out value))
&& themeResourceProvider.TryGetResource(key, theme, out value))
{
return true;
}
if (theme.InheritTheme is {} themeInherit
&& _themeDictionary.TryGetValue(themeInherit, out themeResourceProvider)
&& themeResourceProvider.TryGetResource(key, out value))
&& themeResourceProvider.TryGetResource(key, theme, out value))
{
return true;
}
Expand All @@ -179,7 +159,7 @@ public bool TryGetResource(ElementTheme theme, object key, out object? value)
{
for (var i = _mergedDictionaries.Count - 1; i >= 0; --i)
{
if (_mergedDictionaries[i].TryGetResource(theme, key, out value))
if (_mergedDictionaries[i].TryGetResource(key, theme, out value))
{
return true;
}
Expand Down
66 changes: 44 additions & 22 deletions src/Avalonia.Base/Controls/ResourceNodeExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using Avalonia.LogicalTree;
using Avalonia.Reactive;

#nullable enable
Expand Down Expand Up @@ -39,38 +38,51 @@ public static bool TryFindResource(this IResourceHost control, object key, out o
control = control ?? throw new ArgumentNullException(nameof(control));
key = key ?? throw new ArgumentNullException(nameof(key));

IResourceNode? current = control;
var theme = AvaloniaLocator.Current.GetService<IApplicationThemeHost>()?.Theme;

while (current != null)
{
if (current.TryGetResource(key, out value))
{
return true;
}
return control.TryFindResource(key, theme, out value);
}

/// <summary>
/// Finds the specified resource by searching up the logical tree and then global styles.
/// </summary>
/// <param name="control">The control.</param>
/// <param name="theme">Theme used to select theme dictionary.</param>
/// <param name="key">The resource key.</param>
/// <returns>The resource, or <see cref="AvaloniaProperty.UnsetValue"/> if not found.</returns>
public static object? FindResource(this IResourceHost control, ElementTheme? theme, object key)
{
control = control ?? throw new ArgumentNullException(nameof(control));
key = key ?? throw new ArgumentNullException(nameof(key));

current = (current as IStyledElement)?.StylingParent as IResourceNode;
if (control.TryFindResource(key, theme, out var value))
{
return value;
}

value = null;
return false;
return AvaloniaProperty.UnsetValue;
}

public static bool TryFindThemeResource(this IResourceHost control, ElementTheme theme, object key, out object? value)

/// <summary>
/// Tries to the specified resource by searching up the logical tree and then global styles.
/// </summary>
/// <param name="control">The control.</param>
/// <param name="key">The resource key.</param>
/// <param name="theme">Theme used to select theme dictionary.</param>
/// <param name="value">On return, contains the resource if found, otherwise null.</param>
/// <returns>True if the resource was found; otherwise false.</returns>
public static bool TryFindResource(this IResourceHost control, object key, ElementTheme? theme, out object? value)
{
control = control ?? throw new ArgumentNullException(nameof(control));
theme = theme ?? throw new ArgumentNullException(nameof(theme));
key = key ?? throw new ArgumentNullException(nameof(key));

IResourceHost? current = control;

while (current != null)
{
if (current is IResourceHost host)
if (current.TryGetResource(key, theme, out value))
{
if (host.TryGetResource(theme, key, out value))
{
return true;
}
return true;
}

current = (current as IStyledElement)?.StylingParent as IResourceHost;
Expand All @@ -79,6 +91,17 @@ public static bool TryFindThemeResource(this IResourceHost control, ElementTheme
value = null;
return false;
}

/// <inheritdoc cref="IResourceHost.TryGetResource" />
public static bool TryGetResource(this IResourceHost control, object key, out object? value)
{
control = control ?? throw new ArgumentNullException(nameof(control));
key = key ?? throw new ArgumentNullException(nameof(key));

var theme = AvaloniaLocator.Current.GetService<IApplicationThemeHost>()?.Theme;

return control.TryGetResource(key, theme, out value);
}

public static IObservable<object?> GetResourceObservable(
this IResourceHost control,
Expand Down Expand Up @@ -151,8 +174,7 @@ private void ThemeChanged(object? sender, EventArgs e)
private object? GetValue()
{
if (!(_target is IThemeStyleable themeStyleable)
|| themeStyleable.Theme is null
|| !themeStyleable.TryFindThemeResource(themeStyleable.Theme, _key, out var value))
|| !themeStyleable.TryFindResource(_key, themeStyleable.Theme, out var value))
{
value = _target.FindResource(_key) ?? AvaloniaProperty.UnsetValue;
}
Expand Down Expand Up @@ -242,7 +264,7 @@ private void ThemeChanged(object? sender, EventArgs e)
{
if (!(_target.Owner is IThemeStyleable themeStyleable)
|| themeStyleable.Theme is null
|| !themeStyleable.TryFindThemeResource(themeStyleable.Theme, _key, out var value))
|| !themeStyleable.TryFindResource(_key, themeStyleable.Theme, out var value))
{
value = _target.Owner?.FindResource(_key) ?? AvaloniaProperty.UnsetValue;
}
Expand Down
13 changes: 3 additions & 10 deletions src/Avalonia.Base/StyledElement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -396,18 +396,11 @@ void ILogical.NotifyDetachedFromLogicalTree(LogicalTreeAttachmentEventArgs e)
void IResourceHost.NotifyHostedResourcesChanged(ResourcesChangedEventArgs e) => NotifyResourcesChanged(e);

/// <inheritdoc/>
bool IResourceNode.TryGetResource(object key, out object? value)
public bool TryGetResource(object key, ElementTheme? theme, out object? value)
{
value = null;
return (_resources?.TryGetResource(key, out value) ?? false) ||
(_styles?.TryGetResource(key, out value) ?? false);
}

public bool TryGetResource(ElementTheme theme, object key, out object? value)
{
value = null;
return (_resources?.TryGetResource(theme, key, out value) ?? false) ||
(_styles?.TryGetResource(theme, key, out value) ?? false);
return (_resources?.TryGetResource(key, theme, out value) ?? false) ||
(_styles?.TryGetResource(key, theme, out value) ?? false);
}

/// <summary>
Expand Down
13 changes: 4 additions & 9 deletions src/Avalonia.Base/Styling/Style.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,17 +110,12 @@ public SelectorMatchResult TryAttach(IStyleable target, IStyleHost? host)

return match.Result;
}

public bool TryGetResource(object key, out object? result)
{
result = null;
return _resources?.TryGetResource(key, out result) ?? false;
}

public bool TryGetResource(ElementTheme theme, object key, out object? result)

/// <inheritdoc/>
public bool TryGetResource(object key, ElementTheme? theme, out object? result)
{
result = null;
return _resources?.TryGetResource(theme, key, out result) ?? false;
return _resources?.TryGetResource(key, theme, out result) ?? false;
}

/// <summary>
Expand Down
25 changes: 3 additions & 22 deletions src/Avalonia.Base/Styling/Styles.cs
Original file line number Diff line number Diff line change
Expand Up @@ -151,35 +151,16 @@ public SelectorMatchResult TryAttach(IStyleable target, IStyleHost? host)
}

/// <inheritdoc/>
public bool TryGetResource(object key, out object? value)
public bool TryGetResource(object key, ElementTheme? theme, out object? value)
{
if (_resources != null && _resources.TryGetResource(key, out value))
if (_resources != null && _resources.TryGetResource(key, theme, out value))
{
return true;
}

for (var i = Count - 1; i >= 0; --i)
{
if (this[i].TryGetResource(key, out value))
{
return true;
}
}

value = null;
return false;
}

public bool TryGetResource(ElementTheme theme, object key, out object? value)
{
if (_resources != null && _resources.TryGetResource(theme, key, out value))
{
return true;
}

for (var i = Count - 1; i >= 0; --i)
{
if (this[i] is IResourceProvider p && p.TryGetResource(theme, key, out value))
if (this[i] is IResourceProvider p && p.TryGetResource(key, theme, out value))
{
return true;
}
Expand Down
2 changes: 1 addition & 1 deletion src/Avalonia.Base/Themes/ElementTheme.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public ElementTheme(object key)
Key = key ?? throw new ArgumentNullException(nameof(key));
}

public ElementTheme(object key, ElementTheme inheritTheme)
public ElementTheme(object key, ElementTheme? inheritTheme)
{
Key = key ?? throw new ArgumentNullException(nameof(key));
InheritTheme = inheritTheme;
Expand Down
13 changes: 3 additions & 10 deletions src/Avalonia.Controls/Application.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,18 +210,11 @@ event Action<IReadOnlyList<IStyle>>? IGlobalStyles.GlobalStylesRemoved
public virtual void Initialize() { }

/// <inheritdoc/>
bool IResourceNode.TryGetResource(object key, out object? value)
public bool TryGetResource(object key, ElementTheme? theme, out object? value)
{
value = null;
return (_resources?.TryGetResource(key, out value) ?? false) ||
Styles.TryGetResource(key, out value);
}

public bool TryGetResource(ElementTheme theme, object key, out object? value)
{
value = null;
return (_resources?.TryGetResource(theme, key, out value) ?? false) ||
Styles.TryGetResource(theme, key, out value);
return (_resources?.TryGetResource(key, theme, out value) ?? false) ||
Styles.TryGetResource(key, theme, out value);
}

void IResourceHost.NotifyHostedResourcesChanged(ResourcesChangedEventArgs e)
Expand Down
2 changes: 1 addition & 1 deletion src/Avalonia.Dialogs/ResourceSelectorConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public class ResourceSelectorConverter : ResourceDictionary, IValueConverter
{
public object Convert(object key, Type targetType, object parameter, CultureInfo culture)
{
TryGetResource((string)key, out var value);
TryGetResource((string)key, null, out var value);
return value;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,23 +47,12 @@ public event EventHandler OwnerChanged
add => Loaded.OwnerChanged += value;
remove => Loaded.OwnerChanged -= value;
}

bool IResourceNode.TryGetResource(object key, out object? value)
{
if (!_isLoading)
{
return Loaded.TryGetResource(key, out value);
}

value = null;
return false;
}

public bool TryGetResource(ElementTheme theme, object key, out object? value)

public bool TryGetResource(object key, ElementTheme? theme, out object? value)
{
if (!_isLoading)
{
return Loaded.TryGetResource(theme, key, out value);
return Loaded.TryGetResource(key, theme, out value);
}

value = null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,7 @@ public object ProvideValue(IServiceProvider serviceProvider)
{
if (parent is IResourceNode node)
{
if (appTheme is not null && node.TryGetResource(appTheme, ResourceKey, out var value))
{
return ColorToBrushConverter.Convert(value, targetType);
}
if (node.TryGetResource(ResourceKey, out value))
if (node.TryGetResource(ResourceKey, appTheme, out var value))
{
return ColorToBrushConverter.Convert(value, targetType);
}
Expand Down
Loading

0 comments on commit a96fb54

Please sign in to comment.