Skip to content

Commit 5c8a3d8

Browse files
committed
Fixed alignment issues for forced stretching
1 parent 62b5e20 commit 5c8a3d8

File tree

1 file changed

+95
-83
lines changed

1 file changed

+95
-83
lines changed

components/StretchPanel/src/StretchPanel.cs

Lines changed: 95 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -88,48 +88,9 @@ protected override Size ArrangeOverride(Size finalSize)
8888
var elements = Children.Where(static e => e.Visibility is Visibility.Visible);
8989
foreach (var row in _rowSpecs)
9090
{
91-
var spacingTotalSize = uvSpacing.U * (row.ItemsCount - 1);
92-
var remainingSpace = uvFinalSize.U - row.ReservedSpace - spacingTotalSize;
93-
var portionSize = row.MinPortionSize;
94-
95-
// Determine if the desired alignment is stretched.
96-
bool stretch = GetAlignment() is Alignment.Stretch && !double.IsInfinity(uvFinalSize.U);
97-
98-
// Calculate portion size if stretching
99-
// Same logic applies for matching row lengths, since the size was determined during measure
100-
if (stretch || FixedRowLengths)
101-
{
102-
portionSize = remainingSpace / row.PortionsSum;
103-
}
104-
105-
// Reset U position
106-
pos.U = 0;
107-
108-
// Adjust the starting position if not stretching
109-
// Also do this if there are no star-sized items in the row/column
110-
// and no forced streching is in use.
111-
if (!stretch || (row.PortionsSum is 0 && ForcedStretchMethod is ForcedStretchMethod.None))
112-
{
113-
// Determine the offset based on alignment
114-
var rowSize = row.Measure(uvSpacing.U);
115-
pos.U = GetStartByAlignment(GetAlignment(), rowSize, uvFinalSize.U);
116-
}
117-
118-
// Set a flag for if the row is being forced to stretch
119-
bool forceStrech = row.PortionsSum is 0 && ForcedStretchMethod is not ForcedStretchMethod.None;
120-
121-
// Setup portionSize for forced stretching
122-
if (forceStrech)
123-
{
124-
portionSize = ForcedStretchMethod switch
125-
{
126-
ForcedStretchMethod.First => remainingSpace + GetChildSize(elements.ElementAt(0)),
127-
ForcedStretchMethod.Last => remainingSpace + GetChildSize(elements.ElementAt(row.ItemsCount - 1)),
128-
ForcedStretchMethod.Equal => (uvFinalSize.U - spacingTotalSize) / row.ItemsCount,
129-
ForcedStretchMethod.Equal or ForcedStretchMethod.Proportional => (uvFinalSize.U - spacingTotalSize) / row.ReservedSpace,
130-
_ => row.MinPortionSize,
131-
};
132-
}
91+
// Setup the row/column for arrangement
92+
var (uPos, portionSize, forceStrech) = SetupArrangeRow(row, uvFinalSize, uvSpacing, elements);
93+
pos.U = uPos;
13394

13495
for (int i = 0; i < row.ItemsCount; i++)
13596
{
@@ -143,51 +104,14 @@ protected override Size ArrangeOverride(Size finalSize)
143104
return finalSize;
144105
}
145106

146-
// Get layout and desired size
147-
var layoutLength = GetLayoutLength(child);
148-
var uvDesiredSize = new UVCoord(child.DesiredSize, Orientation);
149-
150-
// Override the layout based on the forced stretch method if necessary
151-
if (forceStrech)
152-
{
153-
var oneStar = new GridLength(1, GridUnitType.Star);
154-
layoutLength = ForcedStretchMethod switch
155-
{
156-
ForcedStretchMethod.First when i is 0 => oneStar,
157-
ForcedStretchMethod.Last when i == (row.ItemsCount - 1) => oneStar,
158-
ForcedStretchMethod.Equal => oneStar,
159-
ForcedStretchMethod.Proportional => layoutLength.GridUnitType switch
160-
{
161-
GridUnitType.Auto => new GridLength(uvDesiredSize.U, GridUnitType.Star),
162-
GridUnitType.Pixel or _ => new GridLength(layoutLength.Value, GridUnitType.Star),
163-
},
164-
165-
// If the above conditions aren't met, do nothing
166-
_ => layoutLength,
167-
};
168-
}
169-
170-
// Determine the child's U size
171-
double uSize = layoutLength.GridUnitType switch
172-
{
173-
GridUnitType.Auto => uvDesiredSize.U,
174-
GridUnitType.Pixel => layoutLength.Value,
175-
GridUnitType.Star => layoutLength.Value * portionSize,
176-
_ => uvDesiredSize.U,
177-
};
178-
179-
// Arrange the child
180-
var size = new UVCoord(0, 0, Orientation)
181-
{
182-
U = uSize,
183-
V = row.MaxOffAxisSize
184-
};
107+
// Determine the child's size
108+
var size = GetChildSize(child, i, row, portionSize, forceStrech);
185109

186110
// NOTE: The arrange method is still in X/Y coordinate system
187111
child.Arrange(new Rect(pos.X, pos.Y, size.X, size.Y));
188112

189113
// Advance the position
190-
pos.U += uSize + uvSpacing.U;
114+
pos.U += size.U + uvSpacing.U;
191115
}
192116

193117
// Advance to the next row/column
@@ -196,6 +120,94 @@ protected override Size ArrangeOverride(Size finalSize)
196120

197121
return finalSize;
198122
}
123+
private (double uPos, double portionSize, bool forceStretch) SetupArrangeRow(RowSpec row, UVCoord uvFinalSize, UVCoord uvSpacing, IEnumerable<UIElement> elements)
124+
{
125+
double uPos = 0;
126+
127+
var spacingTotalSize = uvSpacing.U * (row.ItemsCount - 1);
128+
var remainingSpace = uvFinalSize.U - row.ReservedSpace - spacingTotalSize;
129+
var portionSize = row.MinPortionSize;
130+
131+
// Determine if the desired alignment is stretched.
132+
bool stretch = GetAlignment() is Alignment.Stretch && !double.IsInfinity(uvFinalSize.U);
133+
134+
// Calculate portion size if stretching
135+
// Same logic applies for matching row lengths, since the size was determined during measure
136+
if (stretch || FixedRowLengths)
137+
{
138+
portionSize = remainingSpace / row.PortionsSum;
139+
}
140+
141+
// Adjust the starting position if not stretching
142+
// Also do this if there are no star-sized items in the row/column
143+
// and no forced streching is in use.
144+
if (!(stretch || FixedRowLengths) || (row.PortionsSum is 0 && ForcedStretchMethod is ForcedStretchMethod.None))
145+
{
146+
var rowSize = row.Measure(uvSpacing.U);
147+
uPos = GetStartByAlignment(GetAlignment(), rowSize, uvFinalSize.U);
148+
}
149+
150+
// Set a flag for if the row is being forced to stretch
151+
bool forceStretch = row.PortionsSum is 0 && ForcedStretchMethod is not ForcedStretchMethod.None;
152+
153+
// Setup portionSize for forced stretching
154+
if (forceStretch)
155+
{
156+
portionSize = ForcedStretchMethod switch
157+
{
158+
ForcedStretchMethod.First => remainingSpace + GetChildSize(elements.ElementAt(0)),
159+
ForcedStretchMethod.Last => remainingSpace + GetChildSize(elements.ElementAt(row.ItemsCount - 1)),
160+
ForcedStretchMethod.Equal => (uvFinalSize.U - spacingTotalSize) / row.ItemsCount,
161+
ForcedStretchMethod.Equal or ForcedStretchMethod.Proportional => (uvFinalSize.U - spacingTotalSize) / row.ReservedSpace,
162+
_ => row.MinPortionSize,
163+
};
164+
}
165+
166+
return (uPos, portionSize, forceStretch);
167+
}
168+
169+
private UVCoord GetChildSize(UIElement child, int rowIndex, RowSpec row, double portionSize, bool forceStretch)
170+
{
171+
// Get layout and desired size
172+
var layoutLength = GetLayoutLength(child);
173+
var uvDesiredSize = new UVCoord(child.DesiredSize, Orientation);
174+
175+
// Override the layout based on the forced stretch method if necessary
176+
if (forceStretch)
177+
{
178+
var oneStar = new GridLength(1, GridUnitType.Star);
179+
layoutLength = ForcedStretchMethod switch
180+
{
181+
ForcedStretchMethod.First when rowIndex is 0 => oneStar,
182+
ForcedStretchMethod.Last when rowIndex == (row.ItemsCount - 1) => oneStar,
183+
ForcedStretchMethod.Equal => oneStar,
184+
ForcedStretchMethod.Proportional => layoutLength.GridUnitType switch
185+
{
186+
GridUnitType.Auto => new GridLength(uvDesiredSize.U, GridUnitType.Star),
187+
GridUnitType.Pixel or _ => new GridLength(layoutLength.Value, GridUnitType.Star),
188+
},
189+
190+
// If the above conditions aren't met, do nothing
191+
_ => layoutLength,
192+
};
193+
}
194+
195+
// Determine the child's U size
196+
double uSize = layoutLength.GridUnitType switch
197+
{
198+
GridUnitType.Auto => uvDesiredSize.U,
199+
GridUnitType.Pixel => layoutLength.Value,
200+
GridUnitType.Star => layoutLength.Value * portionSize,
201+
_ => uvDesiredSize.U,
202+
};
203+
204+
// Return the final size
205+
return new UVCoord(0, 0, Orientation)
206+
{
207+
U = uSize,
208+
V = row.MaxOffAxisSize
209+
};
210+
}
199211

200212
private static double GetStartByAlignment(Alignment alignment, double size, double availableSize)
201213
{
@@ -391,7 +403,7 @@ public UVCoord(Size size, Orientation orientation) : this(size.Width, size.Heigh
391403
public double U
392404
{
393405
readonly get => _horizontal ? X : Y;
394-
set
406+
set
395407
{
396408
if (_horizontal)
397409
{

0 commit comments

Comments
 (0)