|
|
@@ -0,0 +1,258 @@
|
|
|
+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;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ /// <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));
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|