using System;
namespace Avalonia.Styling
{
///
/// Defines a style.
///
public class Style : StyleBase
{
private Selector? _selector;
///
/// Initializes a new instance of the class.
///
public Style()
{
}
///
/// Initializes a new instance of the class.
///
/// The style selector.
public Style(Func selector)
{
Selector = selector(null);
}
///
/// Gets or sets the style's selector.
///
public Selector? Selector
{
get => _selector;
set => _selector = ValidateSelector(value);
}
///
/// Returns a string representation of the style.
///
/// A string representation of the style.
public override string ToString() => Selector?.ToString(this) ?? "Style";
internal override void SetParent(StyleBase? parent)
{
if (parent is Style parentStyle && parentStyle.Selector is not null)
{
if (Selector is null)
throw new InvalidOperationException("Child styles must have a selector.");
Selector.ValidateNestingSelector(false);
}
else if (parent is ControlTheme)
{
if (Selector is null)
throw new InvalidOperationException("Child styles must have a selector.");
Selector.ValidateNestingSelector(true);
}
base.SetParent(parent);
}
internal override SelectorMatchResult TryAttach(IStyleable target, object? host)
{
_ = target ?? throw new ArgumentNullException(nameof(target));
var result = SelectorMatchResult.NeverThisType;
if (HasSettersOrAnimations)
{
var match = Selector?.Match(target, Parent, true) ??
(target == host ?
SelectorMatch.AlwaysThisInstance :
SelectorMatch.NeverThisInstance);
if (match.IsMatch)
{
Attach(target, match.Activator);
}
result = match.Result;
}
return result;
}
private static Selector? ValidateSelector(Selector? selector)
{
if (selector is TemplateSelector)
throw new InvalidOperationException(
"Invalid selector: Template selector must be followed by control selector.");
return selector;
}
}
}