A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

166 lines
5.2 KiB

using System;
using System.Collections.Generic;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.Markup.Xaml.Styling;
using Avalonia.Styling;
#nullable enable
namespace Avalonia.Themes.Default
{
public class SimpleTheme : AvaloniaObject, IStyle, IResourceProvider
{
public static readonly StyledProperty<SimpleThemeMode> ModeProperty =
AvaloniaProperty.Register<SimpleTheme, SimpleThemeMode>(nameof(Mode));
private readonly Uri _baseUri;
private bool _isLoading;
private IStyle? _loaded;
private Styles _sharedStyles = new();
private Styles _simpleDark = new();
private Styles _simpleLight = new();
/// <summary>
/// Initializes a new instance of the <see cref="SimpleTheme"/> class.
/// </summary>
/// <param name="baseUri">The base URL for the XAML context.</param>
public SimpleTheme(Uri baseUri)
{
_baseUri = baseUri;
InitStyles(_baseUri);
}
/// <summary>
/// Initializes a new instance of the <see cref="SimpleTheme"/> class.
/// </summary>
/// <param name="serviceProvider">The XAML service provider.</param>
public SimpleTheme(IServiceProvider serviceProvider)
{
var service = serviceProvider.GetService(typeof(IUriContext));
if (service == null)
{
throw new Exception("There is no service object of type IUriContext!");
}
_baseUri = ((IUriContext)service).BaseUri;
InitStyles(_baseUri);
}
public event EventHandler OwnerChanged
{
add
{
if (Loaded is IResourceProvider rp)
{
rp.OwnerChanged += value;
}
}
remove
{
if (Loaded is IResourceProvider rp)
{
rp.OwnerChanged -= value;
}
}
}
IReadOnlyList<IStyle> IStyle.Children => _loaded?.Children ?? Array.Empty<IStyle>();
bool IResourceNode.HasResources => (Loaded as IResourceProvider)?.HasResources ?? false;
public IStyle Loaded
{
get
{
if (_loaded == null)
{
_isLoading = true;
if (Mode == SimpleThemeMode.Light)
{
_loaded = new Styles { _sharedStyles, _simpleLight };
}
else if (Mode == SimpleThemeMode.Dark)
{
_loaded = new Styles { _sharedStyles, _simpleDark };
}
_isLoading = false;
}
return _loaded!;
}
}
/// <summary>
/// Gets or sets the mode of the fluent theme (light, dark).
/// </summary>
public SimpleThemeMode Mode
{
get => GetValue(ModeProperty);
set => SetValue(ModeProperty, value);
}
public IResourceHost? Owner => (Loaded as IResourceProvider)?.Owner;
void IResourceProvider.AddOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.AddOwner(owner);
void IResourceProvider.RemoveOwner(IResourceHost owner) => (Loaded as IResourceProvider)?.RemoveOwner(owner);
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;
}
protected override void OnPropertyChanged<T>(AvaloniaPropertyChangedEventArgs<T> change)
{
base.OnPropertyChanged(change);
if (change.Property == ModeProperty)
{
if (Mode == SimpleThemeMode.Dark)
{
(Loaded as Styles)![1] = _simpleDark[0];
}
else
{
(Loaded as Styles)![1] = _simpleLight[0];
}
}
}
private void InitStyles(Uri baseUri)
{
_sharedStyles = new Styles
{
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Default/DefaultTheme.xaml")
},
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Default/Accents/Base.xaml")
}
};
_simpleLight = new Styles
{
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Default/Accents/BaseLight.xaml")
}
};
_simpleDark = new Styles
{
new StyleInclude(baseUri)
{
Source = new Uri("avares://Avalonia.Themes.Default/Accents/BaseDark.xaml")
}
};
}
}
}