Skip to content

Commit

Permalink
fix(autolayout): counterLenght property apply when counter alignment …
Browse files Browse the repository at this point in the history
…is stretch
  • Loading branch information
Robert-Louis authored and carldebilly committed May 17, 2023
1 parent 7b56df4 commit cf1ba82
Show file tree
Hide file tree
Showing 5 changed files with 88 additions and 58 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
<Rectangle utu:AutoLayout.CounterLength="100" utu:AutoLayout.PrimaryLength="100" Fill="Blue"/>
<TextBlock Text="With Width and Height" TextAlignment="Center"/>
<Rectangle Height="100" Width="100" Fill="Red"/>
<TextBlock Text="Margin don't work with the attached properties CounterLength and PrimaryLength" TextAlignment="Center"/>
<TextBlock Text="Margin work with CounterLength and PrimaryLength" TextAlignment="Center"/>
<Rectangle Margin="20" utu:AutoLayout.CounterLength="100" utu:AutoLayout.PrimaryLength="100" Fill="Green"/>
<TextBlock Text="Margin work With Width and Height" TextAlignment="Center"/>
<Rectangle Margin="20" Width="100" Height="100" Fill="Pink"/>
Expand Down
75 changes: 41 additions & 34 deletions src/Uno.Toolkit.RuntimeTests/Tests/AutoLayoutTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -82,20 +82,27 @@ public async Task When_SpaceBetween_with_spacing(Orientation orientation, double
}
}


[TestMethod]
[RequiresFullWindow]
[DataRow(true, Orientation.Vertical, VerticalAlignment.Bottom, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 108, 0, 0, 10 }, 10, 298, 110, 12, 185)]
[DataRow(true, Orientation.Vertical, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 108, 10, 0, 0 }, 10, 12, 110, 12, 185)]
[DataRow(true, Orientation.Vertical, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 108, 10, 0, 0 }, -30, 12, 110, 12, 165)]
[DataRow(true, Orientation.Horizontal, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 10, 10, 0, 0 }, 10, 12, 12, 12, 105)]
[DataRow(true, Orientation.Horizontal, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 10, 10, 0, 0 }, 10, 12, 12, 12, 105)]
[DataRow(true, Orientation.Horizontal, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 10, 10, 0, 0 }, -30, 12, 12, 12, 85)]
[DataRow(false, Orientation.Vertical, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 108, 10, 0, 0 }, 10, 12, 110, 138, 248)]
[DataRow(false, Orientation.Horizontal, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 108, 10, 0, 0 }, 10, 12, 110, 78, 138)]
[DataRow(false, Orientation.Vertical, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 108, 10, 0, 0 }, -20, 12, 110, 168, 248)]
[DataRow(false, Orientation.Horizontal, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 108, 10, 0, 0 }, -20, 12, 110, 108, 138)]
[DataRow(true, Orientation.Vertical, VerticalAlignment.Bottom, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 110, 0, 0, 10 }, 10, 300, 110, 12, 185)]
[DataRow(true, Orientation.Vertical, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 110, 10, 0, 0 }, 10, 10, 110, 12, 185)]
[DataRow(true, Orientation.Vertical, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 110, 10, 0, 0 }, -30, 10, 110, 12, 165)]
[DataRow(true, Orientation.Horizontal, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 10, 10, 0, 0 }, 10, 10, 10, 12, 105)]
[DataRow(true, Orientation.Horizontal, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 10, 10, 0, 0 }, 10, 10, 10, 12, 105)]
[DataRow(true, Orientation.Horizontal, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 10, 10, 0, 0 }, -30, 10, 10, 12, 85)]
[DataRow(false, Orientation.Vertical, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 110, 10, 0, 0 }, 10, 10, 110, 138, 248)]
[DataRow(false, Orientation.Horizontal, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 110, 10, 0, 0 }, 10, 10, 110, 78, 138)]
[DataRow(false, Orientation.Vertical, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 110, 10, 0, 0 }, -20, 10, 110, 168, 248)]
[DataRow(false, Orientation.Horizontal, VerticalAlignment.Top, HorizontalAlignment.Left, new[] { 10, 10, 10, 10 }, new[] { 110, 10, 0, 0 }, -20, 10, 110, 108, 138)]
public async Task When_AbsolutePosition_WithPadding(bool isStretch, Orientation orientation, VerticalAlignment vAlign, HorizontalAlignment hAlign, int[] padding, int[] margin, int spacing, double expectedY, double expectedX, double rec1expected, double rec2expected)
{
if (RuntimeInformation.IsOSPlatform(OSPlatform.Create("BROWSER")))
{
Assert.Inconclusive("This test is not valid on Wasm");
return;
}

var SUT = new AutoLayout()
{
Orientation = orientation,
Expand Down Expand Up @@ -176,7 +183,7 @@ public async Task When_AbsolutePosition_WithPadding(bool isStretch, Orientation
}

[TestMethod]
//[RequiresFullWindow]
[RequiresFullWindow]
[DataRow(false, Orientation.Vertical, AutoLayoutAlignment.Start, AutoLayoutAlignment.Center, 100, 25)]
[DataRow(false, Orientation.Vertical, AutoLayoutAlignment.Center, AutoLayoutAlignment.Center, 25, 25)]
[DataRow(false, Orientation.Vertical, AutoLayoutAlignment.Start, AutoLayoutAlignment.Start, 100, 100)]
Expand All @@ -185,18 +192,18 @@ public async Task When_AbsolutePosition_WithPadding(bool isStretch, Orientation
[DataRow(false, Orientation.Horizontal, AutoLayoutAlignment.Center, AutoLayoutAlignment.Center, 25, 25)]
[DataRow(false, Orientation.Horizontal, AutoLayoutAlignment.Start, AutoLayoutAlignment.Start, 100, 100)]
[DataRow(false, Orientation.Horizontal, AutoLayoutAlignment.Start, AutoLayoutAlignment.Center, 25, 100)]
//[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.Start, AutoLayoutAlignment.Center, 100, 25)]
//[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.Center, AutoLayoutAlignment.Center, 100, 25)]
//[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.End, AutoLayoutAlignment.Center, 100, 25)]
//[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.Start, AutoLayoutAlignment.Start, 100, 100)]
//[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.Center, AutoLayoutAlignment.Start, 100, 100)]
//[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.End, AutoLayoutAlignment.Start, 100, 100)]
//[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.Start, AutoLayoutAlignment.Center, 25, 100)]
//[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.Center, AutoLayoutAlignment.Center, 25, 100)]
//[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.End, AutoLayoutAlignment.Center, 25, 100)]
//[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.Start, AutoLayoutAlignment.Start, 100, 100)]
//[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.Center, AutoLayoutAlignment.Start, 100, 100)]
//[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.End, AutoLayoutAlignment.Start, 100, 100)]
[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.Start, AutoLayoutAlignment.Center, 100, 25)]
[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.Center, AutoLayoutAlignment.Center, 100, 25)]
[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.End, AutoLayoutAlignment.Center, 100, 25)]
[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.Start, AutoLayoutAlignment.Start, 100, 100)]
[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.Center, AutoLayoutAlignment.Start, 100, 100)]
[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.End, AutoLayoutAlignment.Start, 100, 100)]
[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.Start, AutoLayoutAlignment.Center, 25, 100)]
[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.Center, AutoLayoutAlignment.Center, 25, 100)]
[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.End, AutoLayoutAlignment.Center, 25, 100)]
[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.Start, AutoLayoutAlignment.Start, 100, 100)]
[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.Center, AutoLayoutAlignment.Start, 100, 100)]
[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.End, AutoLayoutAlignment.Start, 100, 100)]

// Issue with TransformToVisual not having the same result in iOS and Android and WinIU uno issue #11774
//https://github.com/unoplatform/uno/issues/11774
Expand All @@ -205,18 +212,18 @@ public async Task When_AbsolutePosition_WithPadding(bool isStretch, Orientation
[DataRow(false, Orientation.Vertical, AutoLayoutAlignment.Center, AutoLayoutAlignment.End, 25, -50)]
[DataRow(false, Orientation.Vertical, AutoLayoutAlignment.End, AutoLayoutAlignment.End, -50, -50)]
[DataRow(false, Orientation.Vertical, AutoLayoutAlignment.End, AutoLayoutAlignment.Center, -50, 25)]
//[DataRow(false, Orientation.Vertical, AutoLayoutAlignment.End, AutoLayoutAlignment.Start, -50, 100)]
//[DataRow(false, Orientation.Horizontal, AutoLayoutAlignment.Center, AutoLayoutAlignment.End, -50, 25)]
[DataRow(false, Orientation.Vertical, AutoLayoutAlignment.End, AutoLayoutAlignment.Start, -50, 100)]
[DataRow(false, Orientation.Horizontal, AutoLayoutAlignment.Center, AutoLayoutAlignment.End, -50, 25)]
[DataRow(false, Orientation.Horizontal, AutoLayoutAlignment.End, AutoLayoutAlignment.Start, 100, -50)]
[DataRow(false, Orientation.Horizontal, AutoLayoutAlignment.End, AutoLayoutAlignment.Center, 25, -50)]
//[DataRow(false, Orientation.Horizontal, AutoLayoutAlignment.End, AutoLayoutAlignment.End, -50, -50)]
[DataRow(false, Orientation.Horizontal, AutoLayoutAlignment.End, AutoLayoutAlignment.End, -50, -50)]
[DataRow(false, Orientation.Horizontal, AutoLayoutAlignment.Start, AutoLayoutAlignment.End, -50, 100)]
//[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.Start, AutoLayoutAlignment.End, 100, -50)]
//[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.Center, AutoLayoutAlignment.End, 100, -50)]
//[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.End, AutoLayoutAlignment.End, 100, -50)]
//[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.Start, AutoLayoutAlignment.End, -50, 100)]
//[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.Center, AutoLayoutAlignment.End, -50, 100)]
//[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.End, AutoLayoutAlignment.End, -50, 100)]
[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.Start, AutoLayoutAlignment.End, 100, -50)]
[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.Center, AutoLayoutAlignment.End, 100, -50)]
[DataRow(true, Orientation.Vertical, AutoLayoutAlignment.End, AutoLayoutAlignment.End, 100, -50)]
[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.Start, AutoLayoutAlignment.End, -50, 100)]
[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.Center, AutoLayoutAlignment.End, -50, 100)]
[DataRow(true, Orientation.Horizontal, AutoLayoutAlignment.End, AutoLayoutAlignment.End, -50, 100)]
#endif

public async Task When_Padding(bool isStretch, Orientation orientation, AutoLayoutAlignment primaryAxisAlignment, AutoLayoutAlignment counterAlignment, double rec1expected, double rec2expected)
Expand All @@ -233,8 +240,8 @@ public async Task When_Padding(bool isStretch, Orientation orientation, AutoLayo
var border1 = new Border()
{
Background = new SolidColorBrush(Color.FromArgb(255, 0, 0, 255)),
Width = 350,
Height = 350,
Width = orientation is Orientation.Horizontal && isStretch ? double.NaN : 350,
Height = orientation is Orientation.Vertical && isStretch ? double.NaN : 350,
};

if (isStretch)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,9 @@ protected override Size ArrangeOverride(Size finalSize)
var padding = Padding;
var spacing = Spacing is > double.NegativeInfinity and < double.PositiveInfinity and { } s ? s : 0d;
var isHorizontal = orientation == Orientation.Horizontal;
var borderThickness = BorderThickness;

if (BorderBrush is null)
{
// BorderBrush is not set, so we don't need to consider the border thickness
borderThickness = default;
}

var finalSizeMinusBorderThickness = new Size(
finalSize.Width - (borderThickness.Left + borderThickness.Right),
finalSize.Height - (borderThickness.Top + borderThickness.Bottom));
// BorderBrush is not set, so we don't need to consider the border thickness
var borderThickness = BorderBrush == null ? default : BorderThickness;
var borderThicknessLenght = borderThickness.GetLength(orientation);

var totalNonFilledStackedSize = 0d;
var numberOfFilledChildren = 0;
Expand Down Expand Up @@ -91,6 +83,11 @@ protected override Size ArrangeOverride(Size finalSize)
haveStartPadding = atLeastOneFilledChild || justify == AutoLayoutJustify.SpaceBetween;
haveEndPadding = true;
break;
case AutoLayoutAlignment.Center:
var havePadding = atLeastOneFilledChild || justify == AutoLayoutJustify.SpaceBetween;
haveEndPadding = havePadding;
haveStartPadding = havePadding;
break;
}

var startPadding = haveStartPadding
Expand All @@ -103,7 +100,7 @@ protected override Size ArrangeOverride(Size finalSize)
var totalPaddingSize = startPadding + endPadding;

// Available Size is the final size minus the border thickness and the padding
var availableSizeForStackedChildren = finalSize.GetLength(orientation) - (borderThickness.GetLength(orientation) + totalPaddingSize);
var availableSizeForStackedChildren = finalSize.GetLength(orientation) - (borderThicknessLenght + totalPaddingSize);
EnsureZeroFloor(ref availableSizeForStackedChildren);

// Start the offset at the border + start padding
Expand Down Expand Up @@ -145,7 +142,7 @@ protected override Size ArrangeOverride(Size finalSize)
// Independent is given all the available space,
// because it's not stacking with others.
// No padding is applied to it either.
child.Element.Arrange(new Rect(new Point(borderThickness.Left, borderThickness.Top), finalSizeMinusBorderThickness));
child.Element.Arrange(new Rect(default, finalSize));

continue; // next child, current offset remains unchanged
}
Expand All @@ -157,7 +154,7 @@ protected override Size ArrangeOverride(Size finalSize)
? filledChildrenSize
: child.MeasuredLength;

var offsetRelativeToPadding = currentOffset - startPadding;
var offsetRelativeToPadding = currentOffset - (startPadding + borderThicknessLenght);

if (childLength > availableSizeForStackedChildren - offsetRelativeToPadding)
{
Expand Down Expand Up @@ -193,18 +190,19 @@ protected override Size ArrangeOverride(Size finalSize)
var haveCounterEndPadding = counterAlignment is AutoLayoutAlignment.Stretch or AutoLayoutAlignment.End;
var counterEndPadding = haveCounterEndPadding ? (isHorizontal ? padding.Bottom : padding.Right) : 0;

var availableCounterLength = finalSize.GetCounterLength(orientation) - (counterStartPadding + counterEndPadding);
var test = borderThickness.GetCounterLength(orientation);
var availableCounterLength = finalSize.GetCounterLength(orientation) - (counterStartPadding + counterEndPadding + test);

EnsureZeroFloor(ref availableCounterLength);

var childSize = isHorizontal
? new Size(childLength, counterAlignment is AutoLayoutAlignment.Stretch ? availableCounterLength : childFinalCounterLength)
: new Size(counterAlignment is AutoLayoutAlignment.Stretch ? availableCounterLength : childFinalCounterLength, childLength);

ApplyMinMaxValues(child.Element, ref childSize);
ApplyMinMaxValues(child.Element, orientation, ref childSize);

var counterAlignmentOffset =
ComputeCounterAlignmentOffset(counterAlignment, childFinalCounterLength, availableCounterLength, counterStartPadding, counterEndPadding);
ComputeCounterAlignmentOffset(counterAlignment, childFinalCounterLength, availableCounterLength, counterStartPadding, borderThickness.GetCounterStartLength(orientation));

var childOffsetPosition = new Point(
isHorizontal ? currentOffset : counterAlignmentOffset,
Expand Down Expand Up @@ -236,7 +234,7 @@ private static void UpdateCounterAlignmentToStretch(ref FrameworkElement framewo
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void ApplyMinMaxValues(UIElement element, ref Size desiredSize)
private static void ApplyMinMaxValues(UIElement element, Orientation orientation, ref Size desiredSize)
{
if (element is not FrameworkElement frameworkElement)
{
Expand All @@ -251,6 +249,21 @@ private static void ApplyMinMaxValues(UIElement element, ref Size desiredSize)
var minWidth = frameworkElement.MinWidth;
var minHeight = frameworkElement.MinHeight;

var primaryLenght = GetPrimaryLength(element);
var counterLenght = GetCounterLength(element);

// Apply primaryLenght and counterLenght constraints, if defined
if (orientation is Orientation.Horizontal)
{
if (!double.IsNaN(primaryLenght)) desiredSize.Width = primaryLenght;
if (!double.IsNaN(counterLenght)) desiredSize.Height = counterLenght;
}
else
{
if (!double.IsNaN(primaryLenght)) desiredSize.Height = primaryLenght;
if (!double.IsNaN(counterLenght)) desiredSize.Width = counterLenght;
}

// Apply Width and Height constraints, if defined
if (!double.IsNaN(width)) desiredSize.Width = width;
if (!double.IsNaN(height)) desiredSize.Height = height;
Expand All @@ -270,7 +283,7 @@ private static void ApplyMinMaxValues(UIElement element, ref Size desiredSize)
double childCounterLength,
double availableCounterLength,
double counterStartPadding,
double counterEndPadding
double counterBorderThickness
)
{
var alignmentOffsetSize = availableCounterLength - childCounterLength;
Expand All @@ -282,7 +295,7 @@ private static void ApplyMinMaxValues(UIElement element, ref Size desiredSize)
_ => 0
};

return calculatedOffset + counterStartPadding;
return calculatedOffset + counterStartPadding + counterBorderThickness;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,6 @@ protected override Size MeasureOverride(Size availableSize)
_calculatedChildren!
.Select(c => c.MeasuredLength)
.Sum()
+ paddingSize
+ totalSpacingSize;

var desiredSizeInPrimaryOrientation = Math.Max(independentDesiredSize, stackedChildrenDesiredSize);
Expand All @@ -110,8 +109,8 @@ protected override Size MeasureOverride(Size availableSize)

desiredSize = orientation switch
{
Orientation.Horizontal => new Size(desiredSizeInPrimaryOrientation, desiredCounterSize),
Orientation.Vertical => new Size(desiredCounterSize, desiredSizeInPrimaryOrientation),
Orientation.Horizontal => new Size(desiredSizeInPrimaryOrientation + paddingSize, desiredCounterSize + Padding.GetCounterLength(orientation)),
Orientation.Vertical => new Size(desiredCounterSize + Padding.GetCounterLength(orientation), desiredSizeInPrimaryOrientation + paddingSize),
_ => throw new ArgumentOutOfRangeException(),
};
}
Expand Down
11 changes: 11 additions & 0 deletions src/Uno.Toolkit.UI/Controls/AutoLayout/AutoLayoutExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,17 @@ internal static double GetStartLength(this Thickness thickness, Orientation orie
};
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static double GetCounterStartLength(this Thickness thickness, Orientation orientation)
{
return orientation switch
{
Orientation.Horizontal => thickness.Top,
Orientation.Vertical => thickness.Left,
_ => throw new ArgumentOutOfRangeException(nameof(orientation), orientation, null),
};
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static double GetEndLength(this Thickness thickness, Orientation orientation)
{
Expand Down

0 comments on commit cf1ba82

Please sign in to comment.