@@ -31,10 +31,6 @@ protected override Size MeasureOverride(Size availableSize)
3131 return new Size ( 0 , 0 ) ;
3232 }
3333
34- // Adjusted measuring will be required if items justification is enabled and
35- // ItemsStreching is set to Equal. Condense this into a bool here.
36- bool equalStretching = ItemJustification && ItemsStretch is WrapPanelItemsStretch . Equal ;
37-
3834 foreach ( var child in elements )
3935 {
4036 // Measure the child's desired size and get layout
@@ -44,19 +40,20 @@ protected override Size MeasureOverride(Size availableSize)
4440
4541 // Attempt to add the child to the current row/column
4642 var spec = new RowSpec ( layoutLength , uvDesiredSize ) ;
47- if ( ! currentRowSpec . TryAdd ( spec , ItemSpacing , uvAvailableSize . U , equalStretching ) )
43+ if ( ! currentRowSpec . TryAdd ( spec , ItemSpacing , uvAvailableSize . U , ItemsStretch , RealJustification ) )
4844 {
4945 // Could not add to current row/column
5046 // Start a new row/column
5147 _rowSpecs . Add ( currentRowSpec ) ;
52- _longestRowSize = Math . Max ( _longestRowSize , currentRowSpec . Measure ( ItemSpacing , equalStretching ) ) ;
48+ var newSize = currentRowSpec . Measure ( ItemSpacing , ItemsStretch , RealJustification ) ;
49+ _longestRowSize = Math . Max ( _longestRowSize , newSize ) ;
5350 currentRowSpec = spec ;
5451 }
5552 }
5653
5754 // Add the final row/column
5855 _rowSpecs . Add ( currentRowSpec ) ;
59- _longestRowSize = Math . Max ( _longestRowSize , currentRowSpec . Measure ( ItemSpacing , equalStretching ) ) ;
56+ _longestRowSize = Math . Max ( _longestRowSize , currentRowSpec . Measure ( ItemSpacing , ItemsStretch , RealJustification ) ) ;
6057
6158 // Calculate final desired size
6259 var uvSize = new UVCoord ( 0 , 0 , Orientation )
@@ -106,13 +103,13 @@ protected override Size ArrangeOverride(Size finalSize)
106103
107104 private void ArrangeRow ( ref UVCoord pos , RowSpec row , UVCoord uvFinalSize , Queue < UIElement > childQueue )
108105 {
109- var spacingTotalSize = ItemSpacing * ( row . ItemsCount - 1 ) ;
106+ var spacingTotalSize = GetTotalSpacing ( row . ItemsCount , ItemSpacing , RealJustification ) ;
110107 var remainingSpace = uvFinalSize . U - row . ReservedSpace - spacingTotalSize ;
111108 var portionSize = row . MinPortionSize ;
112109
113110 // Determine if the desired alignment is stretched.
114111 // Or if fixed row lengths are in use.
115- bool stretch = IsMainAxisStretch ( uvFinalSize . U ) || ItemJustification ;
112+ bool stretch = IsMainAxisStretch ( uvFinalSize . U ) || JustifiedSpacing ;
116113
117114 // Calculate portion size if stretching
118115 // Same logic applies for matching row lengths, since the size was determined during measure
@@ -124,17 +121,9 @@ private void ArrangeRow(ref UVCoord pos, RowSpec row, UVCoord uvFinalSize, Queue
124121 // Reset the starting U position
125122 pos . U = 0 ;
126123
127- // Adjust the starting position if not stretching
128- // Also do this if there are no star-sized items in the row/column and no forced streching is in use.
129- if ( ! stretch || ( row . PortionsSum is 0 && ItemsStretch is WrapPanelItemsStretch . None ) )
130- {
131- var rowSize = row . Measure ( ItemSpacing , false ) ;
132- pos . U = GetStartByAlignment ( GetAlignment ( ) , rowSize , uvFinalSize . U ) ;
133- }
134-
135124 // Set a flag for if the row is being forced to stretch
136125 // Also declare a variable for the effective items spacing. This will be adjusted if needed for justification.
137- bool forceStretch = ItemJustification && row . PortionsSum is 0 && ItemsStretch is not WrapPanelItemsStretch . None ;
126+ bool forceStretch = JustifiedSpacing && row . PortionsSum is 0 && ItemsStretch is not WrapPanelItemsStretch . None ;
138127 var itemSpacing = ItemSpacing ;
139128
140129 // Setup portionSize for forced stretching
@@ -166,13 +155,33 @@ private void ArrangeRow(ref UVCoord pos, RowSpec row, UVCoord uvFinalSize, Queue
166155 _ => row . MinPortionSize ,
167156 } ;
168157 }
169- else if ( ItemJustification && row . PortionsSum is 0 )
158+ else if ( JustifiedSpacing && row . PortionsSum is 0 )
170159 {
171160 // If Item Justification is enabled and there's no proportional
172- // Adjust the spacing between items to align items with the margins
173- itemSpacing = ( remainingSpace + spacingTotalSize ) / ( row . ItemsCount - 1 ) ;
161+ // Adjust the spacing between items according to the justification mode.
162+ var divisbleSpace = remainingSpace + spacingTotalSize ;
163+ itemSpacing = RealJustification switch
164+ {
165+ WrapPanelItemsJustification . SpaceBetween => divisbleSpace / ( row . ItemsCount - 1 ) ,
166+ WrapPanelItemsJustification . SpaceAround => divisbleSpace / row . ItemsCount ,
167+ WrapPanelItemsJustification . SpaceEvenly => divisbleSpace / ( row . ItemsCount + 1 ) ,
168+ _ => divisbleSpace / row . ItemsCount ,
169+ } ;
174170 }
175171
172+ // Adjust the starting position
173+ var rowSize = row . Measure ( ItemSpacing , ItemsStretch , RealJustification ) ;
174+ pos . U = RealJustification switch
175+ {
176+ WrapPanelItemsJustification . SpaceAround => itemSpacing / 2 ,
177+ WrapPanelItemsJustification . SpaceBetween => 0 ,
178+ WrapPanelItemsJustification . SpaceEvenly => itemSpacing ,
179+
180+ WrapPanelItemsJustification . Start or
181+ WrapPanelItemsJustification . Center or
182+ WrapPanelItemsJustification . End or _ => GetStartByAlignment ( GetJustificationAlignment ( ) , rowSize , uvFinalSize . U ) ,
183+ } ;
184+
176185 // Arrange each child in the row/column
177186 for ( int i = 0 ; i < row . ItemsCount ; i ++ )
178187 {
@@ -312,12 +321,70 @@ private Alignment GetOffAlignment()
312321 } ;
313322 }
314323
324+ private Alignment GetJustificationAlignment ( )
325+ {
326+ return RealJustification switch
327+ {
328+ WrapPanelItemsJustification . Start => Alignment . Start ,
329+ WrapPanelItemsJustification . Center => Alignment . Center ,
330+ WrapPanelItemsJustification . End => Alignment . End ,
331+ _ => Alignment . Stretch ,
332+ } ;
333+ }
334+
315335 /// <summary>
316336 /// Determine if the desired alignment is stretched.
317337 /// Don't stretch if infinite space is available though. Attempting to divide infinite space will result in a crash.
318338 /// </summary>
319339 private bool IsMainAxisStretch ( double availableSize ) => GetAlignment ( ) is Alignment . Stretch && ! double . IsInfinity ( availableSize ) ;
320340
341+ /// <summary>
342+ /// Gets whether or not the <see cref="ItemsJustification"/> is adjusting spacing.
343+ /// </summary>
344+ private bool JustifiedSpacing => IsSpacingJustified ( RealJustification ) ;
345+
346+ /// <summary>
347+ /// Gets the <see cref="ItemsJustification"/> with the automatic option converted to the actual behavior.
348+ /// </summary>
349+ private WrapPanelItemsJustification RealJustification => ItemsJustification switch
350+ {
351+ WrapPanelItemsJustification . Automatic => GetAlignment ( ) switch
352+ {
353+ Alignment . Start => WrapPanelItemsJustification . Start ,
354+ Alignment . Center => WrapPanelItemsJustification . Center ,
355+ Alignment . End => WrapPanelItemsJustification . End ,
356+ _ => WrapPanelItemsJustification . SpaceBetween ,
357+ } ,
358+ _ => ItemsJustification ,
359+ } ;
360+
361+ private static bool IsSpacingJustified ( WrapPanelItemsJustification justification ) => justification switch
362+ {
363+ WrapPanelItemsJustification . Start or
364+ WrapPanelItemsJustification . Center or
365+ WrapPanelItemsJustification . End => false ,
366+
367+ WrapPanelItemsJustification . SpaceAround or
368+ WrapPanelItemsJustification . SpaceBetween or
369+ WrapPanelItemsJustification . SpaceEvenly => true ,
370+
371+ _ => false ,
372+ } ;
373+
374+ private static double GetTotalSpacing ( int itemCount , double itemsSpacing , WrapPanelItemsJustification justification )
375+ {
376+ return justification switch
377+ {
378+ WrapPanelItemsJustification . SpaceAround => itemCount * itemsSpacing ,
379+ WrapPanelItemsJustification . SpaceEvenly => ( itemCount + 1 ) * itemsSpacing ,
380+
381+ WrapPanelItemsJustification . Start or
382+ WrapPanelItemsJustification . Center or
383+ WrapPanelItemsJustification . End or
384+ WrapPanelItemsJustification . SpaceBetween or _ => ( itemCount - 1 ) * itemsSpacing ,
385+ } ;
386+ }
387+
321388 private double GetChildSize ( UIElement child )
322389 {
323390 var childLayout = GetLayoutLength ( child ) ;
0 commit comments