66using HandyControl . Data ;
77using HandyControl . Expression . Drawing ;
88using HandyControl . Tools ;
9+ using HandyControl . Tools . Extension ;
910
1011namespace HandyControl . Controls
1112{
@@ -20,7 +21,8 @@ public class FlexPanel : Panel
2021 #region Item
2122
2223 public static readonly DependencyProperty OrderProperty = DependencyProperty . RegisterAttached (
23- "Order" , typeof ( int ) , typeof ( FlexPanel ) , new FrameworkPropertyMetadata ( ValueBoxes . Int0Box , OnItemPropertyChanged ) ) ;
24+ "Order" , typeof ( int ) , typeof ( FlexPanel ) ,
25+ new FrameworkPropertyMetadata ( ValueBoxes . Int0Box , OnItemPropertyChanged ) ) ;
2426
2527 public static void SetOrder ( DependencyObject element , int value )
2628 => element . SetValue ( OrderProperty , value ) ;
@@ -29,7 +31,9 @@ public static int GetOrder(DependencyObject element)
2931 => ( int ) element . GetValue ( OrderProperty ) ;
3032
3133 public static readonly DependencyProperty FlexGrowProperty = DependencyProperty . RegisterAttached (
32- "FlexGrow" , typeof ( double ) , typeof ( FlexPanel ) , new FrameworkPropertyMetadata ( ValueBoxes . Double0Box , OnItemPropertyChanged ) , ValidateHelper . IsInRangeOfPosDoubleIncludeZero ) ;
34+ "FlexGrow" , typeof ( double ) , typeof ( FlexPanel ) ,
35+ new FrameworkPropertyMetadata ( ValueBoxes . Double0Box , OnItemPropertyChanged ) ,
36+ ValidateHelper . IsInRangeOfPosDoubleIncludeZero ) ;
3337
3438 public static void SetFlexGrow ( DependencyObject element , double value )
3539 => element . SetValue ( FlexGrowProperty , value ) ;
@@ -38,7 +42,9 @@ public static double GetFlexGrow(DependencyObject element)
3842 => ( double ) element . GetValue ( FlexGrowProperty ) ;
3943
4044 public static readonly DependencyProperty FlexShrinkProperty = DependencyProperty . RegisterAttached (
41- "FlexShrink" , typeof ( double ) , typeof ( FlexPanel ) , new FrameworkPropertyMetadata ( ValueBoxes . Double1Box , OnItemPropertyChanged ) ) ;
45+ "FlexShrink" , typeof ( double ) , typeof ( FlexPanel ) ,
46+ new FrameworkPropertyMetadata ( ValueBoxes . Double1Box , OnItemPropertyChanged ) ,
47+ ValidateHelper . IsInRangeOfPosDoubleIncludeZero ) ;
4248
4349 public static void SetFlexShrink ( DependencyObject element , double value )
4450 => element . SetValue ( FlexShrinkProperty , value ) ;
@@ -47,7 +53,8 @@ public static double GetFlexShrink(DependencyObject element)
4753 => ( double ) element . GetValue ( FlexShrinkProperty ) ;
4854
4955 public static readonly DependencyProperty FlexBasisProperty = DependencyProperty . RegisterAttached (
50- "FlexBasis" , typeof ( double ) , typeof ( FlexPanel ) , new FrameworkPropertyMetadata ( double . NaN , OnItemPropertyChanged ) ) ;
56+ "FlexBasis" , typeof ( double ) , typeof ( FlexPanel ) ,
57+ new FrameworkPropertyMetadata ( double . NaN , OnItemPropertyChanged ) ) ;
5158
5259 public static void SetFlexBasis ( DependencyObject element , double value )
5360 => element . SetValue ( FlexBasisProperty , value ) ;
@@ -56,7 +63,8 @@ public static double GetFlexBasis(DependencyObject element)
5663 => ( double ) element . GetValue ( FlexBasisProperty ) ;
5764
5865 public static readonly DependencyProperty AlignSelfProperty = DependencyProperty . RegisterAttached (
59- "AlignSelf" , typeof ( FlexItemAlignment ) , typeof ( FlexPanel ) , new FrameworkPropertyMetadata ( default ( FlexItemAlignment ) , OnItemPropertyChanged ) ) ;
66+ "AlignSelf" , typeof ( FlexItemAlignment ) , typeof ( FlexPanel ) ,
67+ new FrameworkPropertyMetadata ( default ( FlexItemAlignment ) , OnItemPropertyChanged ) ) ;
6068
6169 public static void SetAlignSelf ( DependencyObject element , FlexItemAlignment value )
6270 => element . SetValue ( AlignSelfProperty , value ) ;
@@ -69,7 +77,8 @@ public static FlexItemAlignment GetAlignSelf(DependencyObject element)
6977 => ( FlexItemAlignment ) element . GetValue ( AlignSelfProperty ) ;
7078
7179 public static readonly DependencyProperty FlexDirectionProperty = DependencyProperty . Register (
72- "FlexDirection" , typeof ( FlexDirection ) , typeof ( FlexPanel ) , new FrameworkPropertyMetadata ( default ( FlexDirection ) , FrameworkPropertyMetadataOptions . AffectsMeasure ) ) ;
80+ "FlexDirection" , typeof ( FlexDirection ) , typeof ( FlexPanel ) ,
81+ new FrameworkPropertyMetadata ( default ( FlexDirection ) , FrameworkPropertyMetadataOptions . AffectsMeasure ) ) ;
7382
7483 public FlexDirection FlexDirection
7584 {
@@ -78,7 +87,8 @@ public FlexDirection FlexDirection
7887 }
7988
8089 public static readonly DependencyProperty FlexWrapProperty = DependencyProperty . Register (
81- "FlexWrap" , typeof ( FlexWrap ) , typeof ( FlexPanel ) , new FrameworkPropertyMetadata ( default ( FlexWrap ) , FrameworkPropertyMetadataOptions . AffectsMeasure ) ) ;
90+ "FlexWrap" , typeof ( FlexWrap ) , typeof ( FlexPanel ) ,
91+ new FrameworkPropertyMetadata ( default ( FlexWrap ) , FrameworkPropertyMetadataOptions . AffectsMeasure ) ) ;
8292
8393 public FlexWrap FlexWrap
8494 {
@@ -87,7 +97,9 @@ public FlexWrap FlexWrap
8797 }
8898
8999 public static readonly DependencyProperty JustifyContentProperty = DependencyProperty . Register (
90- "JustifyContent" , typeof ( FlexContentJustify ) , typeof ( FlexPanel ) , new FrameworkPropertyMetadata ( default ( FlexContentJustify ) , FrameworkPropertyMetadataOptions . AffectsMeasure ) ) ;
100+ "JustifyContent" , typeof ( FlexContentJustify ) , typeof ( FlexPanel ) ,
101+ new FrameworkPropertyMetadata ( default ( FlexContentJustify ) ,
102+ FrameworkPropertyMetadataOptions . AffectsMeasure ) ) ;
91103
92104 public FlexContentJustify JustifyContent
93105 {
@@ -96,7 +108,9 @@ public FlexContentJustify JustifyContent
96108 }
97109
98110 public static readonly DependencyProperty AlignItemsProperty = DependencyProperty . Register (
99- "AlignItems" , typeof ( FlexItemsAlignment ) , typeof ( FlexPanel ) , new FrameworkPropertyMetadata ( default ( FlexItemsAlignment ) , FrameworkPropertyMetadataOptions . AffectsMeasure ) ) ;
111+ "AlignItems" , typeof ( FlexItemsAlignment ) , typeof ( FlexPanel ) ,
112+ new FrameworkPropertyMetadata ( default ( FlexItemsAlignment ) ,
113+ FrameworkPropertyMetadataOptions . AffectsMeasure ) ) ;
100114
101115 public FlexItemsAlignment AlignItems
102116 {
@@ -105,7 +119,9 @@ public FlexItemsAlignment AlignItems
105119 }
106120
107121 public static readonly DependencyProperty AlignContentProperty = DependencyProperty . Register (
108- "AlignContent" , typeof ( FlexContentAlignment ) , typeof ( FlexPanel ) , new FrameworkPropertyMetadata ( default ( FlexContentAlignment ) , FrameworkPropertyMetadataOptions . AffectsMeasure ) ) ;
122+ "AlignContent" , typeof ( FlexContentAlignment ) , typeof ( FlexPanel ) ,
123+ new FrameworkPropertyMetadata ( default ( FlexContentAlignment ) ,
124+ FrameworkPropertyMetadataOptions . AffectsMeasure ) ) ;
109125
110126 public FlexContentAlignment AlignContent
111127 {
@@ -143,13 +159,19 @@ protected override Size MeasureOverride(Size constraint)
143159
144160 _orderList . Add ( new FlexItemInfo ( i , GetOrder ( child ) ) ) ;
145161 }
162+
146163 _orderList . Sort ( ) ;
147164
148165 for ( var i = 0 ; i < children . Count ; i ++ )
149166 {
150167 var child = children [ _orderList [ i ] . Index ] ;
151168 if ( child == null ) continue ;
152169
170+ var flexBasis = GetFlexBasis ( child ) ;
171+ if ( ! flexBasis . IsNaN ( ) )
172+ {
173+ child . SetCurrentValue ( WidthProperty , flexBasis ) ;
174+ }
153175 child . Measure ( childConstraint ) ;
154176
155177 var sz = new UVSize ( FlexDirection , child . DesiredSize ) ;
@@ -260,6 +282,7 @@ protected override Size ArrangeOverride(Size arrangeSize)
260282 {
261283 freeV -= flexSize . V ;
262284 }
285+
263286 var freeItemV = freeV ;
264287
265288 // calculate status
@@ -277,13 +300,10 @@ protected override Size ArrangeOverride(Size arrangeSize)
277300
278301 accumulatedV = FlexWrap == FlexWrap . WrapReverse ? uvFinalSize . V - curLineSizeArr [ 0 ] . V - lineFreeVArr [ 0 ] : 0 ;
279302 }
303+
280304 break ;
281305 case FlexContentAlignment . FlexStart :
282- if ( FlexWrap == FlexWrap . WrapReverse )
283- {
284- wrapReverseAdd = 1 ;
285- }
286-
306+ wrapReverseAdd = FlexWrap == FlexWrap . WrapReverse ? 0 : 1 ;
287307 if ( _lineCount > 1 )
288308 {
289309 accumulatedV = FlexWrap == FlexWrap . WrapReverse ? uvFinalSize . V - curLineSizeArr [ 0 ] . V : 0 ;
@@ -292,13 +312,10 @@ protected override Size ArrangeOverride(Size arrangeSize)
292312 {
293313 wrapReverseAdd = 0 ;
294314 }
315+
295316 break ;
296317 case FlexContentAlignment . FlexEnd :
297- if ( FlexWrap != FlexWrap . WrapReverse )
298- {
299- wrapReverseAdd = 1 ;
300- }
301-
318+ wrapReverseAdd = FlexWrap == FlexWrap . WrapReverse ? 1 : 0 ;
302319 if ( _lineCount > 1 )
303320 {
304321 accumulatedV = FlexWrap == FlexWrap . WrapReverse ? uvFinalSize . V - curLineSizeArr [ 0 ] . V - freeV : freeV ;
@@ -307,12 +324,14 @@ protected override Size ArrangeOverride(Size arrangeSize)
307324 {
308325 wrapReverseAdd = 0 ;
309326 }
327+
310328 break ;
311329 case FlexContentAlignment . Center :
312330 if ( _lineCount > 1 )
313331 {
314332 accumulatedV = FlexWrap == FlexWrap . WrapReverse ? uvFinalSize . V - curLineSizeArr [ 0 ] . V - freeV * 0.5 : freeV * 0.5 ;
315333 }
334+
316335 break ;
317336 case FlexContentAlignment . SpaceBetween :
318337 if ( _lineCount > 1 )
@@ -325,6 +344,7 @@ protected override Size ArrangeOverride(Size arrangeSize)
325344
326345 accumulatedV = FlexWrap == FlexWrap . WrapReverse ? uvFinalSize . V - curLineSizeArr [ 0 ] . V : 0 ;
327346 }
347+
328348 break ;
329349 case FlexContentAlignment . SpaceAround :
330350 if ( _lineCount > 1 )
@@ -337,6 +357,7 @@ protected override Size ArrangeOverride(Size arrangeSize)
337357
338358 accumulatedV = FlexWrap == FlexWrap . WrapReverse ? uvFinalSize . V - curLineSizeArr [ 0 ] . V - freeItemV : freeItemV ;
339359 }
360+
340361 break ;
341362 }
342363
@@ -371,7 +392,8 @@ protected override Size ArrangeOverride(Size arrangeSize)
371392 lineIndex ++ ;
372393 itemsU = 0 ;
373394
374- if ( i >= lastInLineArr [ lineIndex ] ) //the element is wider then the constraint - give it a separate line
395+ if ( i >= lastInLineArr [ lineIndex ]
396+ ) //the element is wider then the constraint - give it a separate line
375397 {
376398 //switch to next line which only contain one element
377399 ArrangeLine ( new FlexLineInfo
@@ -390,6 +412,7 @@ protected override Size ArrangeOverride(Size arrangeSize)
390412 lineIndex ++ ;
391413 itemsU = 0 ;
392414 }
415+
393416 firstInLine = i ;
394417 }
395418 }
@@ -420,6 +443,10 @@ private void ArrangeLine(FlexLineInfo lineInfo)
420443 {
421444 var isHorizontal = FlexDirection == FlexDirection . Row || FlexDirection == FlexDirection . RowReverse ;
422445 var isReverse = FlexDirection == FlexDirection . RowReverse || FlexDirection == FlexDirection . ColumnReverse ;
446+ var itemCount = lineInfo . ItemEndIndex - lineInfo . ItemStartIndex ;
447+ var children = InternalChildren ;
448+ var lineFreeU = lineInfo . LineU - lineInfo . ItemsU ;
449+ var constraintFreeU = _uvConstraint . U - lineInfo . ItemsU ;
423450
424451 // calculate initial u
425452 var u = .0 ;
@@ -439,43 +466,120 @@ private void ArrangeLine(FlexLineInfo lineInfo)
439466 {
440467 u = JustifyContent switch
441468 {
442- FlexContentJustify . FlexEnd => lineInfo . LineU - lineInfo . ItemsU ,
443- FlexContentJustify . Center => ( lineInfo . LineU - lineInfo . ItemsU ) * 0.5 ,
469+ FlexContentJustify . FlexEnd => lineFreeU ,
470+ FlexContentJustify . Center => lineFreeU * 0.5 ,
444471 _ => u
445472 } ;
446473 }
474+
447475 u *= lineInfo . ScaleU ;
448476
449- // calculate offset u
450- var itemCount = lineInfo . ItemEndIndex - lineInfo . ItemStartIndex ;
451- var offsetUArr = new double [ itemCount ] ;
452- if ( JustifyContent == FlexContentJustify . SpaceBetween )
477+ // apply FlexGrow
478+ var flexGrowUArr = new double [ itemCount ] ;
479+ if ( constraintFreeU > 0 )
453480 {
454- var freeItemU = ( lineInfo . LineU - lineInfo . ItemsU ) / ( itemCount - 1 ) ;
455- for ( var i = 1 ; i < itemCount ; i ++ )
481+ var ignoreFlexGrow = true ;
482+ var flexGrowSum = .0 ;
483+
484+ for ( var i = 0 ; i < itemCount ; i ++ )
485+ {
486+ var flexGrow = GetFlexGrow ( children [ _orderList [ i ] . Index ] ) ;
487+ ignoreFlexGrow &= MathHelper . IsVerySmall ( flexGrow ) ;
488+ flexGrowUArr [ i ] = flexGrow ;
489+ flexGrowSum += flexGrow ;
490+ }
491+
492+ if ( ! ignoreFlexGrow )
493+ {
494+ var flexGrowItem = .0 ;
495+ if ( flexGrowSum > 0 )
496+ {
497+ flexGrowItem = constraintFreeU / flexGrowSum ;
498+ lineInfo . ScaleU = 1 ;
499+ lineFreeU = 0 ; //line free U was used up
500+ }
501+
502+ for ( var i = 0 ; i < itemCount ; i ++ )
503+ {
504+ flexGrowUArr [ i ] *= flexGrowItem ;
505+ }
506+ }
507+ else
456508 {
457- offsetUArr [ i ] = freeItemU ;
509+ flexGrowUArr = new double [ itemCount ] ;
458510 }
459511 }
460- else if ( JustifyContent == FlexContentJustify . SpaceAround )
512+
513+ // apply FlexShrink
514+ var flexShrinkUArr = new double [ itemCount ] ;
515+ if ( constraintFreeU < 0 )
461516 {
462- var freeItemU = ( lineInfo . LineU - lineInfo . ItemsU ) / itemCount * 0.5 ;
463- offsetUArr [ 0 ] = freeItemU ;
464- for ( var i = 1 ; i < itemCount ; i ++ )
517+ var ignoreFlexShrink = true ;
518+ var flexShrinkSum = .0 ;
519+
520+ for ( var i = 0 ; i < itemCount ; i ++ )
465521 {
466- offsetUArr [ i ] = freeItemU * 2 ;
522+ var flexShrink = GetFlexShrink ( children [ _orderList [ i ] . Index ] ) ;
523+ ignoreFlexShrink &= MathHelper . IsVerySmall ( flexShrink - 1 ) ;
524+ flexShrinkUArr [ i ] = flexShrink ;
525+ flexShrinkSum += flexShrink ;
526+ }
527+
528+ if ( ! ignoreFlexShrink )
529+ {
530+ var flexShrinkItem = .0 ;
531+ if ( flexShrinkSum > 0 )
532+ {
533+ flexShrinkItem = constraintFreeU / flexShrinkSum ;
534+ lineInfo . ScaleU = 1 ;
535+ lineFreeU = 0 ; //line free U was used up
536+ }
537+
538+ for ( var i = 0 ; i < itemCount ; i ++ )
539+ {
540+ flexShrinkUArr [ i ] *= flexShrinkItem ;
541+ }
542+ }
543+ else
544+ {
545+ flexShrinkUArr = new double [ itemCount ] ;
467546 }
468547 }
469548
470- var children = InternalChildren ;
549+ // calculate offset u
550+ var offsetUArr = new double [ itemCount ] ;
551+ if ( lineFreeU > 0 )
552+ {
553+ if ( JustifyContent == FlexContentJustify . SpaceBetween )
554+ {
555+ var freeItemU = lineFreeU / ( itemCount - 1 ) ;
556+ for ( var i = 1 ; i < itemCount ; i ++ )
557+ {
558+ offsetUArr [ i ] = freeItemU ;
559+ }
560+ }
561+ else if ( JustifyContent == FlexContentJustify . SpaceAround )
562+ {
563+ var freeItemU = lineFreeU / itemCount * 0.5 ;
564+ offsetUArr [ 0 ] = freeItemU ;
565+ for ( var i = 1 ; i < itemCount ; i ++ )
566+ {
567+ offsetUArr [ i ] = freeItemU * 2 ;
568+ }
569+ }
570+ }
571+
572+ // arrange item
471573 for ( int i = lineInfo . ItemStartIndex , j = 0 ; i < lineInfo . ItemEndIndex ; i ++ , j ++ )
472574 {
473575 var child = children [ _orderList [ i ] . Index ] ;
474576 if ( child == null ) continue ;
475577
476- var childSize = new UVSize ( FlexDirection , isHorizontal ?
477- new Size ( child . DesiredSize . Width * lineInfo . ScaleU , child . DesiredSize . Height ) :
478- new Size ( child . DesiredSize . Width , child . DesiredSize . Height * lineInfo . ScaleU ) ) ;
578+ var childSize = new UVSize ( FlexDirection , isHorizontal
579+ ? new Size ( child . DesiredSize . Width * lineInfo . ScaleU , child . DesiredSize . Height )
580+ : new Size ( child . DesiredSize . Width , child . DesiredSize . Height * lineInfo . ScaleU ) ) ;
581+
582+ childSize . U += flexGrowUArr [ j ] + flexShrinkUArr [ j ] ;
479583
480584 if ( isReverse )
481585 {
@@ -489,15 +593,7 @@ private void ArrangeLine(FlexLineInfo lineInfo)
489593
490594 var v = lineInfo . OffsetV ;
491595 var alignSelf = GetAlignSelf ( child ) ;
492- FlexItemsAlignment alignment ;
493- if ( alignSelf == FlexItemAlignment . Auto )
494- {
495- alignment = AlignItems ;
496- }
497- else
498- {
499- alignment = ( FlexItemsAlignment ) alignSelf ;
500- }
596+ var alignment = alignSelf == FlexItemAlignment . Auto ? AlignItems : ( FlexItemsAlignment ) alignSelf ;
501597
502598 switch ( alignment )
503599 {
@@ -510,6 +606,7 @@ private void ArrangeLine(FlexLineInfo lineInfo)
510606 {
511607 childSize . V = lineInfo . LineV ;
512608 }
609+
513610 break ;
514611 case FlexItemsAlignment . FlexEnd :
515612 v += lineInfo . LineV - childSize . V ;
0 commit comments