@ -45,6 +45,10 @@ namespace Avalonia.Controls.Primitives
public static readonly StyledProperty < bool > IgnoreThumbDragProperty =
AvaloniaProperty . Register < Track , bool > ( nameof ( IgnoreThumbDrag ) ) ;
public static readonly StyledProperty < bool > DeferThumbDragProperty =
AvaloniaProperty . Register < Track , bool > ( nameof ( DeferThumbDrag ) ) ;
private VectorEventArgs ? _d eferredThumbDrag ;
private Vector _l astDrag ;
static Track ( )
@ -78,6 +82,11 @@ namespace Avalonia.Controls.Primitives
set = > SetValue ( ValueProperty , value ) ;
}
/// <summary>
/// Gets the value of the <see cref="Thumb"/>'s current position. This can differ from <see cref="Value"/> when <see cref="ScrollViewer.IsDeferredScrollingEnabled"/> is true.
/// </summary>
private double ThumbValue = > Value + ( _d eferredThumbDrag = = null ? 0 : ValueFromDistance ( _d eferredThumbDrag . Vector . X , _d eferredThumbDrag . Vector . Y ) ) ;
public double ViewportSize
{
get = > GetValue ( ViewportSizeProperty ) ;
@ -121,6 +130,12 @@ namespace Avalonia.Controls.Primitives
set = > SetValue ( IgnoreThumbDragProperty , value ) ;
}
public bool DeferThumbDrag
{
get = > GetValue ( DeferThumbDragProperty ) ;
set = > SetValue ( DeferThumbDragProperty , value ) ;
}
private double ThumbCenterOffset { get ; set ; }
private double Density { get ; set ; }
@ -139,11 +154,11 @@ namespace Avalonia.Controls.Primitives
// Find distance from center of thumb to given point.
if ( Orientation = = Orientation . Horizontal )
{
val = Value + ValueFromDistance ( point . X - ThumbCenterOffset , point . Y - ( Bounds . Height * 0.5 ) ) ;
val = Thumb Value + ValueFromDistance ( point . X - ThumbCenterOffset , point . Y - ( Bounds . Height * 0.5 ) ) ;
}
else
{
val = Value + ValueFromDistance ( point . X - ( Bounds . Width * 0.5 ) , point . Y - ThumbCenterOffset ) ;
val = Thumb Value + ValueFromDistance ( point . X - ( Bounds . Width * 0.5 ) , point . Y - ThumbCenterOffset ) ;
}
return Math . Max ( Minimum , Math . Min ( Maximum , val ) ) ;
@ -291,6 +306,13 @@ namespace Avalonia.Controls.Primitives
{
UpdatePseudoClasses ( change . GetNewValue < Orientation > ( ) ) ;
}
else if ( change . Property = = DeferThumbDragProperty )
{
if ( ! change . GetNewValue < bool > ( ) )
{
ApplyDeferredThumbDrag ( ) ;
}
}
}
private Vector CalculateThumbAdjustment ( Thumb thumb , Rect newThumbBounds )
@ -315,7 +337,7 @@ namespace Avalonia.Controls.Primitives
{
double min = Minimum ;
double range = Math . Max ( 0.0 , Maximum - min ) ;
double offset = Math . Min ( range , Value - min ) ;
double offset = Math . Min ( range , Thumb Value - min ) ;
double trackLength ;
@ -348,7 +370,7 @@ namespace Avalonia.Controls.Primitives
{
var min = Minimum ;
var range = Math . Max ( 0.0 , Maximum - min ) ;
var offset = Math . Min ( range , Value - min ) ;
var offset = Math . Min ( range , Thumb Value - min ) ;
var extent = Math . Max ( 0.0 , range ) + viewportSize ;
var trackLength = isVertical ? arrangeSize . Height : arrangeSize . Width ;
double thumbMinLength = 1 0 ;
@ -407,7 +429,7 @@ namespace Avalonia.Controls.Primitives
if ( oldThumb ! = null )
{
oldThumb . DragDelta - = ThumbDragged ;
oldThumb . DragCompleted - = ThumbDragCompleted ;
LogicalChildren . Remove ( oldThumb ) ;
VisualChildren . Remove ( oldThumb ) ;
}
@ -415,6 +437,7 @@ namespace Avalonia.Controls.Primitives
if ( newThumb ! = null )
{
newThumb . DragDelta + = ThumbDragged ;
newThumb . DragCompleted + = ThumbDragCompleted ;
LogicalChildren . Add ( newThumb ) ;
VisualChildren . Add ( newThumb ) ;
}
@ -443,17 +466,43 @@ namespace Avalonia.Controls.Primitives
if ( IgnoreThumbDrag )
return ;
var value = Value ;
if ( DeferThumbDrag )
{
_d eferredThumbDrag = e ;
InvalidateArrange ( ) ;
}
else
{
ApplyThumbDrag ( e ) ;
}
}
private void ApplyThumbDrag ( VectorEventArgs e )
{
var delta = ValueFromDistance ( e . Vector . X , e . Vector . Y ) ;
var factor = e . Vector / delta ;
var oldValue = Value ;
SetCurrentValue ( ValueProperty , MathUtilities . Clamp (
value + delta ,
V alue + delta ,
Minimum ,
Maximum ) ) ;
// Record the part of the drag that actually had effect as the last drag delta.
_l astDrag = ( Value - value ) * factor ;
// Due to clamping, we need to compare the two values instead of using the drag delta.
_l astDrag = ( Value - oldValue ) * factor ;
}
private void ThumbDragCompleted ( object? sender , EventArgs e ) = > ApplyDeferredThumbDrag ( ) ;
private void ApplyDeferredThumbDrag ( )
{
if ( _d eferredThumbDrag ! = null )
{
ApplyThumbDrag ( _d eferredThumbDrag ) ;
_d eferredThumbDrag = null ;
}
}
private void ShowChildren ( bool visible )