4 changed files with 119 additions and 2 deletions
@ -0,0 +1,114 @@ |
|||||
|
using System; |
||||
|
using System.Collections.Generic; |
||||
|
using Avalonia.Controls; |
||||
|
using Avalonia.Markup.Xaml; |
||||
|
using Avalonia.Styling; |
||||
|
|
||||
|
#nullable enable |
||||
|
|
||||
|
namespace Avalonia.Themes.Fluent |
||||
|
{ |
||||
|
public enum FluentColorScheme |
||||
|
{ |
||||
|
Light, |
||||
|
Dark, |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Includes the fluent theme in an application.
|
||||
|
/// </summary>
|
||||
|
public class FluentTheme : IStyle, IResourceProvider |
||||
|
{ |
||||
|
private readonly Uri _baseUri; |
||||
|
private IStyle[]? _loaded; |
||||
|
private bool _isLoading; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="FluentTheme"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="baseUri">The base URL for the XAML context.</param>
|
||||
|
public FluentTheme(Uri baseUri) |
||||
|
{ |
||||
|
_baseUri = baseUri; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Initializes a new instance of the <see cref="FluentTheme"/> class.
|
||||
|
/// </summary>
|
||||
|
/// <param name="serviceProvider">The XAML service provider.</param>
|
||||
|
public FluentTheme(IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
_baseUri = ((IUriContext)serviceProvider.GetService(typeof(IUriContext))).BaseUri; |
||||
|
} |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets or sets the color scheme to use (light, dark).
|
||||
|
/// </summary>
|
||||
|
public FluentColorScheme Scheme { get; set; } |
||||
|
|
||||
|
public IResourceHost? Owner => (Loaded as IResourceProvider)?.Owner; |
||||
|
|
||||
|
/// <summary>
|
||||
|
/// Gets the loaded style.
|
||||
|
/// </summary>
|
||||
|
public IStyle Loaded |
||||
|
{ |
||||
|
get |
||||
|
{ |
||||
|
if (_loaded == null) |
||||
|
{ |
||||
|
_isLoading = true; |
||||
|
var loaded = (IStyle)AvaloniaXamlLoader.Load(GetUri(), _baseUri); |
||||
|
_loaded = new[] { loaded }; |
||||
|
_isLoading = false; |
||||
|
} |
||||
|
|
||||
|
return _loaded?[0]!; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
bool IResourceNode.HasResources => (Loaded as IResourceProvider)?.HasResources ?? false; |
||||
|
|
||||
|
IReadOnlyList<IStyle> IStyle.Children => _loaded ?? Array.Empty<IStyle>(); |
||||
|
|
||||
|
public event EventHandler OwnerChanged |
||||
|
{ |
||||
|
add |
||||
|
{ |
||||
|
if (Loaded is IResourceProvider rp) |
||||
|
{ |
||||
|
rp.OwnerChanged += value; |
||||
|
} |
||||
|
} |
||||
|
remove |
||||
|
{ |
||||
|
if (Loaded is IResourceProvider rp) |
||||
|
{ |
||||
|
rp.OwnerChanged -= value; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
public SelectorMatchResult TryAttach(IStyleable target, IStyleHost? host) => Loaded.TryAttach(target, host); |
||||
|
|
||||
|
public bool TryGetResource(object key, out object? value) |
||||
|
{ |
||||
|
if (!_isLoading && Loaded is IResourceProvider p) |
||||
|
{ |
||||
|
return p.TryGetResource(key, out value); |
||||
|
} |
||||
|
|
||||
|
value = null; |
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
void IResourceProvider.AddOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.AddOwner(owner); |
||||
|
void IResourceProvider.RemoveOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.RemoveOwner(owner); |
||||
|
|
||||
|
private Uri GetUri() => Scheme switch |
||||
|
{ |
||||
|
FluentColorScheme.Dark => new Uri("avares://Avalonia.Themes.Fluent/FluentDark.xaml", UriKind.Absolute), |
||||
|
_ => new Uri("avares://Avalonia.Themes.Fluent/FluentLight.xaml", UriKind.Absolute), |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
using Avalonia.Metadata; |
||||
|
|
||||
|
[assembly: XmlnsDefinition("https://github.com/avaloniaui", "Avalonia.Themes.Fluent")] |
||||
Loading…
Reference in new issue