// Copyright (c) The Avalonia Project. All rights reserved. // Licensed under the MIT license. See licence.md file in the project root for full license information. using System; using Avalonia.Data; using Avalonia.Utilities; namespace Avalonia.Controls.Primitives { /// /// Base class for controls that display a value within a range. /// public abstract class RangeBase : TemplatedControl { /// /// Defines the property. /// public static readonly DirectProperty MinimumProperty = AvaloniaProperty.RegisterDirect( nameof(Minimum), o => o.Minimum, (o, v) => o.Minimum = v); /// /// Defines the property. /// public static readonly DirectProperty MaximumProperty = AvaloniaProperty.RegisterDirect( nameof(Maximum), o => o.Maximum, (o, v) => o.Maximum = v); /// /// Defines the property. /// public static readonly DirectProperty ValueProperty = AvaloniaProperty.RegisterDirect( nameof(Value), o => o.Value, (o, v) => o.Value = v, defaultBindingMode: BindingMode.TwoWay); /// /// Defines the property. /// public static readonly StyledProperty SmallChangeProperty = AvaloniaProperty.Register(nameof(SmallChange), 1); /// /// Defines the property. /// public static readonly StyledProperty LargeChangeProperty = AvaloniaProperty.Register(nameof(LargeChange), 10); private double _minimum; private double _maximum = 100.0; private double _value; /// /// Initializes a new instance of the class. /// public RangeBase() { } /// /// Gets or sets the minimum value. /// public double Minimum { get { return _minimum; } set { ValidateDouble(value, "Minimum"); if (IsInitialized) { SetAndRaise(MinimumProperty, ref _minimum, value); Maximum = ValidateMaximum(Maximum); Value = ValidateValue(Value); } else { SetAndRaise(MinimumProperty, ref _minimum, value); } } } /// /// Gets or sets the maximum value. /// public double Maximum { get { return _maximum; } set { ValidateDouble(value, "Maximum"); if (IsInitialized) { value = ValidateMaximum(value); SetAndRaise(MaximumProperty, ref _maximum, value); Value = ValidateValue(Value); } else { SetAndRaise(MaximumProperty, ref _maximum, value); } } } /// /// Gets or sets the current value. /// public double Value { get { return _value; } set { ValidateDouble(value, "Value"); if (IsInitialized) { value = ValidateValue(value); SetAndRaise(ValueProperty, ref _value, value); } else { SetAndRaise(ValueProperty, ref _value, value); } } } public double SmallChange { get => GetValue(SmallChangeProperty); set => SetValue(SmallChangeProperty, value); } public double LargeChange { get => GetValue(LargeChangeProperty); set => SetValue(LargeChangeProperty, value); } protected override void OnInitialized() { base.OnInitialized(); Maximum = ValidateMaximum(Maximum); Value = ValidateValue(Value); } /// /// Throws an exception if the double value is NaN or Inf. /// /// The value. /// The name of the property being set. private static void ValidateDouble(double value, string property) { if (double.IsInfinity(value) || double.IsNaN(value)) { throw new ArgumentException($"{value} is not a valid value for {property}."); } } /// /// Validates/coerces the property. /// /// The value. /// The coerced value. private double ValidateMaximum(double value) { return Math.Max(value, Minimum); } /// /// Validates/coerces the property. /// /// The value. /// The coerced value. private double ValidateValue(double value) { return MathUtilities.Clamp(value, Minimum, Maximum); } } }