using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives;
namespace StabilityMatrix.Avalonia.Controls;
///
/// A control used to indicate the progress of an operation.
///
[PseudoClasses(":preserveaspect", ":indeterminate")]
public class ProgressRing : RangeBase
{
public static readonly StyledProperty IsIndeterminateProperty =
ProgressBar.IsIndeterminateProperty.AddOwner();
public static readonly StyledProperty PreserveAspectProperty =
AvaloniaProperty.Register(nameof(PreserveAspect), true);
public static readonly StyledProperty ValueAngleProperty =
AvaloniaProperty.Register(nameof(ValueAngle), 0);
public static readonly StyledProperty StartAngleProperty =
AvaloniaProperty.Register(nameof(StartAngle), 0);
public static readonly StyledProperty EndAngleProperty =
AvaloniaProperty.Register(nameof(EndAngle), 360);
static ProgressRing()
{
MinimumProperty.Changed.AddClassHandler(OnMinimumPropertyChanged);
MaximumProperty.Changed.AddClassHandler(OnMaximumPropertyChanged);
ValueProperty.Changed.AddClassHandler(OnValuePropertyChanged);
MaximumProperty.Changed.AddClassHandler(OnStartAnglePropertyChanged);
MaximumProperty.Changed.AddClassHandler(OnEndAnglePropertyChanged);
}
public ProgressRing()
{
UpdatePseudoClasses(IsIndeterminate, PreserveAspect);
}
public bool IsIndeterminate
{
get => GetValue(IsIndeterminateProperty);
set => SetValue(IsIndeterminateProperty, value);
}
public bool PreserveAspect
{
get => GetValue(PreserveAspectProperty);
set => SetValue(PreserveAspectProperty, value);
}
public double ValueAngle
{
get => GetValue(ValueAngleProperty);
private set => SetValue(ValueAngleProperty, value);
}
public double StartAngle
{
get => GetValue(StartAngleProperty);
set => SetValue(StartAngleProperty, value);
}
public double EndAngle
{
get => GetValue(EndAngleProperty);
set => SetValue(EndAngleProperty, value);
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
var e = change as AvaloniaPropertyChangedEventArgs;
if (e is null) return;
if (e.Property == IsIndeterminateProperty)
{
UpdatePseudoClasses(e.NewValue.GetValueOrDefault(), null);
}
else if (e.Property == PreserveAspectProperty)
{
UpdatePseudoClasses(null, e.NewValue.GetValueOrDefault());
}
}
private void UpdatePseudoClasses(
bool? isIndeterminate,
bool? preserveAspect)
{
if (isIndeterminate.HasValue)
{
PseudoClasses.Set(":indeterminate", isIndeterminate.Value);
}
if (preserveAspect.HasValue)
{
PseudoClasses.Set(":preserveaspect", preserveAspect.Value);
}
}
private static void OnMinimumPropertyChanged(ProgressRing sender, AvaloniaPropertyChangedEventArgs e)
{
sender.Minimum = (double)e.NewValue;
}
private static void OnMaximumPropertyChanged(ProgressRing sender, AvaloniaPropertyChangedEventArgs e)
{
sender.Maximum = (double)e.NewValue;
}
private static void OnValuePropertyChanged(ProgressRing sender, AvaloniaPropertyChangedEventArgs e)
{
sender.ValueAngle = ((double)e.NewValue - sender.Minimum) * (sender.EndAngle - sender.StartAngle) / (sender.Maximum - sender.Minimum);
}
private static void OnStartAnglePropertyChanged(ProgressRing sender, AvaloniaPropertyChangedEventArgs e)
{
sender.StartAngle = (double)e.NewValue;
}
private static void OnEndAnglePropertyChanged(ProgressRing sender, AvaloniaPropertyChangedEventArgs e)
{
sender.EndAngle = (double)e.NewValue;
}
}