in XamlControlsGallery/Common/WrapPanel.cs [318:394]
protected override Size ArrangeOverride(Size finalSize)
{
// Variables tracking the size of the current line, and the maximum
// size available to fill. Note that the line might represent a row
// or a column depending on the orientation.
Orientation o = Orientation;
OrientedSize lineSize = new OrientedSize(o);
OrientedSize maximumSize = new OrientedSize(o, finalSize.Width, finalSize.Height);
// Determine the constraints for individual items
double itemWidth = ItemWidth;
double itemHeight = ItemHeight;
bool hasFixedWidth = !itemWidth.IsNaN();
bool hasFixedHeight = !itemHeight.IsNaN();
double indirectOffset = 0;
double? directDelta = (o == Orientation.Horizontal) ?
(hasFixedWidth ? (double?)itemWidth : null) :
(hasFixedHeight ? (double?)itemHeight : null);
// Measure each of the Children. We will process the elements one
// line at a time, just like during measure, but we will wait until
// we've completed an entire line of elements before arranging them.
// The lineStart and lineEnd variables track the size of the
// currently arranged line.
UIElementCollection children = Children;
int count = children.Count;
int lineStart = 0;
for (int lineEnd = 0; lineEnd < count; lineEnd++)
{
UIElement element = children[lineEnd];
// Get the size of the element
OrientedSize elementSize = new OrientedSize(
o,
hasFixedWidth ? itemWidth : element.DesiredSize.Width,
hasFixedHeight ? itemHeight : element.DesiredSize.Height);
// If this element falls of the edge of the line
if (NumericExtensions.IsGreaterThan(lineSize.Direct + elementSize.Direct, maximumSize.Direct))
{
// Then we just completed a line and we should arrange it
ArrangeLine(lineStart, lineEnd, directDelta, indirectOffset, lineSize.Indirect);
// Move the current element to a new line
indirectOffset += lineSize.Indirect;
lineSize = elementSize;
// If the current element is larger than the maximum size
if (NumericExtensions.IsGreaterThan(elementSize.Direct, maximumSize.Direct))
{
// Arrange the element as a single line
ArrangeLine(lineEnd, ++lineEnd, directDelta, indirectOffset, elementSize.Indirect);
// Move to a new line
indirectOffset += lineSize.Indirect;
lineSize = new OrientedSize(o);
}
// Advance the start index to a new line after arranging
lineStart = lineEnd;
}
else
{
// Otherwise just add the element to the end of the line
lineSize.Direct += elementSize.Direct;
lineSize.Indirect = Math.Max(lineSize.Indirect, elementSize.Indirect);
}
}
// Arrange any elements on the last line
if (lineStart < count)
{
ArrangeLine(lineStart, count, directDelta, indirectOffset, lineSize.Indirect);
}
return finalSize;
}