feat: WIP.
This commit is contained in:
@@ -14,7 +14,7 @@ public partial class RatingDemoViewModel : ViewModelBase
|
|||||||
|
|
||||||
// [ObservableProperty] private object _character;
|
// [ObservableProperty] private object _character;
|
||||||
[ObservableProperty] private int _count = 10;
|
[ObservableProperty] private int _count = 10;
|
||||||
[ObservableProperty] private double _defaultValue = 5;
|
[ObservableProperty] private double _defaultValue = 5.5;
|
||||||
|
|
||||||
public ObservableCollection<string> Tooltips { get; set; } = ["1", "2", "3", "4", "5"];
|
public ObservableCollection<string> Tooltips { get; set; } = ["1", "2", "3", "4", "5"];
|
||||||
}
|
}
|
||||||
@@ -3,16 +3,29 @@
|
|||||||
xmlns:u="https://irihi.tech/ursa">
|
xmlns:u="https://irihi.tech/ursa">
|
||||||
<ControlTheme x:Key="{x:Type u:RatingCharacter}" TargetType="u:RatingCharacter">
|
<ControlTheme x:Key="{x:Type u:RatingCharacter}" TargetType="u:RatingCharacter">
|
||||||
<Setter Property="Foreground" Value="{DynamicResource RatingCharacterUnSelectedForeground}" />
|
<Setter Property="Foreground" Value="{DynamicResource RatingCharacterUnSelectedForeground}" />
|
||||||
|
<Setter Property="Background" Value="{DynamicResource RatingCharacterUnSelectedForeground}" />
|
||||||
<Setter Property="Cursor" Value="Hand" />
|
<Setter Property="Cursor" Value="Hand" />
|
||||||
<Setter Property="VerticalAlignment" Value="Stretch" />
|
<Setter Property="VerticalAlignment" Value="Stretch" />
|
||||||
<Setter Property="Template">
|
<Setter Property="Template">
|
||||||
<ControlTemplate TargetType="u:RatingCharacter">
|
<ControlTemplate TargetType="u:RatingCharacter">
|
||||||
<PathIcon Name="{x:Static u:RatingCharacter.PART_IconGlyph}"
|
<!-- <Border Margin="0 0 6 0"> -->
|
||||||
Width="24"
|
<Canvas Width="24" Height="24">
|
||||||
Height="24"
|
<Path Width="24"
|
||||||
Margin="0 0 6 0"
|
Height="24"
|
||||||
Data="{DynamicResource RatingStarIconGlyph}"
|
Data="{DynamicResource RatingStarIconGlyph}"
|
||||||
Foreground="{TemplateBinding Foreground}" />
|
Fill="{TemplateBinding Background}" />
|
||||||
|
<Border Name="{x:Static u:RatingCharacter.PART_IconGlyph}"
|
||||||
|
IsVisible="True"
|
||||||
|
ClipToBounds="True">
|
||||||
|
<Path Width="24"
|
||||||
|
Height="24"
|
||||||
|
HorizontalAlignment="Left"
|
||||||
|
Data="{DynamicResource RatingStarIconGlyph}"
|
||||||
|
Fill="{TemplateBinding Foreground}" />
|
||||||
|
</Border>
|
||||||
|
</Canvas>
|
||||||
|
<!-- </Border> -->
|
||||||
|
|
||||||
</ControlTemplate>
|
</ControlTemplate>
|
||||||
</Setter>
|
</Setter>
|
||||||
<Style Selector="^:pointerover">
|
<Style Selector="^:pointerover">
|
||||||
@@ -21,6 +34,14 @@
|
|||||||
<Style Selector="^:selected">
|
<Style Selector="^:selected">
|
||||||
<Setter Property="Foreground" Value="{DynamicResource RatingCharacterSelectedForeground}" />
|
<Setter Property="Foreground" Value="{DynamicResource RatingCharacterSelectedForeground}" />
|
||||||
</Style>
|
</Style>
|
||||||
|
<Style Selector="^:half">
|
||||||
|
<!-- <Setter Property="Foreground"> -->
|
||||||
|
<!-- <LinearGradientBrush StartPoint="0%,0%" EndPoint="0%,100%"> -->
|
||||||
|
<!-- <GradientStop Color="#6b4c1b" Offset="0" /> -->
|
||||||
|
<!-- <GradientStop Color="#291e10" Offset="1" /> -->
|
||||||
|
<!-- </LinearGradientBrush> -->
|
||||||
|
<!-- </Setter> -->
|
||||||
|
</Style>
|
||||||
</ControlTheme>
|
</ControlTheme>
|
||||||
|
|
||||||
<ControlTheme x:Key="{x:Type u:Rating}" TargetType="u:Rating">
|
<ControlTheme x:Key="{x:Type u:Rating}" TargetType="u:Rating">
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ 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.0001;
|
||||||
|
|
||||||
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);
|
||||||
@@ -217,7 +218,13 @@ public class Rating : TemplatedControl
|
|||||||
public void Select(RatingCharacter o)
|
public void Select(RatingCharacter o)
|
||||||
{
|
{
|
||||||
var index = Items.IndexOf(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);
|
UpdateItems(-1);
|
||||||
SetCurrentValue(ValueProperty, 0);
|
SetCurrentValue(ValueProperty, 0);
|
||||||
@@ -225,7 +232,7 @@ public class Rating : TemplatedControl
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
UpdateItems(index);
|
UpdateItems(index);
|
||||||
SetCurrentValue(ValueProperty, index + 1);
|
SetCurrentValue(ValueProperty, newValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,35 @@ using Avalonia.LogicalTree;
|
|||||||
|
|
||||||
namespace Ursa.Controls;
|
namespace Ursa.Controls;
|
||||||
|
|
||||||
[PseudoClasses(PC_Selected)]
|
[PseudoClasses(PC_Selected, PC_Half)]
|
||||||
[TemplatePart(PART_IconGlyph, typeof(PathIcon))]
|
[TemplatePart(PART_IconGlyph, typeof(Control))]
|
||||||
public class RatingCharacter : TemplatedControl
|
public class RatingCharacter : TemplatedControl
|
||||||
{
|
{
|
||||||
public const string PART_IconGlyph = "PART_IconGlyph";
|
public const string PART_IconGlyph = "PART_IconGlyph";
|
||||||
protected const string PC_Selected = ":selected";
|
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<Control>(PART_IconGlyph);
|
||||||
|
}
|
||||||
|
|
||||||
protected override void OnPointerEntered(PointerEventArgs e)
|
protected override void OnPointerEntered(PointerEventArgs e)
|
||||||
{
|
{
|
||||||
@@ -19,6 +42,27 @@ public class RatingCharacter : TemplatedControl
|
|||||||
parent?.Preview(this);
|
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)
|
protected override void OnPointerReleased(PointerReleasedEventArgs e)
|
||||||
{
|
{
|
||||||
var parent = this.GetLogicalAncestors().OfType<Rating>().FirstOrDefault();
|
var parent = this.GetLogicalAncestors().OfType<Rating>().FirstOrDefault();
|
||||||
|
|||||||
Reference in New Issue
Block a user