From 0a30d01b7dc18f4c21bc4d2c4dc5d281be5a80ea Mon Sep 17 00:00:00 2001 From: Zhang Dian <54255897+zdpcdt@users.noreply.github.com> Date: Tue, 4 Jun 2024 09:11:22 +0800 Subject: [PATCH] feat: WIP. --- .../ViewModels/RatingDemoViewModel.cs | 2 +- src/Ursa.Themes.Semi/Controls/Rating.axaml | 33 ++++++++++--- src/Ursa/Controls/Rating/Rating.cs | 11 ++++- src/Ursa/Controls/Rating/RatingCharacter.cs | 48 ++++++++++++++++++- 4 files changed, 83 insertions(+), 11 deletions(-) diff --git a/demo/Ursa.Demo/ViewModels/RatingDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/RatingDemoViewModel.cs index 20aa9e7..5911125 100644 --- a/demo/Ursa.Demo/ViewModels/RatingDemoViewModel.cs +++ b/demo/Ursa.Demo/ViewModels/RatingDemoViewModel.cs @@ -14,7 +14,7 @@ public partial class RatingDemoViewModel : ViewModelBase // [ObservableProperty] private object _character; [ObservableProperty] private int _count = 10; - [ObservableProperty] private double _defaultValue = 5; + [ObservableProperty] private double _defaultValue = 5.5; public ObservableCollection Tooltips { get; set; } = ["1", "2", "3", "4", "5"]; } \ No newline at end of file diff --git a/src/Ursa.Themes.Semi/Controls/Rating.axaml b/src/Ursa.Themes.Semi/Controls/Rating.axaml index 39390c4..6a8fb81 100644 --- a/src/Ursa.Themes.Semi/Controls/Rating.axaml +++ b/src/Ursa.Themes.Semi/Controls/Rating.axaml @@ -3,16 +3,29 @@ xmlns:u="https://irihi.tech/ursa"> + - + + + + + + + + + + diff --git a/src/Ursa/Controls/Rating/Rating.cs b/src/Ursa/Controls/Rating/Rating.cs index 37b5a84..98648ff 100644 --- a/src/Ursa/Controls/Rating/Rating.cs +++ b/src/Ursa/Controls/Rating/Rating.cs @@ -19,6 +19,7 @@ public class Rating : TemplatedControl protected const string PC_Selected = ":selected"; private ItemsControl? _itemsControl; + private const double Tolerance = 0.0001; public static readonly StyledProperty ValueProperty = AvaloniaProperty.Register(nameof(Value), defaultBindingMode: BindingMode.TwoWay); @@ -217,7 +218,13 @@ public class Rating : TemplatedControl public void Select(RatingCharacter o) { var index = Items.IndexOf(o); - if (AllowClear && index == (int)Value - 1) + double newValue = index + 1; + if (o.IsHalf) + { + newValue = index + 0.5; + } + + if (AllowClear && Math.Abs(Value - newValue) < Tolerance) { UpdateItems(-1); SetCurrentValue(ValueProperty, 0); @@ -225,7 +232,7 @@ public class Rating : TemplatedControl else { UpdateItems(index); - SetCurrentValue(ValueProperty, index + 1); + SetCurrentValue(ValueProperty, newValue); } } diff --git a/src/Ursa/Controls/Rating/RatingCharacter.cs b/src/Ursa/Controls/Rating/RatingCharacter.cs index 44cc6c9..50344a5 100644 --- a/src/Ursa/Controls/Rating/RatingCharacter.cs +++ b/src/Ursa/Controls/Rating/RatingCharacter.cs @@ -6,12 +6,35 @@ using Avalonia.LogicalTree; namespace Ursa.Controls; -[PseudoClasses(PC_Selected)] -[TemplatePart(PART_IconGlyph, typeof(PathIcon))] +[PseudoClasses(PC_Selected, PC_Half)] +[TemplatePart(PART_IconGlyph, typeof(Control))] public class RatingCharacter : TemplatedControl { public const string PART_IconGlyph = "PART_IconGlyph"; protected const string PC_Selected = ":selected"; + protected const string PC_Half = ":half"; + + private Control? _icon; + + private bool _isHalf; + + internal bool IsHalf + { + get => _isHalf; + set + { + if (_isHalf == value) return; + _isHalf = value; + if (_icon is null) return; + _icon.Width = value ? Bounds.Width / 2 : Bounds.Width; + } + } + + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) + { + base.OnApplyTemplate(e); + _icon = e.NameScope.Find(PART_IconGlyph); + } protected override void OnPointerEntered(PointerEventArgs e) { @@ -19,6 +42,27 @@ public class RatingCharacter : TemplatedControl parent?.Preview(this); } + protected override void OnPointerMoved(PointerEventArgs e) + { + var p = e.GetPosition(this); + var flag = p.X < Bounds.Width / 2; + PseudoClasses.Set(PC_Half, flag); + IsHalf = flag; + // if (flag) + // { + // _icon.Width = Bounds.Width / 2; + // } + // else + // { + // _icon.Width = Bounds.Width; + // } + } + + // protected override void OnPointerExited(PointerEventArgs e) + // { + // // _icon.Width = Bounds.Width; + // } + protected override void OnPointerReleased(PointerReleasedEventArgs e) { var parent = this.GetLogicalAncestors().OfType().FirstOrDefault();