| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263 |
- using System;
- using Avalonia.Controls.Primitives;
- using Avalonia.Input;
- using Avalonia.Interactivity;
- namespace Avalonia.Controls
- {
- public enum Location
- {
- Left,
- Right
- }
- /// <summary>
- /// Represents a spinner control that includes two Buttons.
- /// </summary>
- public class ButtonSpinner : Spinner
- {
- /// <summary>
- /// Defines the <see cref="AllowSpin"/> property.
- /// </summary>
- public static readonly StyledProperty<bool> AllowSpinProperty =
- AvaloniaProperty.Register<ButtonSpinner, bool>(nameof(AllowSpin), true);
- /// <summary>
- /// Defines the <see cref="ShowButtonSpinner"/> property.
- /// </summary>
- public static readonly StyledProperty<bool> ShowButtonSpinnerProperty =
- AvaloniaProperty.Register<ButtonSpinner, bool>(nameof(ShowButtonSpinner), true);
- /// <summary>
- /// Defines the <see cref="ButtonSpinnerLocation"/> property.
- /// </summary>
- public static readonly StyledProperty<Location> ButtonSpinnerLocationProperty =
- AvaloniaProperty.Register<ButtonSpinner, Location>(nameof(ButtonSpinnerLocation), Location.Right);
- private Button _decreaseButton;
- /// <summary>
- /// Gets or sets the DecreaseButton template part.
- /// </summary>
- private Button DecreaseButton
- {
- get { return _decreaseButton; }
- set
- {
- if (_decreaseButton != null)
- {
- _decreaseButton.Click -= OnButtonClick;
- }
- _decreaseButton = value;
- if (_decreaseButton != null)
- {
- _decreaseButton.Click += OnButtonClick;
- }
- }
- }
- private Button _increaseButton;
- /// <summary>
- /// Gets or sets the IncreaseButton template part.
- /// </summary>
- private Button IncreaseButton
- {
- get
- {
- return _increaseButton;
- }
- set
- {
- if (_increaseButton != null)
- {
- _increaseButton.Click -= OnButtonClick;
- }
- _increaseButton = value;
- if (_increaseButton != null)
- {
- _increaseButton.Click += OnButtonClick;
- }
- }
- }
- /// <summary>
- /// Initializes static members of the <see cref="ButtonSpinner"/> class.
- /// </summary>
- static ButtonSpinner()
- {
- AllowSpinProperty.Changed.Subscribe(AllowSpinChanged);
- PseudoClass(ButtonSpinnerLocationProperty, location => location == Location.Left, ":left");
- PseudoClass(ButtonSpinnerLocationProperty, location => location == Location.Right, ":right");
- }
- /// <summary>
- /// Gets or sets a value indicating whether the <see cref="ButtonSpinner"/> should allow to spin.
- /// </summary>
- public bool AllowSpin
- {
- get { return GetValue(AllowSpinProperty); }
- set { SetValue(AllowSpinProperty, value); }
- }
- /// <summary>
- /// Gets or sets a value indicating whether the spin buttons should be shown.
- /// </summary>
- public bool ShowButtonSpinner
- {
- get { return GetValue(ShowButtonSpinnerProperty); }
- set { SetValue(ShowButtonSpinnerProperty, value); }
- }
- /// <summary>
- /// Gets or sets current location of the <see cref="ButtonSpinner"/>.
- /// </summary>
- public Location ButtonSpinnerLocation
- {
- get { return GetValue(ButtonSpinnerLocationProperty); }
- set { SetValue(ButtonSpinnerLocationProperty, value); }
- }
- /// <inheritdoc />
- protected override void OnTemplateApplied(TemplateAppliedEventArgs e)
- {
- IncreaseButton = e.NameScope.Find<Button>("PART_IncreaseButton");
- DecreaseButton = e.NameScope.Find<Button>("PART_DecreaseButton");
- SetButtonUsage();
- }
- /// <inheritdoc />
- protected override void OnPointerReleased(PointerReleasedEventArgs e)
- {
- base.OnPointerReleased(e);
- Point mousePosition;
- if (IncreaseButton != null && IncreaseButton.IsEnabled == false)
- {
- mousePosition = e.GetPosition(IncreaseButton);
- if (mousePosition.X > 0 && mousePosition.X < IncreaseButton.Width &&
- mousePosition.Y > 0 && mousePosition.Y < IncreaseButton.Height)
- {
- e.Handled = true;
- }
- }
- if (DecreaseButton != null && DecreaseButton.IsEnabled == false)
- {
- mousePosition = e.GetPosition(DecreaseButton);
- if (mousePosition.X > 0 && mousePosition.X < DecreaseButton.Width &&
- mousePosition.Y > 0 && mousePosition.Y < DecreaseButton.Height)
- {
- e.Handled = true;
- }
- }
- }
- /// <inheritdoc />
- protected override void OnKeyDown(KeyEventArgs e)
- {
- switch (e.Key)
- {
- case Key.Up:
- {
- if (AllowSpin)
- {
- OnSpin(new SpinEventArgs(SpinEvent, SpinDirection.Increase));
- e.Handled = true;
- }
- break;
- }
- case Key.Down:
- {
- if (AllowSpin)
- {
- OnSpin(new SpinEventArgs(SpinEvent, SpinDirection.Decrease));
- e.Handled = true;
- }
- break;
- }
- case Key.Enter:
- {
- //Do not Spin on enter Key when spinners have focus
- if (((IncreaseButton != null) && (IncreaseButton.IsFocused))
- || ((DecreaseButton != null) && DecreaseButton.IsFocused))
- {
- e.Handled = true;
- }
- break;
- }
- }
- }
- /// <inheritdoc />
- protected override void OnPointerWheelChanged(PointerWheelEventArgs e)
- {
- base.OnPointerWheelChanged(e);
- if (!e.Handled && AllowSpin)
- {
- if (e.Delta.Y != 0)
- {
- var spinnerEventArgs = new SpinEventArgs(SpinEvent, (e.Delta.Y < 0) ? SpinDirection.Decrease : SpinDirection.Increase, true);
- OnSpin(spinnerEventArgs);
- e.Handled = spinnerEventArgs.Handled;
- }
- }
- }
- protected override void OnValidSpinDirectionChanged(ValidSpinDirections oldValue, ValidSpinDirections newValue)
- {
- SetButtonUsage();
- }
- /// <summary>
- /// Called when the <see cref="AllowSpin"/> property value changed.
- /// </summary>
- /// <param name="oldValue">The old value.</param>
- /// <param name="newValue">The new value.</param>
- protected virtual void OnAllowSpinChanged(bool oldValue, bool newValue)
- {
- SetButtonUsage();
- }
- /// <summary>
- /// Called when the <see cref="AllowSpin"/> property value changed.
- /// </summary>
- /// <param name="e">The event args.</param>
- private static void AllowSpinChanged(AvaloniaPropertyChangedEventArgs e)
- {
- if (e.Sender is ButtonSpinner spinner)
- {
- var oldValue = (bool)e.OldValue;
- var newValue = (bool)e.NewValue;
- spinner.OnAllowSpinChanged(oldValue, newValue);
- }
- }
-
- /// <summary>
- /// Disables or enables the buttons based on the valid spin direction.
- /// </summary>
- private void SetButtonUsage()
- {
- if (IncreaseButton != null)
- {
- IncreaseButton.IsEnabled = AllowSpin && ((ValidSpinDirection & ValidSpinDirections.Increase) == ValidSpinDirections.Increase);
- }
- if (DecreaseButton != null)
- {
- DecreaseButton.IsEnabled = AllowSpin && ((ValidSpinDirection & ValidSpinDirections.Decrease) == ValidSpinDirections.Decrease);
- }
- }
- /// <summary>
- /// Called when user clicks one of the spin buttons.
- /// </summary>
- /// <param name="sender">The event sender.</param>
- /// <param name="e">The event args.</param>
- private void OnButtonClick(object sender, RoutedEventArgs e)
- {
- if (AllowSpin)
- {
- var direction = sender == IncreaseButton ? SpinDirection.Increase : SpinDirection.Decrease;
- OnSpin(new SpinEventArgs(SpinEvent, direction));
- }
- }
- }
- }
|