|
|
|
@ -2,6 +2,7 @@ |
|
|
|
using System.Collections.Generic; |
|
|
|
using Avalonia.Controls; |
|
|
|
using Avalonia.Markup.Xaml; |
|
|
|
using Avalonia.Markup.Xaml.Styling; |
|
|
|
using Avalonia.Styling; |
|
|
|
|
|
|
|
#nullable enable |
|
|
|
@ -17,11 +18,14 @@ namespace Avalonia.Themes.Fluent |
|
|
|
/// <summary>
|
|
|
|
/// Includes the fluent theme in an application.
|
|
|
|
/// </summary>
|
|
|
|
public class FluentTheme : IStyle, IResourceProvider |
|
|
|
public class FluentTheme : AvaloniaObject, IStyle, IResourceProvider |
|
|
|
{ |
|
|
|
private readonly Uri _baseUri; |
|
|
|
private IStyle[]? _loaded; |
|
|
|
private Styles _fluentDark = new(); |
|
|
|
private Styles _fluentLight = new(); |
|
|
|
private Styles _sharedStyles = new(); |
|
|
|
private bool _isLoading; |
|
|
|
private IStyle? _loaded; |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Initializes a new instance of the <see cref="FluentTheme"/> class.
|
|
|
|
@ -30,6 +34,7 @@ namespace Avalonia.Themes.Fluent |
|
|
|
public FluentTheme(Uri baseUri) |
|
|
|
{ |
|
|
|
_baseUri = baseUri; |
|
|
|
InitStyles(baseUri); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@ -39,12 +44,37 @@ namespace Avalonia.Themes.Fluent |
|
|
|
public FluentTheme(IServiceProvider serviceProvider) |
|
|
|
{ |
|
|
|
_baseUri = ((IUriContext)serviceProvider.GetService(typeof(IUriContext))).BaseUri; |
|
|
|
InitStyles(_baseUri); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
public static readonly StyledProperty<FluentThemeMode> ModeProperty = |
|
|
|
AvaloniaProperty.Register<FluentTheme, FluentThemeMode>(nameof(Mode)); |
|
|
|
/// <summary>
|
|
|
|
/// Gets or sets the mode of the fluent theme (light, dark).
|
|
|
|
/// </summary>
|
|
|
|
public FluentThemeMode Mode { get; set; } |
|
|
|
public FluentThemeMode Mode |
|
|
|
{ |
|
|
|
get => GetValue(ModeProperty); |
|
|
|
set => SetValue(ModeProperty, value); |
|
|
|
} |
|
|
|
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change) |
|
|
|
{ |
|
|
|
base.OnPropertyChanged(change); |
|
|
|
if (change.Property == ModeProperty) |
|
|
|
{ |
|
|
|
if (Mode == FluentThemeMode.Dark) |
|
|
|
{ |
|
|
|
(Loaded as Styles)![1] = _fluentDark[0]; |
|
|
|
(Loaded as Styles)![2] = _fluentDark[1]; |
|
|
|
} |
|
|
|
else |
|
|
|
{ |
|
|
|
(Loaded as Styles)![1] = _fluentLight[0]; |
|
|
|
(Loaded as Styles)![2] = _fluentLight[1]; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
public IResourceHost? Owner => (Loaded as IResourceProvider)?.Owner; |
|
|
|
|
|
|
|
@ -58,18 +88,25 @@ namespace Avalonia.Themes.Fluent |
|
|
|
if (_loaded == null) |
|
|
|
{ |
|
|
|
_isLoading = true; |
|
|
|
var loaded = (IStyle)AvaloniaXamlLoader.Load(GetUri(), _baseUri); |
|
|
|
_loaded = new[] { loaded }; |
|
|
|
|
|
|
|
if (Mode == FluentThemeMode.Light) |
|
|
|
{ |
|
|
|
_loaded = new Styles() { _sharedStyles , _fluentLight[0], _fluentLight[1] }; |
|
|
|
} |
|
|
|
else if (Mode == FluentThemeMode.Dark) |
|
|
|
{ |
|
|
|
_loaded = new Styles() { _sharedStyles, _fluentDark[0], _fluentDark[1] }; |
|
|
|
} |
|
|
|
_isLoading = false; |
|
|
|
} |
|
|
|
|
|
|
|
return _loaded?[0]!; |
|
|
|
return _loaded!; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
bool IResourceNode.HasResources => (Loaded as IResourceProvider)?.HasResources ?? false; |
|
|
|
|
|
|
|
IReadOnlyList<IStyle> IStyle.Children => _loaded ?? Array.Empty<IStyle>(); |
|
|
|
IReadOnlyList<IStyle> IStyle.Children => _loaded?.Children ?? Array.Empty<IStyle>(); |
|
|
|
|
|
|
|
public event EventHandler OwnerChanged |
|
|
|
{ |
|
|
|
@ -105,10 +142,47 @@ namespace Avalonia.Themes.Fluent |
|
|
|
void IResourceProvider.AddOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.AddOwner(owner); |
|
|
|
void IResourceProvider.RemoveOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.RemoveOwner(owner); |
|
|
|
|
|
|
|
private Uri GetUri() => Mode switch |
|
|
|
private void InitStyles(Uri baseUri) |
|
|
|
{ |
|
|
|
FluentThemeMode.Dark => new Uri("avares://Avalonia.Themes.Fluent/FluentDark.xaml", UriKind.Absolute), |
|
|
|
_ => new Uri("avares://Avalonia.Themes.Fluent/FluentLight.xaml", UriKind.Absolute), |
|
|
|
}; |
|
|
|
_sharedStyles = new Styles |
|
|
|
{ |
|
|
|
new StyleInclude(baseUri) |
|
|
|
{ |
|
|
|
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml") |
|
|
|
}, |
|
|
|
new StyleInclude(baseUri) |
|
|
|
{ |
|
|
|
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/Base.xaml") |
|
|
|
}, |
|
|
|
new StyleInclude(baseUri) |
|
|
|
{ |
|
|
|
Source = new Uri("avares://Avalonia.Themes.Fluent/Controls/FluentControls.xaml") |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
_fluentLight = new Styles |
|
|
|
{ |
|
|
|
new StyleInclude(baseUri) |
|
|
|
{ |
|
|
|
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/BaseLight.xaml") |
|
|
|
}, |
|
|
|
new StyleInclude(baseUri) |
|
|
|
{ |
|
|
|
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/FluentControlResourcesLight.xaml") |
|
|
|
} |
|
|
|
}; |
|
|
|
|
|
|
|
_fluentDark = new Styles |
|
|
|
{ |
|
|
|
new StyleInclude(baseUri) |
|
|
|
{ |
|
|
|
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/BaseDark.xaml") |
|
|
|
}, |
|
|
|
new StyleInclude(baseUri) |
|
|
|
{ |
|
|
|
Source = new Uri("avares://Avalonia.Themes.Fluent/Accents/FluentControlResourcesDark.xaml") |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|