feat: optimize.
This commit is contained in:
@@ -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 }"
|
||||||
|
|||||||
@@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -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)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user