@ -16,8 +16,8 @@ namespace Avalonia.Layout
private Size _l astAvailableSize ;
private double _l astItemSpacing ;
private bool _ collectionChangePending ;
private VirtualizingLayoutContext _ context ;
private IFlowLayoutAlgorithmDelegates _ algorithmCallbacks ;
private VirtualizingLayoutContext ? _ context ;
private IFlowLayoutAlgorithmDelegates ? _ algorithmCallbacks ;
private Rect _l astExtent ;
private int _f irstRealizedDataIndexInsideRealizationWindow = - 1 ;
private int _l astRealizedDataIndexInsideRealizationWindow = - 1 ;
@ -46,7 +46,7 @@ namespace Avalonia.Layout
}
}
private Rect RealizationRect = > IsVirtualizingContext ? _ context . RealizationRect : new Rect ( Size . Infinity ) ;
private Rect RealizationRect = > IsVirtualizingContext ? _ context ! . RealizationRect : new Rect ( Size . Infinity ) ;
public void InitializeForContext ( VirtualizingLayoutContext context , IFlowLayoutAlgorithmDelegates callbacks )
{
@ -76,7 +76,7 @@ namespace Avalonia.Layout
int maxItemsPerLine ,
ScrollOrientation orientation ,
bool disableVirtualization ,
string layoutId )
string? layoutId )
{
_ orientation . ScrollOrientation = orientation ;
@ -87,7 +87,7 @@ namespace Avalonia.Layout
layoutId ,
realizationRect ) ;
var suggestedAnchorIndex = _ context . RecommendedAnchorIndex ;
var suggestedAnchorIndex = _ context ! . RecommendedAnchorIndex ;
if ( _ elementManager . IsIndexValidInData ( suggestedAnchorIndex ) )
{
var anchorRealized = _ elementManager . IsDataIndexRealized ( suggestedAnchorIndex ) ;
@ -124,7 +124,7 @@ namespace Avalonia.Layout
VirtualizingLayoutContext context ,
bool isWrapping ,
LineAlignment lineAlignment ,
string layoutId )
string? layoutId )
{
Logger . TryGet ( LogEventLevel . Verbose , "Repeater" ) ? . Log ( this , "{LayoutId}: ArrangeLayout" , layoutId ) ;
ArrangeVirtualizingLayout ( finalSize , lineAlignment , isWrapping , layoutId ) ;
@ -149,7 +149,7 @@ namespace Avalonia.Layout
Size availableSize ,
VirtualizingLayoutContext context )
{
var measureSize = _ algorithmCallbacks . Algorithm_GetMeasureSize ( index , availableSize , context ) ;
var measureSize = _ algorithmCallbacks ! . Algorithm_GetMeasureSize ( index , availableSize , context ) ;
element . Measure ( measureSize ) ;
var provisionalArrangeSize = _ algorithmCallbacks . Algorithm_GetProvisionalArrangeSize ( index , measureSize , element . DesiredSize , context ) ;
_ algorithmCallbacks . Algorithm_OnElementMeasured ( element , index , availableSize , measureSize , element . DesiredSize , provisionalArrangeSize , context ) ;
@ -161,7 +161,7 @@ namespace Avalonia.Layout
Size availableSize ,
bool isWrapping ,
double minItemSpacing ,
string layoutId )
string? layoutId )
{
int anchorIndex = - 1 ;
var anchorPosition = new Point ( ) ;
@ -170,7 +170,7 @@ namespace Avalonia.Layout
if ( ! IsVirtualizingContext )
{
// Non virtualizing host, start generating from the element 0
anchorIndex = context . ItemCount > 0 ? 0 : - 1 ;
anchorIndex = context ! . ItemCount > 0 ? 0 : - 1 ;
}
else
{
@ -183,7 +183,7 @@ namespace Avalonia.Layout
_l astItemSpacing ! = minItemSpacing | |
_ collectionChangePending ) ;
var suggestedAnchorIndex = _ context . RecommendedAnchorIndex ;
var suggestedAnchorIndex = _ context ! . RecommendedAnchorIndex ;
var isAnchorSuggestionValid = suggestedAnchorIndex > = 0 & &
_ elementManager . IsDataIndexRealized ( suggestedAnchorIndex ) ;
@ -191,10 +191,10 @@ namespace Avalonia.Layout
if ( isAnchorSuggestionValid )
{
Logger . TryGet ( LogEventLevel . Verbose , "Repeater" ) ? . Log ( this , "{LayoutId}: Using suggested anchor {Anchor}" , layoutId , suggestedAnchorIndex ) ;
anchorIndex = _ algorithmCallbacks . Algorithm_GetAnchorForTargetElement (
anchorIndex = _ algorithmCallbacks ! . Algorithm_GetAnchorForTargetElement (
suggestedAnchorIndex ,
availableSize ,
context ) . Index ;
context ! ) . Index ;
if ( _ elementManager . IsDataIndexRealized ( anchorIndex ) )
{
@ -235,7 +235,7 @@ namespace Avalonia.Layout
// The anchor is based on the realization window because a connected ItemsRepeater might intersect the realization window
// but not the visible window. In that situation, we still need to produce a valid anchor.
var anchorInfo = _ algorithmCallbacks . Algorithm_GetAnchorForRealizationRect ( availableSize , context ) ;
var anchorInfo = _ algorithmCallbacks ! . Algorithm_GetAnchorForRealizationRect ( availableSize , context ! ) ;
anchorIndex = anchorInfo . Index ;
anchorPosition = _ orientation . MinorMajorPoint ( 0 , anchorInfo . Offset ) ;
}
@ -259,12 +259,12 @@ namespace Avalonia.Layout
Logger . TryGet ( LogEventLevel . Verbose , "Repeater" ) ? . Log ( this , "{LayoutId} Disconnected Window - throwing away all realized elements" , layoutId ) ;
_ elementManager . ClearRealizedRange ( ) ;
var anchor = _ context . GetOrCreateElementAt ( anchorIndex , ElementRealizationOptions . ForceCreate | ElementRealizationOptions . SuppressAutoRecycle ) ;
var anchor = _ context ! . GetOrCreateElementAt ( anchorIndex , ElementRealizationOptions . ForceCreate | ElementRealizationOptions . SuppressAutoRecycle ) ;
_ elementManager . Add ( anchor , anchorIndex ) ;
}
var anchorElement = _ elementManager . GetRealizedElement ( anchorIndex ) ;
var desiredSize = MeasureElement ( anchorElement , anchorIndex , availableSize , _ context ) ;
var desiredSize = MeasureElement ( anchorElement ! , anchorIndex , availableSize , _ context ! ) ;
var layoutBounds = new Rect ( anchorPosition . X , anchorPosition . Y , desiredSize . Width , desiredSize . Height ) ;
_ elementManager . SetLayoutBoundsForDataIndex ( anchorIndex , layoutBounds ) ;
@ -296,7 +296,7 @@ namespace Avalonia.Layout
double lineSpacing ,
int maxItemsPerLine ,
bool disableVirtualization ,
string layoutId )
string? layoutId )
{
if ( anchorIndex ! = - 1 )
{
@ -322,7 +322,7 @@ namespace Avalonia.Layout
// Ensure layout element.
_ elementManager . EnsureElementRealized ( direction = = GenerateDirection . Forward , currentIndex , layoutId ) ;
var currentElement = _ elementManager . GetRealizedElement ( currentIndex ) ;
var desiredSize = MeasureElement ( currentElement , currentIndex , availableSize , _ context ) ;
var desiredSize = MeasureElement ( currentElement ! , currentIndex , availableSize , _ context ! ) ;
+ + count ;
// Lay it out.
@ -333,7 +333,7 @@ namespace Avalonia.Layout
if ( direction = = GenerateDirection . Forward )
{
double remainingSpace = _ orientation . Minor ( availableSize ) - ( _ orientation . MinorStart ( previousElementBounds ) + _ orientation . MinorSize ( previousElementBounds ) + minItemSpacing + _ orientation . Minor ( desiredSize ) ) ;
if ( countInLine > = maxItemsPerLine | | _ algorithmCallbacks . Algorithm_ShouldBreakLine ( currentIndex , remainingSpace ) )
if ( countInLine > = maxItemsPerLine | | _ algorithmCallbacks ! . Algorithm_ShouldBreakLine ( currentIndex , remainingSpace ) )
{
// No more space in this row. wrap to next row.
_ orientation . SetMinorStart ( ref currentBounds , 0 ) ;
@ -371,7 +371,7 @@ namespace Avalonia.Layout
{
// Backward
double remainingSpace = _ orientation . MinorStart ( previousElementBounds ) - ( _ orientation . Minor ( desiredSize ) + minItemSpacing ) ;
if ( countInLine > = maxItemsPerLine | | _ algorithmCallbacks . Algorithm_ShouldBreakLine ( currentIndex , remainingSpace ) )
if ( countInLine > = maxItemsPerLine | | _ algorithmCallbacks ! . Algorithm_ShouldBreakLine ( currentIndex , remainingSpace ) )
{
// Does not fit, wrap to the previous row
var availableSizeMinor = _ orientation . Minor ( availableSize ) ;
@ -432,13 +432,13 @@ namespace Avalonia.Layout
// account for that element in the indices inside the realization window.
if ( direction = = GenerateDirection . Forward )
{
int dataCount = _ context . ItemCount ;
int dataCount = _ context ! . ItemCount ;
_l astRealizedDataIndexInsideRealizationWindow = previousIndex = = dataCount - 1 ? dataCount - 1 : previousIndex - 1 ;
_l astRealizedDataIndexInsideRealizationWindow = Math . Max ( 0 , _l astRealizedDataIndexInsideRealizationWindow ) ;
}
else
{
int dataCount = _ context . ItemCount ;
int dataCount = _ context ! . ItemCount ;
_f irstRealizedDataIndexInsideRealizationWindow = previousIndex = = 0 ? 0 : previousIndex + 1 ;
_f irstRealizedDataIndexInsideRealizationWindow = Math . Min ( dataCount - 1 , _f irstRealizedDataIndexInsideRealizationWindow ) ;
}
@ -454,7 +454,7 @@ namespace Avalonia.Layout
{
_ elementManager . ClearRealizedRange ( ) ;
// FlowLayout requires that the anchor is the first element in the row.
var internalAnchor = _ algorithmCallbacks . Algorithm_GetAnchorForTargetElement ( index , availableSize , context ) ;
var internalAnchor = _ algorithmCallbacks ! . Algorithm_GetAnchorForTargetElement ( index , availableSize , context ) ;
// No need to set the position of the anchor.
// (0,0) is fine for now since the extent can
@ -487,7 +487,7 @@ namespace Avalonia.Layout
}
else
{
var realizationRect = _ context . RealizationRect ;
var realizationRect = _ context ! . RealizationRect ;
var elementBounds = _ elementManager . GetLayoutBoundsForDataIndex ( index ) ;
var elementMajorStart = _ orientation . MajorStart ( elementBounds ) ;
@ -510,11 +510,11 @@ namespace Avalonia.Layout
return shouldContinue ;
}
private Rect EstimateExtent ( Size availableSize , string layoutId )
private Rect EstimateExtent ( Size availableSize , string? layoutId )
{
ILayoutable firstRealizedElement = null ;
ILayoutable ? firstRealizedElement = null ;
Rect firstBounds = new Rect ( ) ;
ILayoutable lastRealizedElement = null ;
ILayoutable ? lastRealizedElement = null ;
Rect lastBounds = new Rect ( ) ;
int firstDataIndex = - 1 ;
int lastDataIndex = - 1 ;
@ -531,9 +531,9 @@ namespace Avalonia.Layout
lastBounds = _ elementManager . GetLayoutBoundsForRealizedIndex ( last ) ;
}
Rect extent = _ algorithmCallbacks . Algorithm_GetExtent (
Rect extent = _ algorithmCallbacks ! . Algorithm_GetExtent (
availableSize ,
_ context ,
_ context ! ,
firstRealizedElement ,
firstDataIndex ,
firstBounds ,
@ -563,7 +563,7 @@ namespace Avalonia.Layout
if ( _ orientation . MajorStart ( currentBounds ) ! = currentLineOffset )
{
// Staring a new line
_ algorithmCallbacks . Algorithm_OnLineArranged ( currentDataIndex - countInLine , countInLine , currentLineSize , _ context ) ;
_ algorithmCallbacks ! . Algorithm_OnLineArranged ( currentDataIndex - countInLine , countInLine , currentLineSize , _ context ! ) ;
countInLine = 0 ;
currentLineOffset = _ orientation . MajorStart ( currentBounds ) ;
currentLineSize = 0 ;
@ -575,7 +575,7 @@ namespace Avalonia.Layout
}
// Raise for the last line.
_ algorithmCallbacks . Algorithm_OnLineArranged ( _l astRealizedDataIndexInsideRealizationWindow - countInLine + 1 , countInLine , currentLineSize , _ context ) ;
_ algorithmCallbacks ! . Algorithm_OnLineArranged ( _l astRealizedDataIndexInsideRealizationWindow - countInLine + 1 , countInLine , currentLineSize , _ context ! ) ;
}
}
}
@ -584,7 +584,7 @@ namespace Avalonia.Layout
Size finalSize ,
LineAlignment lineAlignment ,
bool isWrapping ,
string layoutId )
string? layoutId )
{
// Walk through the realized elements one line at a time and
// align them, Then call element.Arrange with the arranged bounds.
@ -636,7 +636,7 @@ namespace Avalonia.Layout
LineAlignment lineAlignment ,
bool isWrapping ,
Size finalSize ,
string layoutId )
string? layoutId )
{
for ( int rangeIndex = lineStartIndex ; rangeIndex < lineStartIndex + countInLine ; + + rangeIndex )
{
@ -723,11 +723,11 @@ namespace Avalonia.Layout
{
if ( IsVirtualizingContext )
{
_ context . LayoutOrigin = new Point ( _l astExtent . X , _l astExtent . Y ) ;
_ context ! . LayoutOrigin = new Point ( _l astExtent . X , _l astExtent . Y ) ;
}
}
public ILayoutable GetElementIfRealized ( int dataIndex )
public ILayoutable ? GetElementIfRealized ( int dataIndex )
{
if ( _ elementManager . IsDataIndexRealized ( dataIndex ) )
{