feat: optimize.
This commit is contained in:
@@ -5,7 +5,6 @@ using Avalonia.Controls.Metadata;
|
||||
using Avalonia.Controls.Primitives;
|
||||
using Avalonia.Controls.Templates;
|
||||
using Avalonia.Data;
|
||||
using Avalonia.Interactivity;
|
||||
|
||||
namespace Ursa.Controls;
|
||||
|
||||
@@ -17,7 +16,6 @@ public class Rating : TemplatedControl
|
||||
protected const string PC_Selected = ":selected";
|
||||
|
||||
private ItemsControl? _itemsControl;
|
||||
private const double Tolerance = 0.00000001;
|
||||
|
||||
public static readonly StyledProperty<double> ValueProperty =
|
||||
AvaloniaProperty.Register<Rating, double>(nameof(Value), defaultBindingMode: BindingMode.TwoWay);
|
||||
@@ -120,7 +118,6 @@ public class Rating : TemplatedControl
|
||||
if (e.NewValue is double newValue)
|
||||
{
|
||||
UpdateItemsByValue(newValue);
|
||||
AdjustWidth(newValue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -148,13 +145,12 @@ public class Rating : TemplatedControl
|
||||
}
|
||||
}
|
||||
|
||||
UpdateItemsByValue(Value);
|
||||
foreach (var item in Items)
|
||||
{
|
||||
item.AllowHalf = AllowHalf;
|
||||
}
|
||||
|
||||
AdjustWidth(Value);
|
||||
UpdateItemsByValue(Value);
|
||||
}
|
||||
|
||||
private void OnAllowHalfChanged(AvaloniaPropertyChangedEventArgs e)
|
||||
@@ -166,7 +162,6 @@ public class Rating : TemplatedControl
|
||||
}
|
||||
|
||||
UpdateItemsByValue(Value);
|
||||
AdjustWidth(Value);
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
@@ -183,12 +178,19 @@ public class Rating : TemplatedControl
|
||||
{
|
||||
item.AllowHalf = AllowHalf;
|
||||
}
|
||||
|
||||
SetCurrentValue(ValueProperty, DefaultValue);
|
||||
}
|
||||
|
||||
public void Preview(RatingCharacter o)
|
||||
internal void PointerEnteredHandler(RatingCharacter o)
|
||||
{
|
||||
var index = Items.IndexOf(o);
|
||||
var item = Items.FirstOrDefault(item => item.IsLast);
|
||||
if (item is not null)
|
||||
{
|
||||
item.IsHalf = false;
|
||||
}
|
||||
|
||||
UpdateItemsByIndex(index);
|
||||
}
|
||||
|
||||
@@ -201,7 +203,7 @@ public class Rating : TemplatedControl
|
||||
newValue = index + 0.5;
|
||||
}
|
||||
|
||||
if (AllowClear && Math.Abs(Value - newValue) < Tolerance)
|
||||
if (AllowClear && Math.Abs(Value - newValue) < double.Epsilon)
|
||||
{
|
||||
SetCurrentValue(ValueProperty, 0);
|
||||
}
|
||||
@@ -213,40 +215,43 @@ public class Rating : TemplatedControl
|
||||
|
||||
internal void UpdateItemsByValue(double newValue)
|
||||
{
|
||||
RestorePreviousLastItem();
|
||||
var index = (int)Math.Ceiling(newValue - 1);
|
||||
UpdateItemsByIndex(index);
|
||||
UpdateChosenItem(newValue);
|
||||
}
|
||||
|
||||
private void RestorePreviousLastItem()
|
||||
{
|
||||
if (!AllowHalf) return;
|
||||
var item = Items.FirstOrDefault(item => item.IsLast);
|
||||
if (item is null) return;
|
||||
item.Ratio = 1;
|
||||
item.ApplyRatio();
|
||||
}
|
||||
|
||||
private void UpdateItemsByIndex(int index)
|
||||
{
|
||||
for (var i = 0; i < Items.Count; i++)
|
||||
{
|
||||
if (i == index) continue;
|
||||
Items[i].Select(i < index);
|
||||
Items[i].IsLast = false;
|
||||
Items[i].IsHalf = false;
|
||||
Items[i].Ratio = 1;
|
||||
Items[i].SetSelectedState(i <= index);
|
||||
Items[i].IsLast = i == index;
|
||||
}
|
||||
|
||||
if (index >= Items.Count || index < 0) return;
|
||||
var ratio = Math.Abs(Value - Math.Floor(Value));
|
||||
var isInt = ratio < Tolerance;
|
||||
Items[index].Select(true);
|
||||
Items[index].IsLast = true;
|
||||
Items[index].IsHalf = AllowHalf && !isInt;
|
||||
Items[index].Ratio = AllowHalf ? ratio : 1;
|
||||
}
|
||||
|
||||
|
||||
internal void AdjustWidth(double newValue)
|
||||
private void UpdateChosenItem(double newValue)
|
||||
{
|
||||
var ratio = Math.Abs(newValue - Math.Floor(newValue));
|
||||
var isInt = ratio < Tolerance;
|
||||
ratio = AllowHalf && !isInt ? ratio : 1;
|
||||
foreach (var item in Items)
|
||||
var ratio = newValue - Math.Floor(newValue);
|
||||
var isFraction = ratio >= double.Epsilon;
|
||||
ratio = AllowHalf && isFraction ? ratio : 1;
|
||||
var item = Items.FirstOrDefault(item => item.IsLast);
|
||||
if (item is null) return;
|
||||
if (!AllowHalf && isFraction)
|
||||
{
|
||||
item.Ratio = item.IsLast ? ratio : 1;
|
||||
item.AdjustWidth();
|
||||
item.SetSelectedState(false);
|
||||
}
|
||||
|
||||
item.Ratio = ratio;
|
||||
item.ApplyRatio();
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,8 @@ public class RatingCharacter : TemplatedControl
|
||||
|
||||
private Control? _icon;
|
||||
|
||||
public static readonly StyledProperty<bool> AllowHalfProperty = Rating.AllowHalfProperty.AddOwner<RatingCharacter>();
|
||||
public static readonly StyledProperty<bool> AllowHalfProperty =
|
||||
Rating.AllowHalfProperty.AddOwner<RatingCharacter>();
|
||||
|
||||
public bool AllowHalf
|
||||
{
|
||||
@@ -41,12 +42,12 @@ public class RatingCharacter : TemplatedControl
|
||||
}
|
||||
}
|
||||
|
||||
internal double Ratio { get; set; }
|
||||
internal double Ratio { get; set; } = 1;
|
||||
|
||||
protected override void OnLoaded(RoutedEventArgs e)
|
||||
{
|
||||
base.OnLoaded(e);
|
||||
AdjustWidth();
|
||||
ApplyRatio();
|
||||
}
|
||||
|
||||
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
|
||||
@@ -58,7 +59,7 @@ public class RatingCharacter : TemplatedControl
|
||||
protected override void OnPointerEntered(PointerEventArgs e)
|
||||
{
|
||||
var parent = this.GetLogicalAncestors().OfType<Rating>().FirstOrDefault();
|
||||
parent?.Preview(this);
|
||||
parent?.PointerEnteredHandler(this);
|
||||
}
|
||||
|
||||
protected override void OnPointerMoved(PointerEventArgs e)
|
||||
@@ -72,7 +73,6 @@ public class RatingCharacter : TemplatedControl
|
||||
{
|
||||
var parent = this.GetLogicalAncestors().OfType<Rating>().FirstOrDefault();
|
||||
parent?.UpdateItemsByValue(parent.Value);
|
||||
parent?.AdjustWidth(parent.Value);
|
||||
}
|
||||
|
||||
protected override void OnPointerReleased(PointerReleasedEventArgs e)
|
||||
@@ -81,12 +81,12 @@ public class RatingCharacter : TemplatedControl
|
||||
parent?.PointerReleasedHandler(this);
|
||||
}
|
||||
|
||||
internal void Select(bool value)
|
||||
internal void SetSelectedState(bool value)
|
||||
{
|
||||
PseudoClasses.Set(PC_Selected, value);
|
||||
}
|
||||
|
||||
internal void AdjustWidth()
|
||||
internal void ApplyRatio()
|
||||
{
|
||||
if (_icon is not null)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user