using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using HandyControl.Data; using HandyControl.Tools.Extension; namespace HandyControl.Controls; [TemplatePart(Name = ElementIcon, Type = typeof(FrameworkElement))] public class RateItem : Control { private const string ElementIcon = "PART_Icon"; public static readonly DependencyProperty AllowClearProperty = Rate.AllowClearProperty.AddOwner(typeof(RateItem)); public static readonly DependencyProperty AllowHalfProperty = Rate.AllowHalfProperty.AddOwner(typeof(RateItem), new PropertyMetadata(OnAllowHalfChanged)); public static readonly DependencyProperty IconProperty = Rate.IconProperty.AddOwner(typeof(RateItem)); public static readonly DependencyProperty IsReadOnlyProperty = Rate.IsReadOnlyProperty.AddOwner(typeof(RateItem)); internal static readonly DependencyProperty IsSelectedProperty = DependencyProperty.Register( nameof(IsSelected), typeof(bool), typeof(RateItem), new PropertyMetadata(ValueBoxes.FalseBox, OnIsSelectedChanged)); public static readonly RoutedEvent SelectedChangedEvent = EventManager.RegisterRoutedEvent("SelectedChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(RateItem)); public static readonly RoutedEvent ValueChangedEvent = EventManager.RegisterRoutedEvent("ValueChanged", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(RateItem)); private FrameworkElement _icon; private bool _isHalf; private bool _isLoaded; private bool _isMouseLeftButtonDown; private bool _isSentValue; public RateItem() { Loaded += (s, e) => { if (_isLoaded) return; _isLoaded = true; OnApplyTemplate(); }; } public bool AllowClear { get => (bool) GetValue(AllowClearProperty); set => SetValue(AllowClearProperty, ValueBoxes.BooleanBox(value)); } public bool AllowHalf { get => (bool) GetValue(AllowHalfProperty); set => SetValue(AllowHalfProperty, ValueBoxes.BooleanBox(value)); } public Geometry Icon { get => (Geometry) GetValue(IconProperty); set => SetValue(IconProperty, value); } internal bool IsSelected { get => (bool) GetValue(IsSelectedProperty); set => SetValue(IsSelectedProperty, ValueBoxes.BooleanBox(value)); } public bool IsReadOnly { get => (bool) GetValue(IsReadOnlyProperty); set => SetValue(IsReadOnlyProperty, ValueBoxes.BooleanBox(value)); } internal bool IsHalf { get => _isHalf; set { if (_isHalf == value) return; _isHalf = value; if (_icon == null) return; _icon.Width = value ? Width / 2 : Width; } } internal int Index { get; set; } private static void OnAllowHalfChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var ctl = (RateItem) d; ctl.HandleMouseMoveEvent((bool) e.NewValue); } private static void OnIsSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var ctl = (RateItem) d; ctl._icon?.Show((bool) e.NewValue); } public event RoutedEventHandler SelectedChanged { add => AddHandler(SelectedChangedEvent, value); remove => RemoveHandler(SelectedChangedEvent, value); } public event RoutedEventHandler ValueChanged { add => AddHandler(ValueChangedEvent, value); remove => RemoveHandler(ValueChangedEvent, value); } private void HandleMouseMoveEvent(bool handle) { if (handle) { MouseMove += RateItem_MouseMove; } else { MouseMove -= RateItem_MouseMove; } } private void RateItem_MouseMove(object sender, MouseEventArgs e) { if (IsReadOnly) return; if (!AllowHalf) return; var p = e.GetPosition(this); IsHalf = p.X < Width / 2; } public override void OnApplyTemplate() { base.OnApplyTemplate(); _icon = GetTemplateChild(ElementIcon) as FrameworkElement; if (_isLoaded) { if (_icon == null) return; _icon.Show(IsSelected); _icon.Width = IsHalf ? Width / 2 : Width; } } protected override void OnMouseEnter(MouseEventArgs e) { base.OnMouseEnter(e); if (IsReadOnly) return; _isSentValue = false; IsSelected = true; RaiseEvent(new RoutedEventArgs(SelectedChangedEvent) { Source = this }); } protected override void OnMouseLeftButtonDown(MouseButtonEventArgs e) { base.OnMouseLeftButtonDown(e); if (IsReadOnly) return; _isMouseLeftButtonDown = true; } protected override void OnMouseLeave(MouseEventArgs e) { base.OnMouseLeave(e); if (IsReadOnly) return; _isMouseLeftButtonDown = false; } protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e) { base.OnMouseLeftButtonUp(e); if (IsReadOnly) return; if (_isMouseLeftButtonDown) { if (Index == 1 && AllowClear) { if (IsSelected) { if (!_isSentValue) { RaiseEvent(new RoutedEventArgs(ValueChangedEvent) { Source = this }); _isMouseLeftButtonDown = false; _isSentValue = true; return; } _isSentValue = false; IsSelected = false; IsHalf = false; } else { IsSelected = true; if (AllowHalf) { var p = e.GetPosition(this); IsHalf = p.X < Width / 2; } } } RaiseEvent(new RoutedEventArgs(ValueChangedEvent) { Source = this }); _isMouseLeftButtonDown = false; } } }