feat: optimize.

This commit is contained in:
Zhang Dian
2024-06-06 21:52:22 +08:00
parent ee2e4c4395
commit e5628f7f23
3 changed files with 42 additions and 36 deletions

View File

@@ -15,6 +15,7 @@
<Grid Grid.Column="0"> <Grid Grid.Column="0">
<StackPanel> <StackPanel>
<u:Rating <u:Rating
HorizontalAlignment="Center"
AllowClear="{Binding AllowClear }" AllowClear="{Binding AllowClear }"
AllowHalf="{Binding AllowHalf }" AllowHalf="{Binding AllowHalf }"
AllowFocus="{Binding AllowFocus }" AllowFocus="{Binding AllowFocus }"

View File

@@ -5,7 +5,6 @@ using Avalonia.Controls.Metadata;
using Avalonia.Controls.Primitives; using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using Avalonia.Data; using Avalonia.Data;
using Avalonia.Interactivity;
namespace Ursa.Controls; namespace Ursa.Controls;
@@ -17,7 +16,6 @@ public class Rating : TemplatedControl
protected const string PC_Selected = ":selected"; protected const string PC_Selected = ":selected";
private ItemsControl? _itemsControl; private ItemsControl? _itemsControl;
private const double Tolerance = 0.00000001;
public static readonly StyledProperty<double> ValueProperty = public static readonly StyledProperty<double> ValueProperty =
AvaloniaProperty.Register<Rating, double>(nameof(Value), defaultBindingMode: BindingMode.TwoWay); AvaloniaProperty.Register<Rating, double>(nameof(Value), defaultBindingMode: BindingMode.TwoWay);
@@ -120,7 +118,6 @@ public class Rating : TemplatedControl
if (e.NewValue is double newValue) if (e.NewValue is double newValue)
{ {
UpdateItemsByValue(newValue); UpdateItemsByValue(newValue);
AdjustWidth(newValue);
} }
} }
@@ -148,13 +145,12 @@ public class Rating : TemplatedControl
} }
} }
UpdateItemsByValue(Value);
foreach (var item in Items) foreach (var item in Items)
{ {
item.AllowHalf = AllowHalf; item.AllowHalf = AllowHalf;
} }
AdjustWidth(Value); UpdateItemsByValue(Value);
} }
private void OnAllowHalfChanged(AvaloniaPropertyChangedEventArgs e) private void OnAllowHalfChanged(AvaloniaPropertyChangedEventArgs e)
@@ -166,7 +162,6 @@ public class Rating : TemplatedControl
} }
UpdateItemsByValue(Value); UpdateItemsByValue(Value);
AdjustWidth(Value);
} }
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
@@ -183,12 +178,19 @@ public class Rating : TemplatedControl
{ {
item.AllowHalf = AllowHalf; item.AllowHalf = AllowHalf;
} }
SetCurrentValue(ValueProperty, DefaultValue); SetCurrentValue(ValueProperty, DefaultValue);
} }
public void Preview(RatingCharacter o) internal void PointerEnteredHandler(RatingCharacter o)
{ {
var index = Items.IndexOf(o); var index = Items.IndexOf(o);
var item = Items.FirstOrDefault(item => item.IsLast);
if (item is not null)
{
item.IsHalf = false;
}
UpdateItemsByIndex(index); UpdateItemsByIndex(index);
} }
@@ -201,7 +203,7 @@ public class Rating : TemplatedControl
newValue = index + 0.5; newValue = index + 0.5;
} }
if (AllowClear && Math.Abs(Value - newValue) < Tolerance) if (AllowClear && Math.Abs(Value - newValue) < double.Epsilon)
{ {
SetCurrentValue(ValueProperty, 0); SetCurrentValue(ValueProperty, 0);
} }
@@ -213,40 +215,43 @@ public class Rating : TemplatedControl
internal void UpdateItemsByValue(double newValue) internal void UpdateItemsByValue(double newValue)
{ {
RestorePreviousLastItem();
var index = (int)Math.Ceiling(newValue - 1); var index = (int)Math.Ceiling(newValue - 1);
UpdateItemsByIndex(index); 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) private void UpdateItemsByIndex(int index)
{ {
for (var i = 0; i < Items.Count; i++) for (var i = 0; i < Items.Count; i++)
{ {
if (i == index) continue; Items[i].SetSelectedState(i <= index);
Items[i].Select(i < index); Items[i].IsLast = i == index;
Items[i].IsLast = false;
Items[i].IsHalf = false;
Items[i].Ratio = 1;
} }
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;
} }
private void UpdateChosenItem(double newValue)
internal void AdjustWidth(double newValue)
{ {
var ratio = Math.Abs(newValue - Math.Floor(newValue)); var ratio = newValue - Math.Floor(newValue);
var isInt = ratio < Tolerance; var isFraction = ratio >= double.Epsilon;
ratio = AllowHalf && !isInt ? ratio : 1; ratio = AllowHalf && isFraction ? ratio : 1;
foreach (var item in Items) var item = Items.FirstOrDefault(item => item.IsLast);
if (item is null) return;
if (!AllowHalf && isFraction)
{ {
item.Ratio = item.IsLast ? ratio : 1; item.SetSelectedState(false);
item.AdjustWidth();
} }
item.Ratio = ratio;
item.ApplyRatio();
} }
} }

View File

@@ -17,7 +17,8 @@ public class RatingCharacter : TemplatedControl
private Control? _icon; 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 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) protected override void OnLoaded(RoutedEventArgs e)
{ {
base.OnLoaded(e); base.OnLoaded(e);
AdjustWidth(); ApplyRatio();
} }
protected override void OnApplyTemplate(TemplateAppliedEventArgs e) protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
@@ -58,7 +59,7 @@ public class RatingCharacter : TemplatedControl
protected override void OnPointerEntered(PointerEventArgs e) protected override void OnPointerEntered(PointerEventArgs e)
{ {
var parent = this.GetLogicalAncestors().OfType<Rating>().FirstOrDefault(); var parent = this.GetLogicalAncestors().OfType<Rating>().FirstOrDefault();
parent?.Preview(this); parent?.PointerEnteredHandler(this);
} }
protected override void OnPointerMoved(PointerEventArgs e) protected override void OnPointerMoved(PointerEventArgs e)
@@ -72,7 +73,6 @@ public class RatingCharacter : TemplatedControl
{ {
var parent = this.GetLogicalAncestors().OfType<Rating>().FirstOrDefault(); var parent = this.GetLogicalAncestors().OfType<Rating>().FirstOrDefault();
parent?.UpdateItemsByValue(parent.Value); parent?.UpdateItemsByValue(parent.Value);
parent?.AdjustWidth(parent.Value);
} }
protected override void OnPointerReleased(PointerReleasedEventArgs e) protected override void OnPointerReleased(PointerReleasedEventArgs e)
@@ -81,12 +81,12 @@ public class RatingCharacter : TemplatedControl
parent?.PointerReleasedHandler(this); parent?.PointerReleasedHandler(this);
} }
internal void Select(bool value) internal void SetSelectedState(bool value)
{ {
PseudoClasses.Set(PC_Selected, value); PseudoClasses.Set(PC_Selected, value);
} }
internal void AdjustWidth() internal void ApplyRatio()
{ {
if (_icon is not null) if (_icon is not null)
{ {