csharpc-sharpdotnetxamlavaloniauicross-platformcross-platform-xamlavaloniaguimulti-platformuser-interfacedotnetcore
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
263 lines
9.0 KiB
263 lines
9.0 KiB
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<ButtonSpinner, Location>(ButtonSpinnerLocationProperty, location => location == Location.Left, ":left");
|
|
PseudoClass<ButtonSpinner, Location>(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));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|