using System;
using Avalonia.Data;
using Avalonia.Interactivity;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Threading;
using Avalonia.Controls.Metadata;
using Avalonia.Automation.Peers;
namespace Avalonia.Controls.Primitives
{
public class ScrollEventArgs : EventArgs
{
public ScrollEventArgs(ScrollEventType eventType, double newValue)
{
ScrollEventType = eventType;
NewValue = newValue;
}
public double NewValue { get; private set; }
public ScrollEventType ScrollEventType { get; private set; }
}
///
/// A scrollbar control.
///
[TemplatePart("PART_LineDownButton", typeof(Button))]
[TemplatePart("PART_LineUpButton", typeof(Button))]
[TemplatePart("PART_PageDownButton", typeof(Button))]
[TemplatePart("PART_PageUpButton", typeof(Button))]
[PseudoClasses(":vertical", ":horizontal")]
public class ScrollBar : RangeBase
{
///
/// Defines the property.
///
public static readonly StyledProperty ViewportSizeProperty =
AvaloniaProperty.Register(nameof(ViewportSize), defaultValue: double.NaN);
///
/// Defines the property.
///
public static readonly StyledProperty VisibilityProperty =
AvaloniaProperty.Register(nameof(Visibility), ScrollBarVisibility.Visible);
///
/// Defines the property.
///
public static readonly StyledProperty OrientationProperty =
AvaloniaProperty.Register(nameof(Orientation), Orientation.Vertical);
///
/// Defines the property.
///
public static readonly DirectProperty IsExpandedProperty =
AvaloniaProperty.RegisterDirect(
nameof(IsExpanded),
o => o.IsExpanded);
///
/// Defines the property.
///
public static readonly StyledProperty AllowAutoHideProperty =
AvaloniaProperty.Register(nameof(AllowAutoHide), true);
///
/// Defines the property.
///
public static readonly StyledProperty HideDelayProperty =
AvaloniaProperty.Register(nameof(HideDelay), TimeSpan.FromSeconds(2));
///
/// Defines the property.
///
public static readonly StyledProperty ShowDelayProperty =
AvaloniaProperty.Register(nameof(ShowDelay), TimeSpan.FromSeconds(0.5));
private Button? _lineUpButton;
private Button? _lineDownButton;
private Button? _pageUpButton;
private Button? _pageDownButton;
private DispatcherTimer? _timer;
private bool _isExpanded;
///
/// Initializes static members of the class.
///
static ScrollBar()
{
Thumb.DragDeltaEvent.AddClassHandler((x, e) => x.OnThumbDragDelta(e), RoutingStrategies.Bubble);
Thumb.DragCompletedEvent.AddClassHandler((x, e) => x.OnThumbDragComplete(e), RoutingStrategies.Bubble);
}
///
/// Initializes a new instance of the class.
///
public ScrollBar()
{
UpdatePseudoClasses(Orientation);
}
///
/// Gets or sets the amount of the scrollable content that is currently visible.
///
public double ViewportSize
{
get { return GetValue(ViewportSizeProperty); }
set { SetValue(ViewportSizeProperty, value); }
}
///
/// Gets or sets a value that indicates whether the scrollbar should hide itself when it
/// is not needed.
///
public ScrollBarVisibility Visibility
{
get { return GetValue(VisibilityProperty); }
set { SetValue(VisibilityProperty, value); }
}
///
/// Gets or sets the orientation of the scrollbar.
///
public Orientation Orientation
{
get { return GetValue(OrientationProperty); }
set { SetValue(OrientationProperty, value); }
}
///
/// Gets a value that indicates whether the scrollbar is expanded.
///
public bool IsExpanded
{
get => _isExpanded;
private set => SetAndRaise(IsExpandedProperty, ref _isExpanded, value);
}
///
/// Gets a value that indicates whether the scrollbar can hide itself when user is not interacting with it.
///
public bool AllowAutoHide
{
get => GetValue(AllowAutoHideProperty);
set => SetValue(AllowAutoHideProperty, value);
}
///
/// Gets a value that determines how long will be the hide delay after user stops interacting with the scrollbar.
///
public TimeSpan HideDelay
{
get => GetValue(HideDelayProperty);
set => SetValue(HideDelayProperty, value);
}
///
/// Gets a value that determines how long will be the show delay when user starts interacting with the scrollbar.
///
public TimeSpan ShowDelay
{
get => GetValue(ShowDelayProperty);
set => SetValue(ShowDelayProperty, value);
}
public event EventHandler? Scroll;
///
/// Calculates and updates whether the scrollbar should be visible.
///
private void UpdateIsVisible()
{
var isVisible = Visibility switch
{
ScrollBarVisibility.Visible => true,
ScrollBarVisibility.Disabled => false,
ScrollBarVisibility.Hidden => false,
ScrollBarVisibility.Auto => (double.IsNaN(ViewportSize) || Maximum > 0),
_ => throw new InvalidOperationException("Invalid value for ScrollBar.Visibility.")
};
SetValue(IsVisibleProperty, isVisible);
}
protected override void OnKeyDown(KeyEventArgs e)
{
if (e.Key == Key.PageUp)
{
LargeDecrement();
e.Handled = true;
}
else if (e.Key == Key.PageDown)
{
LargeIncrement();
e.Handled = true;
}
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
if (change.Property == OrientationProperty)
{
UpdatePseudoClasses(change.GetNewValue());
}
else if (change.Property == AllowAutoHideProperty)
{
UpdateIsExpandedState();
}
else
{
if (change.Property == MinimumProperty ||
change.Property == MaximumProperty ||
change.Property == ViewportSizeProperty ||
change.Property == VisibilityProperty)
{
UpdateIsVisible();
}
}
}
protected override void OnPointerEntered(PointerEventArgs e)
{
base.OnPointerEntered(e);
if (AllowAutoHide)
{
ExpandAfterDelay();
}
}
protected override void OnPointerExited(PointerEventArgs e)
{
base.OnPointerExited(e);
if (AllowAutoHide)
{
CollapseAfterDelay();
}
}
protected override void OnApplyTemplate(TemplateAppliedEventArgs e)
{
if (_lineUpButton != null)
{
_lineUpButton.Click -= LineUpClick;
}
if (_lineDownButton != null)
{
_lineDownButton.Click -= LineDownClick;
}
if (_pageUpButton != null)
{
_pageUpButton.Click -= PageUpClick;
}
if (_pageDownButton != null)
{
_pageDownButton.Click -= PageDownClick;
}
_lineUpButton = e.NameScope.Find