void ArrangeSlot(SlotData slotData, Point upperLeft, Size finalSize) { UVHelper uv = UVHelper.CreateInstance(slotData.Slot.Orientation); Point runningUpperLeft = upperLeft; double maxU = uv.U(runningUpperLeft) + uv.U(finalSize); bool addSizer = false; Slot previousSlot = null; foreach (var child in slotData.Slot.Children) { if (addSizer) { SlotSizer sizer = GetNextSizer(); sizer.SizeDirection = slotData.Slot.Orientation; sizer.Slot1 = previousSlot; sizer.Slot2 = child; sizer.Measure(uv.Size(SlotSpacing, uv.V(finalSize))); sizer.Arrange(new Rect(uv.Point(uv.U(runningUpperLeft), uv.V(runningUpperLeft)), uv.Size(SlotSpacing, uv.V(finalSize)))); runningUpperLeft = uv.Point(Math.Min(maxU, uv.U(runningUpperLeft) + SlotSpacing), uv.V(runningUpperLeft)); } var childSlot = slotTable[InternalGetSlotName(child)]; var childFinalSize = uv.Size(Math.Min(uv.U(finalSize), uv.U(childSlot.FinalSize)), uv.V(finalSize)); ArrangeSlot(childSlot, runningUpperLeft, childFinalSize); runningUpperLeft = uv.Point(Math.Min(maxU, uv.U(runningUpperLeft) + uv.U(childFinalSize)), uv.V(runningUpperLeft)); addSizer = (SlotSpacing > 0); previousSlot = child; } if (slotData.Elements != null) { foreach (UIElement element in slotData.Elements) { element.Arrange(new Rect(upperLeft, finalSize)); } } slotData.Slot.ActualSize = finalSize; slotData.Slot.UpperLeft = upperLeft; }
void MeasureSlot(SlotData slotData, Size availableSize) { UVHelper uv = UVHelper.CreateInstance(slotData.Slot.Orientation); // Measure all 'auto' and 'absolute' children; add up the * values as we go. double totalU = 0, maxV = 0; double totalStars = 0; bool addPad = false; foreach (var child in slotData.Slot.Children) { var length = child.Length; var childSlot = slotTable[InternalGetSlotName(child)]; if (addPad) { totalU += SlotSpacing; } if (length.IsAuto) { var childU = Math.Max(Math.Min(uv.U(availableSize), childSlot.Slot.MaxLength), childSlot.Slot.MinLength); var childAvailableSize = uv.Size(childU, uv.V(availableSize)); MeasureSlot(childSlot, childAvailableSize); childSlot.FinalSize = childSlot.DesiredSize; totalU += uv.U(childSlot.FinalSize); maxV = Math.Max(maxV, uv.V(childSlot.FinalSize)); } else if (length.IsAbsolute) { var childU = Math.Max(Math.Min(length.Value, childSlot.Slot.MaxLength), childSlot.Slot.MinLength); MeasureSlot(childSlot, uv.Size(childU, uv.V(availableSize))); childSlot.FinalSize = uv.Size(childU, uv.V(childSlot.DesiredSize)); totalU += childU; maxV = Math.Max(maxV, uv.V(childSlot.FinalSize)); } else { totalStars += length.Value; } addPad = (SlotSpacing > 0); } // Now measure the * values. double spaceLeft = Math.Max(uv.U(availableSize) - totalU, 0); List <Slot> slots = (from child in slotData.Slot.Children where child.Length.IsStar select child).ToList(); List <Slot> proportional = new List <Slot>(); // Determined the size for stars that are over the min or max length int constrained; do { constrained = 0; for (int idx = 0; idx < slots.Count; idx++) { Slot child = slots[idx]; var childSlot = slotTable[InternalGetSlotName(child)]; var childU = (spaceLeft / totalStars) * child.Length.Value; if (childU < childSlot.Slot.MinLength) { spaceLeft -= childSlot.Slot.MinLength - childU; childU = childSlot.Slot.MinLength; } else if (childU > childSlot.Slot.MaxLength) { spaceLeft += childSlot.Slot.MaxLength - childU; childU = childSlot.Slot.MaxLength; } else { proportional.Add(child); continue; } constrained++; var childAvailableSize = uv.Size(Math.Max(0, childU), uv.V(availableSize)); MeasureSlot(childSlot, childAvailableSize); childSlot.FinalSize = uv.Size(MaxNonInfinite(childU, uv.U(childSlot.DesiredSize)), uv.V(childSlot.DesiredSize)); totalU += uv.U(childSlot.FinalSize); maxV = Math.Max(maxV, uv.V(childSlot.FinalSize)); } slots = proportional; proportional = new List <Slot>(); } while (slots.Count > 0 && constrained > 0); // Determine the size of remaining star children foreach (var child in slots) { var childSlot = slotTable[InternalGetSlotName(child)]; var childU = (spaceLeft / totalStars) * child.Length.Value; var childAvailableSize = uv.Size(Math.Max(0, childU), uv.V(availableSize)); MeasureSlot(childSlot, childAvailableSize); childSlot.FinalSize = uv.Size(MaxNonInfinite(childU, uv.U(childSlot.DesiredSize)), uv.V(childSlot.DesiredSize)); totalU += uv.U(childSlot.FinalSize); maxV = Math.Max(maxV, uv.V(childSlot.FinalSize)); } // Finally, measure any child elements we have if (slotData.Elements != null) { foreach (var e in slotData.Elements) { e.Measure(availableSize); totalU = Math.Max(totalU, uv.U(e.DesiredSize)); maxV = Math.Max(maxV, uv.V(e.DesiredSize)); } } slotData.DesiredSize = uv.Size(totalU, maxV); }