@@ -277,27 +277,42 @@ public bool BringDescendantIntoView(Visual target, Rect targetRect)
277
277
return ! Offset . NearlyEquals ( oldOffset ) ;
278
278
}
279
279
280
+ /// <summary>
281
+ /// Computes the closest offset to ensure most of the child is visible in the viewport along an axis.
282
+ /// </summary>
283
+ /// <param name="viewportStart">The left or top of the viewport</param>
284
+ /// <param name="viewportEnd">The right or bottom of the viewport</param>
285
+ /// <param name="childStart">The left or top of the child</param>
286
+ /// <param name="childEnd">The right or bottom of the child</param>
287
+ /// <returns></returns>
280
288
internal static double ComputeScrollOffsetWithMinimalScroll (
281
- double topView ,
282
- double bottomView ,
283
- double topChild ,
284
- double bottomChild )
289
+ double viewportStart ,
290
+ double viewportEnd ,
291
+ double childStart ,
292
+ double childEnd )
285
293
{
286
- bool fAbove = MathUtilities . LessThan ( topChild , topView ) && MathUtilities . LessThan ( bottomChild , bottomView ) ;
287
- bool fBelow = MathUtilities . GreaterThan ( bottomChild , bottomView ) && MathUtilities . GreaterThan ( topChild , topView ) ;
288
- bool fLarger = ( bottomChild - topChild ) > ( bottomView - topView ) ;
294
+ // If child is above viewport, i.e. top of child is above viewport top and bottom of child is above viewport bottom.
295
+ bool isChildAbove = MathUtilities . LessThan ( childStart , viewportStart ) && MathUtilities . LessThan ( childEnd , viewportEnd ) ;
289
296
290
- var res = topView ;
297
+ // If child is below viewport, i.e. top of child is below viewport top and bottom of child is below viewport bottom.
298
+ bool isChildBelow = MathUtilities . GreaterThan ( childEnd , viewportEnd ) && MathUtilities . GreaterThan ( childStart , viewportStart ) ;
299
+ bool isChildLarger = ( childEnd - childStart ) > ( viewportEnd - viewportStart ) ;
291
300
292
- if ( ( fAbove && ! fLarger )
293
- || ( fBelow && fLarger ) )
301
+ // Value if no updates is needed. The child is fully visible in the viewport, or the viewport is completely within the child's bounds
302
+ var res = viewportStart ;
303
+
304
+ // The child is above the viewport and is smaller than the viewport, or if the child's top is below the viewport top
305
+ // and is larger than the viewport, we align the child top to the top of the viewport
306
+ if ( ( isChildAbove && ! isChildLarger )
307
+ || ( isChildBelow && isChildLarger ) )
294
308
{
295
- res = topChild ;
309
+ res = childStart ;
296
310
}
297
-
298
- else if ( fAbove || fBelow )
311
+ // The child is above the viewport and is larger than the viewport, or if the child's smaller but is below the viewport,
312
+ // we align the child's bottom to the bottom of the viewport
313
+ else if ( isChildAbove || isChildBelow )
299
314
{
300
- res = ( bottomChild - ( bottomView - topView ) ) ;
315
+ res = ( childEnd - ( viewportEnd - viewportStart ) ) ;
301
316
}
302
317
303
318
return res ;
0 commit comments