@@ -118,35 +118,35 @@ public bool ScrollbarOverlapsContent
118
118
/// <summary>
119
119
/// The current scroll position.
120
120
/// </summary>
121
- public float Current { get ; private set ; }
121
+ public double Current { get ; private set ; }
122
122
123
123
/// <summary>
124
124
/// The target scroll position which is exponentially approached by current via a rate of distance decay.
125
125
/// </summary>
126
126
/// <remarks>
127
127
/// When not animating scroll position, this will always be equal to <see cref="Current"/>.
128
128
/// </remarks>
129
- public float Target { get ; private set ; }
129
+ public double Target { get ; private set ; }
130
130
131
131
/// <summary>
132
132
/// The maximum distance that can be scrolled in the scroll direction.
133
133
/// </summary>
134
- public float ScrollableExtent => Math . Max ( AvailableContent - DisplayableContent , 0 ) ;
134
+ public double ScrollableExtent => Math . Max ( AvailableContent - DisplayableContent , 0 ) ;
135
135
136
136
/// <summary>
137
137
/// The maximum distance that the scrollbar can move in the scroll direction.
138
138
/// </summary>
139
139
/// <remarks>
140
140
/// May not be accurate to actual display of scrollbar if <see cref="ToScrollbarPosition"/> or <see cref="FromScrollbarPosition"/> are overridden.
141
141
/// </remarks>
142
- protected float ScrollbarMovementExtent => Math . Max ( DisplayableContent - Scrollbar . DrawSize [ ScrollDim ] , 0 ) ;
142
+ protected double ScrollbarMovementExtent => Math . Max ( DisplayableContent - Scrollbar . DrawSize [ ScrollDim ] , 0 ) ;
143
143
144
144
/// <summary>
145
145
/// Clamp a value to the available scroll range.
146
146
/// </summary>
147
147
/// <param name="position">The value to clamp.</param>
148
148
/// <param name="extension">An extension value beyond the normal extent.</param>
149
- protected float Clamp ( float position , float extension = 0 ) => Math . Max ( Math . Min ( position , ScrollableExtent + extension ) , - extension ) ;
149
+ protected double Clamp ( double position , double extension = 0 ) => Math . Max ( Math . Min ( position , ScrollableExtent + extension ) , - extension ) ;
150
150
151
151
protected override Container < T > Content => ScrollContent ;
152
152
@@ -345,8 +345,8 @@ protected override void OnDrag(DragEvent e)
345
345
346
346
Vector2 childDelta = ToLocalSpace ( e . ScreenSpaceMousePosition ) - ToLocalSpace ( e . ScreenSpaceLastMousePosition ) ;
347
347
348
- float scrollOffset = - childDelta [ ScrollDim ] ;
349
- float clampedScrollOffset = Clamp ( Target + scrollOffset ) - Clamp ( Target ) ;
348
+ double scrollOffset = - childDelta [ ScrollDim ] ;
349
+ double clampedScrollOffset = Clamp ( Target + scrollOffset ) - Clamp ( Target ) ;
350
350
351
351
// If we are dragging past the extent of the scrollable area, half the offset
352
352
// such that the user can feel it.
@@ -424,7 +424,7 @@ public void OffsetScrollPosition(float offset)
424
424
Current += offset ;
425
425
}
426
426
427
- private void scrollByOffset ( float value , bool animated , double distanceDecay = float . PositiveInfinity ) =>
427
+ private void scrollByOffset ( double value , bool animated , double distanceDecay = float . PositiveInfinity ) =>
428
428
OnUserScroll ( Target + value , animated , distanceDecay ) ;
429
429
430
430
/// <summary>
@@ -454,15 +454,15 @@ public void ScrollToEnd(bool animated = true, bool allowDuringDrag = false)
454
454
/// </summary>
455
455
/// <param name="offset">The amount by which we should scroll.</param>
456
456
/// <param name="animated">Whether to animate the movement.</param>
457
- public void ScrollBy ( float offset , bool animated = true ) => scrollTo ( Target + offset , animated ) ;
457
+ public void ScrollBy ( double offset , bool animated = true ) => scrollTo ( Target + offset , animated ) ;
458
458
459
459
/// <summary>
460
460
/// Handle a scroll to an absolute position from a user input.
461
461
/// </summary>
462
462
/// <param name="value">The position to scroll to.</param>
463
463
/// <param name="animated">Whether to animate the movement.</param>
464
464
/// <param name="distanceDecay">Controls the rate with which the target position is approached after jumping to a specific location. Default is <see cref="DistanceDecayJump"/>.</param>
465
- protected virtual void OnUserScroll ( float value , bool animated = true , double ? distanceDecay = null ) =>
465
+ protected virtual void OnUserScroll ( double value , bool animated = true , double ? distanceDecay = null ) =>
466
466
ScrollTo ( value , animated , distanceDecay ) ;
467
467
468
468
/// <summary>
@@ -471,9 +471,9 @@ protected virtual void OnUserScroll(float value, bool animated = true, double? d
471
471
/// <param name="value">The position to scroll to.</param>
472
472
/// <param name="animated">Whether to animate the movement.</param>
473
473
/// <param name="distanceDecay">Controls the rate with which the target position is approached after jumping to a specific location. Default is <see cref="DistanceDecayJump"/>.</param>
474
- public void ScrollTo ( float value , bool animated = true , double ? distanceDecay = null ) => scrollTo ( value , animated , distanceDecay ?? DistanceDecayJump ) ;
474
+ public void ScrollTo ( double value , bool animated = true , double ? distanceDecay = null ) => scrollTo ( value , animated , distanceDecay ?? DistanceDecayJump ) ;
475
475
476
- private void scrollTo ( float value , bool animated , double distanceDecay = float . PositiveInfinity )
476
+ private void scrollTo ( double value , bool animated , double distanceDecay = double . PositiveInfinity )
477
477
{
478
478
Target = Clamp ( value , ClampExtension ) ;
479
479
@@ -497,11 +497,11 @@ private void scrollTo(float value, bool animated, double distanceDecay = float.P
497
497
/// <param name="animated">Whether to animate the movement.</param>
498
498
public void ScrollIntoView ( Drawable d , bool animated = true )
499
499
{
500
- float childPos0 = GetChildPosInContent ( d ) ;
501
- float childPos1 = GetChildPosInContent ( d , d . DrawSize ) ;
500
+ double childPos0 = GetChildPosInContent ( d ) ;
501
+ double childPos1 = GetChildPosInContent ( d , d . DrawSize ) ;
502
502
503
- float minPos = Math . Min ( childPos0 , childPos1 ) ;
504
- float maxPos = Math . Max ( childPos0 , childPos1 ) ;
503
+ double minPos = Math . Min ( childPos0 , childPos1 ) ;
504
+ double maxPos = Math . Max ( childPos0 , childPos1 ) ;
505
505
506
506
if ( minPos < Current || ( minPos > Current && d . DrawSize [ ScrollDim ] > DisplayableContent ) )
507
507
ScrollTo ( minPos , animated ) ;
@@ -515,14 +515,14 @@ public void ScrollIntoView(Drawable d, bool animated = true)
515
515
/// <param name="d">The child to get the position from.</param>
516
516
/// <param name="offset">Positional offset in the child's space.</param>
517
517
/// <returns>The position of the child.</returns>
518
- public float GetChildPosInContent ( Drawable d , Vector2 offset ) => d . ToSpaceOfOtherDrawable ( offset , ScrollContent ) [ ScrollDim ] ;
518
+ public virtual double GetChildPosInContent ( Drawable d , Vector2 offset ) => d . ToSpaceOfOtherDrawable ( offset , ScrollContent ) [ ScrollDim ] ;
519
519
520
520
/// <summary>
521
521
/// Determines the position of a child in the content.
522
522
/// </summary>
523
523
/// <param name="d">The child to get the position from.</param>
524
524
/// <returns>The position of the child.</returns>
525
- public float GetChildPosInContent ( Drawable d ) => GetChildPosInContent ( d , Vector2 . Zero ) ;
525
+ public double GetChildPosInContent ( Drawable d ) => GetChildPosInContent ( d , Vector2 . Zero ) ;
526
526
527
527
private void updatePosition ( )
528
528
{
@@ -544,15 +544,15 @@ private void updatePosition()
544
544
localDistanceDecay = distance_decay_clamping * 2 ;
545
545
546
546
// Lastly, we gradually nudge the target towards valid bounds.
547
- Target = ( float ) Interpolation . Lerp ( Clamp ( Target ) , Target , Math . Exp ( - distance_decay_clamping * Time . Elapsed ) ) ;
547
+ Target = Interpolation . Lerp ( Clamp ( Target ) , Target , Math . Exp ( - distance_decay_clamping * Time . Elapsed ) ) ;
548
548
549
- float clampedTarget = Clamp ( Target ) ;
549
+ double clampedTarget = Clamp ( Target ) ;
550
550
if ( Precision . AlmostEquals ( clampedTarget , Target ) )
551
551
Target = clampedTarget ;
552
552
}
553
553
554
554
// Exponential interpolation between the target and our current scroll position.
555
- Current = ( float ) Interpolation . Lerp ( Target , Current , Math . Exp ( - localDistanceDecay * Time . Elapsed ) ) ;
555
+ Current = Interpolation . Lerp ( Target , Current , Math . Exp ( - localDistanceDecay * Time . Elapsed ) ) ;
556
556
557
557
// This prevents us from entering the de-normalized range of floating point numbers when approaching target closely.
558
558
if ( Precision . AlmostEquals ( Current , Target ) )
@@ -578,28 +578,40 @@ protected override void UpdateAfterChildren()
578
578
}
579
579
580
580
if ( ScrollDirection == Direction . Horizontal )
581
- {
582
581
Scrollbar . X = ToScrollbarPosition ( Current ) ;
583
- ScrollContent . X = - Current + ScrollableExtent * ScrollContent . RelativeAnchorPosition . X ;
584
- }
585
582
else
586
- {
587
583
Scrollbar . Y = ToScrollbarPosition ( Current ) ;
588
- ScrollContent . Y = - Current + ScrollableExtent * ScrollContent . RelativeAnchorPosition . Y ;
589
- }
584
+
585
+ ApplyCurrentToContent ( ) ;
586
+ }
587
+
588
+ /// <summary>
589
+ /// This is the final internal step of updating the scroll container, which takes
590
+ /// <see cref="Current"/> and applies it to <see cref="ScrollContent"/> in order to
591
+ /// correctly offset children.
592
+ ///
593
+ /// Overriding this method can be used to inhibit this default behaviour, to for instance
594
+ /// redirect the positioning to another container or change the way it is applied.
595
+ /// </summary>
596
+ protected virtual void ApplyCurrentToContent ( )
597
+ {
598
+ if ( ScrollDirection == Direction . Horizontal )
599
+ ScrollContent . X = ( float ) ( - Current + ( ScrollableExtent * ScrollContent . RelativeAnchorPosition . X ) ) ;
600
+ else
601
+ ScrollContent . Y = ( float ) ( - Current + ( ScrollableExtent * ScrollContent . RelativeAnchorPosition . Y ) ) ;
590
602
}
591
603
592
604
/// <summary>
593
605
/// Converts a scroll position to a scrollbar position.
594
606
/// </summary>
595
607
/// <param name="scrollPosition">The absolute scroll position (e.g. <see cref="Current"/>).</param>
596
608
/// <returns>The scrollbar position.</returns>
597
- protected virtual float ToScrollbarPosition ( float scrollPosition )
609
+ protected virtual float ToScrollbarPosition ( double scrollPosition )
598
610
{
599
611
if ( Precision . AlmostEquals ( 0 , ScrollableExtent ) )
600
612
return 0 ;
601
613
602
- return ScrollbarMovementExtent * ( scrollPosition / ScrollableExtent ) ;
614
+ return ( float ) ( ScrollbarMovementExtent * ( scrollPosition / ScrollableExtent ) ) ;
603
615
}
604
616
605
617
/// <summary>
@@ -612,7 +624,7 @@ protected virtual float FromScrollbarPosition(float scrollbarPosition)
612
624
if ( Precision . AlmostEquals ( 0 , ScrollbarMovementExtent ) )
613
625
return 0 ;
614
626
615
- return ScrollableExtent * ( scrollbarPosition / ScrollbarMovementExtent ) ;
627
+ return ( float ) ( ScrollableExtent * ( scrollbarPosition / ScrollbarMovementExtent ) ) ;
616
628
}
617
629
618
630
/// <summary>
0 commit comments