diff --git a/demo/Ursa.Demo/Pages/RatingDemo.axaml b/demo/Ursa.Demo/Pages/RatingDemo.axaml index 856f02e..d7c9f7c 100644 --- a/demo/Ursa.Demo/Pages/RatingDemo.axaml +++ b/demo/Ursa.Demo/Pages/RatingDemo.axaml @@ -14,7 +14,6 @@ - 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 6a8fb81..0e84c51 100644 --- a/src/Ursa.Themes.Semi/Controls/Rating.axaml +++ b/src/Ursa.Themes.Semi/Controls/Rating.axaml @@ -3,7 +3,7 @@ xmlns:u="https://irihi.tech/ursa"> - + @@ -15,7 +15,6 @@ Data="{DynamicResource RatingStarIconGlyph}" Fill="{TemplateBinding Background}" /> - diff --git a/src/Ursa.Themes.Semi/Themes/Dark/Rating.axaml b/src/Ursa.Themes.Semi/Themes/Dark/Rating.axaml index d522d56..f9c4707 100644 --- a/src/Ursa.Themes.Semi/Themes/Dark/Rating.axaml +++ b/src/Ursa.Themes.Semi/Themes/Dark/Rating.axaml @@ -1,4 +1,5 @@ - - + + + \ No newline at end of file diff --git a/src/Ursa.Themes.Semi/Themes/Light/Rating.axaml b/src/Ursa.Themes.Semi/Themes/Light/Rating.axaml index 0b233f6..affa457 100644 --- a/src/Ursa.Themes.Semi/Themes/Light/Rating.axaml +++ b/src/Ursa.Themes.Semi/Themes/Light/Rating.axaml @@ -1,4 +1,5 @@ - - + + + \ No newline at end of file diff --git a/src/Ursa/Controls/Rating/Rating.cs b/src/Ursa/Controls/Rating/Rating.cs index 98648ff..1176daf 100644 --- a/src/Ursa/Controls/Rating/Rating.cs +++ b/src/Ursa/Controls/Rating/Rating.cs @@ -137,7 +137,11 @@ public class Rating : TemplatedControl private void OnValueChanged(AvaloniaPropertyChangedEventArgs e) { - UpdateItems((int)Value - 1); + if (e.NewValue is double newValue) + { + UpdateItemsByValue(newValue); + AdjustWidth(newValue); + } } private void OnCountChanged(AvaloniaPropertyChangedEventArgs e) @@ -164,10 +168,8 @@ public class Rating : TemplatedControl } } - if (Value > newCount) - { - SetCurrentValue(ValueProperty, Math.Max(newCount, 0)); - } + UpdateItemsByValue(Value); + AdjustWidth(Value); } protected override void OnApplyTemplate(TemplateAppliedEventArgs e) @@ -180,7 +182,6 @@ public class Rating : TemplatedControl Items.Add(new RatingCharacter()); } - UpdateItems((int)DefaultValue - 1); if (DefaultValue > Count) { SetCurrentValue(ValueProperty, Math.Max(Count, 0)); @@ -207,15 +208,15 @@ public class Rating : TemplatedControl } } - UpdateItems(index); + UpdateItemsByIndex(index); } protected override void OnPointerExited(PointerEventArgs e) { - UpdateItems((int)Value - 1); + UpdateItemsByValue(Value); } - public void Select(RatingCharacter o) + public void PointerReleasedHandler(RatingCharacter o) { var index = Items.IndexOf(o); double newValue = index + 1; @@ -226,23 +227,25 @@ public class Rating : TemplatedControl if (AllowClear && Math.Abs(Value - newValue) < Tolerance) { - UpdateItems(-1); + UpdateItemsByValue(-1); SetCurrentValue(ValueProperty, 0); } else { - UpdateItems(index); + UpdateItemsByValue(newValue); SetCurrentValue(ValueProperty, newValue); } } - private void UpdateItems(int index) + private void UpdateItemsByIndex(int index) { + var isInt = Math.Abs(Value - Math.Floor(Value)) < Tolerance; for (var i = 0; i <= index && i < Items.Count; i++) { if (Items[i] is RatingCharacter item) { item.Select(true); + item.IsHalf = !isInt && i == index; } } @@ -251,6 +254,34 @@ public class Rating : TemplatedControl if (Items[i] is RatingCharacter item) { item.Select(false); + item.IsHalf = false; + } + } + } + + private void UpdateItemsByValue(double newValue) + { + var index = (int)Math.Ceiling(newValue - 1); + UpdateItemsByIndex(index); + } + + private void AdjustWidth(double newValue) + { + var ratio = Math.Abs(newValue - Math.Floor(newValue)); + foreach (var character in Items) + { + if (character is RatingCharacter item) + { + if (item.IsHalf) + { + item.Ratio = ratio; + } + else + { + item.Ratio = 1; + } + + item.AdjustWidth(); } } } diff --git a/src/Ursa/Controls/Rating/RatingCharacter.cs b/src/Ursa/Controls/Rating/RatingCharacter.cs index 50344a5..4dea017 100644 --- a/src/Ursa/Controls/Rating/RatingCharacter.cs +++ b/src/Ursa/Controls/Rating/RatingCharacter.cs @@ -6,13 +6,12 @@ using Avalonia.LogicalTree; namespace Ursa.Controls; -[PseudoClasses(PC_Selected, PC_Half)] +[PseudoClasses(PC_Selected)] [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; @@ -23,13 +22,14 @@ public class RatingCharacter : TemplatedControl get => _isHalf; set { - if (_isHalf == value) return; _isHalf = value; if (_icon is null) return; - _icon.Width = value ? Bounds.Width / 2 : Bounds.Width; + _icon.Width = value ? Bounds.Width * 0.5 : Bounds.Width; } } + internal double Ratio { get; set; } + protected override void OnApplyTemplate(TemplateAppliedEventArgs e) { base.OnApplyTemplate(e); @@ -45,32 +45,25 @@ public class RatingCharacter : TemplatedControl 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; - // } + IsHalf = p.X < Bounds.Width * 0.5; } - // protected override void OnPointerExited(PointerEventArgs e) - // { - // // _icon.Width = Bounds.Width; - // } - protected override void OnPointerReleased(PointerReleasedEventArgs e) { var parent = this.GetLogicalAncestors().OfType().FirstOrDefault(); - parent?.Select(this); + parent?.PointerReleasedHandler(this); } public void Select(bool value) { PseudoClasses.Set(PC_Selected, value); } + + public void AdjustWidth() + { + if (_icon is not null) + { + _icon.Width = Bounds.Width * Ratio; + } + } } \ No newline at end of file