// Decompiled with JetBrains decompiler // Type: Microsoft.Iris.Layouts.GridLayout // Assembly: UIX, Version=4.8.0.0, Culture=neutral, PublicKeyToken=ddd0da4d3e678217 // MVID: A56C6C9D-B7F6-46A9-8BDE-B3D9B8D60B11 // Assembly location: C:\Program Files\Zune\UIX.dll using Microsoft.Iris.Data; using Microsoft.Iris.Layout; using Microsoft.Iris.Library; using Microsoft.Iris.Render; using Microsoft.Iris.ViewItems; using System; namespace Microsoft.Iris.Layouts { internal class GridLayout : ILayout { private Orientation _orientation; private bool _allowWrap; private Size _referenceSize; private Size _spacing; private int _rows; private int _columns; private RepeatPolicy _repeat; private int _repeatGap; private ItemAlignment _defaultChildAlignment; public GridLayout() : this(Orientation.Horizontal) { } public GridLayout(Orientation o) => _orientation = o; public Orientation Orientation { get => _orientation; set { if (_orientation == value) return; _orientation = value; } } public bool AllowWrap { get => _allowWrap; set { if (_allowWrap == value) return; _allowWrap = value; } } public Size ReferenceSize { get => _referenceSize; set { if (!(_referenceSize != value)) return; _referenceSize = value; } } public int Rows { get => _rows; set { if (_rows == value) return; _rows = value; } } public int Columns { get => _columns; set { if (_columns == value) return; _columns = value; } } public Size Spacing { get => _spacing; set { if (!(_spacing != value)) return; _spacing = value; } } public RepeatPolicy Repeat { get => _repeat; set { if (_repeat == value) return; _repeat = value; } } public int RepeatGap { get => _repeatGap; set { if (_repeatGap == value) return; _repeatGap = value; } } public ItemAlignment DefaultChildAlignment { get => _defaultChildAlignment; set => _defaultChildAlignment = value; } Size ILayout.Measure(ILayoutNode layoutNode, Size constraint) { GridLayout.GeneralFlowInfo generalFlowInfo = CalculateGeneralFlowInfo(layoutNode, constraint); layoutNode.MeasureData = generalFlowInfo; if (generalFlowInfo.itemsCount <= 0 || !generalFlowInfo.referenceExtent.IsEmpty) return generalFlowInfo.usedSize.ToSize(Orientation); layoutNode.RequestMoreChildren(1); return Size.Zero; } void ILayout.Arrange(ILayoutNode layoutNode, LayoutSlot slot) { GridLayout.GeneralFlowInfo measureData = (GridLayout.GeneralFlowInfo)layoutNode.MeasureData; measureData.slot = slot; MajorMinor majorMinor1 = new MajorMinor(slot.View.Size, Orientation); MajorMinor majorMinor2 = new MajorMinor(slot.PeripheralView.Size, Orientation); MajorMinor majorMinor3 = new MajorMinor(slot.View.Location.ToSize(), Orientation); bool flag1 = measureData.availableSpace.Major != majorMinor2.Major || majorMinor3.Major != 0; bool flag2 = measureData.availableSpace.Minor != majorMinor2.Minor || majorMinor3.Minor != 0; MajorMinor majorMinor4 = majorMinor2 + measureData.spacing; MajorMinor majorMinor5 = majorMinor1 + measureData.spacing; bool roundUp1 = flag1; bool roundUp2 = flag2; MajorMinor a = MajorMinor.Zero; a.Major = DivideIntegers(majorMinor5.Major, measureData.referenceWithSpacing.Major, roundUp1); a.Minor = DivideIntegers(majorMinor5.Minor, measureData.referenceWithSpacing.Minor, roundUp2); a.Minor = Math.Min(a.Minor, measureData.fitItems.Minor); bool flag3 = !measureData.wrapping ? measureData.totalItems.Major <= a.Major : measureData.totalItems.Minor <= a.Minor; bool flag4; switch (_repeat) { case RepeatPolicy.WhenTooBig: flag4 = !flag3; break; case RepeatPolicy.WhenTooSmall: flag4 = flag3; break; case RepeatPolicy.Always: flag4 = true; break; default: flag4 = false; break; } if (!flag4) a = MajorMinor.Min(a, measureData.totalItems); else measureData.wrapping |= AllowWrap; measureData.repeating = flag4; measureData.allowPartialItemsMajor = roundUp1; measureData.allowPartialItemsMinor = roundUp2; measureData.viewSize = majorMinor2; if (measureData.itemsCount > 0) { GridLayout.IndexRangeInfo indicesInfo; Vector indicesToDisplayList; ArrangeChildren(layoutNode, measureData, out indicesInfo, out indicesToDisplayList); if (indicesToDisplayList != null) layoutNode.RequestSpecificChildren(indicesToDisplayList); layoutNode.SetVisibleIndexRange(indicesInfo.realBeginIndex, indicesInfo.realEndIndex, indicesInfo.beginIndex, indicesInfo.endIndex, measureData.focusedItemIndex); } MajorMinor usedSize = measureData.usedSize; if (!measureData.repeating) return; MajorMinor zero = MajorMinor.Zero; if (measureData.wrapping) zero.Minor = -usedSize.Minor / 2; else zero.Major = -usedSize.Major / 2; Rectangle rectangle = new Rectangle(zero.ToPoint(Orientation), usedSize.ToSize(Orientation)); layoutNode.AddAreaOfInterest(new AreaOfInterest(rectangle, AreaOfInterestID.ScrollableRange)); } private int GetItemCount(ILayoutNode layoutNode) { int num = -1; if (layoutNode.GetLayoutInput(CountLayoutInput.Data) is CountLayoutInput layoutInput) num = layoutInput.Count; if (num == -1) num = layoutNode.LayoutChildrenCount; return num; } private Size GetReferenceSize(ILayoutNode layoutNode, Size constraint) { Size referenceSize = ReferenceSize; if (referenceSize.Width == 0.0 && Columns != 0) { int num = (constraint.Width - Spacing.Width * (Columns - 1)) / Columns; if (num <= 0) return Size.Zero; referenceSize.Width = num; constraint.Width = num; } if (referenceSize.Height == 0.0 && Rows != 0) { int num = (constraint.Height - Spacing.Height * (Rows - 1)) / Rows; if (num <= 0) return Size.Zero; referenceSize.Height = num; constraint.Height = num; } if (referenceSize.IsEmpty && layoutNode.LayoutChildrenCount > 0) { foreach (ILayoutNode layoutChild in layoutNode.LayoutChildren) { layoutChild.Measure(constraint); if (referenceSize.Width == 0) referenceSize.Width = layoutChild.DesiredSize.Width; if (referenceSize.Height == 0) referenceSize.Height = layoutChild.DesiredSize.Height; if (!referenceSize.IsEmpty) break; } } return referenceSize; } private GridLayout.GeneralFlowInfo CalculateGeneralFlowInfo( ILayoutNode layoutNode, Size constraint) { int itemCount = GetItemCount(layoutNode); Size size1 = GetReferenceSize(layoutNode, constraint); GridLayout.GeneralFlowInfo generalFlowInfo = new GridLayout.GeneralFlowInfo(itemCount, size1, constraint); if (itemCount == 0 || size1.IsEmpty) return generalFlowInfo; if (size1.Width > constraint.Width || size1.Height > constraint.Height) { foreach (ILayoutNode layoutChild in layoutNode.LayoutChildren) layoutChild.MarkHidden(); generalFlowInfo.referenceExtent = Size.Zero; return generalFlowInfo; } bool flag = AllowWrap; if (Orientation == Orientation.Vertical && Columns > 1) flag = true; else if (Orientation == Orientation.Horizontal && Rows > 1) flag = true; MajorMinor majorMinor1 = new MajorMinor(size1, Orientation); MajorMinor a = new MajorMinor(0, majorMinor1.Minor); if (!flag && new MajorMinor(ReferenceSize, Orientation).Minor == 0) { majorMinor1.Minor = new MajorMinor(constraint, Orientation).Minor; size1 = majorMinor1.ToSize(Orientation); } foreach (ILayoutNode layoutChild in layoutNode.LayoutChildren) { Size size2 = layoutChild.Measure(size1); a = MajorMinor.Max(a, new MajorMinor(size2, Orientation)); } if (!flag) { majorMinor1.Minor = a.Minor; size1 = majorMinor1.ToSize(Orientation); } MajorMinor majorMinor2 = new MajorMinor(size1, Orientation); MajorMinor majorMinor3 = new MajorMinor(Spacing, Orientation); MajorMinor majorMinor4 = majorMinor2 + majorMinor3; MajorMinor majorMinor5 = new MajorMinor(constraint, Orientation); MajorMinor majorMinor6 = majorMinor5 + majorMinor3; MajorMinor zero1 = MajorMinor.Zero; zero1.Major = DivideIntegers(majorMinor6.Major, majorMinor4.Major, false); zero1.Minor = DivideIntegers(majorMinor6.Minor, majorMinor4.Minor, false); if (zero1.Major >= itemCount) flag = false; MajorMinor zero2 = MajorMinor.Zero; zero2.Major = Math.Min(itemCount, zero1.Major); zero2.Minor = 1; if (flag && zero2.Major > 0) { zero2.Minor = DivideIntegers(itemCount, zero2.Major, true); zero2.Minor = Math.Min(zero2.Minor, zero1.Minor); } MajorMinor majorMinor7 = majorMinor4 * zero2 - majorMinor3; MajorMinor majorMinor8 = new MajorMinor(RepeatGap, 0); if (flag) majorMinor8 = majorMinor8.Swap(); MajorMinor majorMinor9 = majorMinor7 + majorMinor8; MajorMinor majorMinor10 = majorMinor7; if (Repeat == RepeatPolicy.WhenTooSmall || Repeat == RepeatPolicy.Always) { if (flag) majorMinor10.Minor = majorMinor5.Minor; else majorMinor10.Major = majorMinor5.Major; } generalFlowInfo.wrapping = flag; generalFlowInfo.reference = majorMinor2; generalFlowInfo.spacing = majorMinor3; generalFlowInfo.referenceWithSpacing = majorMinor4; generalFlowInfo.availableSpace = majorMinor5; generalFlowInfo.fitItems = zero1; generalFlowInfo.totalItems = zero2; generalFlowInfo.repeatInstanceSize = majorMinor9; generalFlowInfo.usedSize = majorMinor10; return generalFlowInfo; } private void ArrangeChildren( ILayoutNode layoutNode, GridLayout.GeneralFlowInfo generalInfo, out GridLayout.IndexRangeInfo indicesInfo, out Vector indicesToDisplayList) { indicesInfo = GetIndexRange(layoutNode, generalInfo); indicesToDisplayList = null; if (indicesInfo.nonEmptyRange) { indicesToDisplayList = layoutNode.GetSpecificChildrenRequestList(); for (int beginIndex = indicesInfo.beginIndex; beginIndex <= indicesInfo.endIndex; ++beginIndex) indicesToDisplayList.Add(beginIndex); } if (layoutNode.LayoutChildrenCount == 0) return; Size referenceExtent = generalInfo.referenceExtent; if (!generalInfo.wrapping) { if (Orientation == Orientation.Horizontal) referenceExtent.Height = generalInfo.slot.Bounds.Height; else referenceExtent.Width = generalInfo.slot.Bounds.Width; } Rectangle rectangle1 = new Rectangle(Point.Zero, generalInfo.slot.Bounds); int num = 0; foreach (ILayoutNode layoutChild in layoutNode.LayoutChildren) { int idx = num; if (layoutChild.GetLayoutInput(IndexLayoutInput.Data) is IndexLayoutInput layoutInput) { idx = layoutInput.Index.Value; int type = (int)layoutInput.Type; } Point offset = PositionFromIndex(layoutNode, idx, generalInfo, out MajorMinor _); if (indicesToDisplayList != null) indicesToDisplayList.Remove(idx); Rectangle rectangle2 = new Rectangle(offset, referenceExtent); if (generalInfo.repeating || rectangle1.Contains(rectangle2)) { layoutChild.Arrange(generalInfo.slot, rectangle2); if (layoutChild.ContainsAreaOfInterest(AreaOfInterestID.Focus)) generalInfo.focusedItemIndex = new int?(idx); } else layoutChild.MarkHidden(); ++num; } } private GridLayout.IndexRangeInfo GetIndexRange( ILayoutNode layoutNode, GridLayout.GeneralFlowInfo generalInfo) { if (generalInfo.totalItems.IsEmpty) return new GridLayout.IndexRangeInfo(); MajorMinor position1 = new MajorMinor(generalInfo.slot.PeripheralView.Location.ToSize(), Orientation); MajorMinor position2 = new MajorMinor(generalInfo.slot.View.Location.ToSize(), Orientation); MajorMinor majorMinor1 = new MajorMinor(generalInfo.slot.PeripheralView.Size, Orientation); MajorMinor majorMinor2 = new MajorMinor(generalInfo.slot.View.Size, Orientation); MajorMinor position3 = position1 + majorMinor1; MajorMinor position4 = position2 + majorMinor2; bool flag1 = true; bool flag2 = true; int index1; bool flag3 = flag1 & GetViewIntersectionFromPosition(layoutNode, position1, generalInfo, ViewIntersectionType.BeginOffscreen, out index1); int index2; bool flag4 = flag2 & GetViewIntersectionFromPosition(layoutNode, position2, generalInfo, ViewIntersectionType.BeginOnscreen, out index2); int index3; bool flag5 = flag3 & GetViewIntersectionFromPosition(layoutNode, position3, generalInfo, ViewIntersectionType.EndOnscreen, out index3); int index4; bool flag6 = flag4 & GetViewIntersectionFromPosition(layoutNode, position4, generalInfo, ViewIntersectionType.EndOffscreen, out index4); return !flag5 ? new GridLayout.IndexRangeInfo() : new GridLayout.IndexRangeInfo(index1, index3, index2, index4, generalInfo); } private Point PositionFromIndex( ILayoutNode layoutNode, int idx, GridLayout.GeneralFlowInfo generalInfo, out MajorMinor index) { int dataIndex; int generationValue; ListUtility.GetWrappedIndex(idx, generalInfo.itemsCount, out dataIndex, out generationValue); index = PositionFromIndex(dataIndex, generalInfo.totalItems); MajorMinor majorMinor1 = index * generalInfo.referenceWithSpacing; MajorMinor majorMinor2 = generalInfo.repeatInstanceSize * new MajorMinor(generationValue, generationValue); if (generalInfo.wrapping) majorMinor2.Major = 0; else majorMinor2.Minor = 0; return (majorMinor1 + majorMinor2).ToPoint(Orientation); } private MajorMinor PositionFromIndex(int idx, MajorMinor totalItems) { if (totalItems.IsEmpty) return MajorMinor.Zero; MajorMinor zero = MajorMinor.Zero; zero.Minor = idx / totalItems.Major; zero.Major = idx - zero.Minor * totalItems.Major; return zero; } private bool GetViewIntersectionFromPosition( ILayoutNode layoutNode, MajorMinor position, GridLayout.GeneralFlowInfo generalInfo, GridLayout.ViewIntersectionType intersectionType, out int index) { MajorMinor repeatInstanceSize = generalInfo.repeatInstanceSize; MajorMinor majorMinor1 = position; index = 0; bool biasUp = false; bool flag1 = false; switch (intersectionType) { case ViewIntersectionType.BeginOffscreen: case ViewIntersectionType.BeginOnscreen: if (!generalInfo.repeating) flag1 = position.Major >= repeatInstanceSize.Major || position.Minor >= repeatInstanceSize.Minor; if (generalInfo.wrapping) position.Major = 0; biasUp = true; break; case ViewIntersectionType.EndOnscreen: case ViewIntersectionType.EndOffscreen: if (!generalInfo.repeating) flag1 = position.Major <= 0 || position.Minor <= 0; if (generalInfo.wrapping) position.Major = repeatInstanceSize.Major - 1; biasUp = false; break; } if (!flag1) { if (!generalInfo.repeating) position = !biasUp ? MajorMinor.Min(position, repeatInstanceSize - new MajorMinor(1, 1)) : MajorMinor.Max(position, MajorMinor.Zero); bool flag2 = position.Major != majorMinor1.Major; bool flag3 = position.Minor != majorMinor1.Minor; int dataIndex1; int generationValue1; ListUtility.GetWrappedIndex(position.Major, repeatInstanceSize.Major, out dataIndex1, out generationValue1); int dataIndex2; int generationValue2; ListUtility.GetWrappedIndex(position.Minor, repeatInstanceSize.Minor, out dataIndex2, out generationValue2); int generation = generationValue1; if (generalInfo.wrapping) generation = generationValue2; MajorMinor majorMinor2 = new MajorMinor(dataIndex1, dataIndex2); MajorMinor zero = MajorMinor.Zero; int result1; zero.Major = Math.DivRem(majorMinor2.Major, generalInfo.referenceWithSpacing.Major, out result1); int result2; zero.Minor = Math.DivRem(majorMinor2.Minor, generalInfo.referenceWithSpacing.Minor, out result2); if (generalInfo.wrapping) { if (!flag3) zero.Minor = ApplyEdgeBias(biasUp, result2, generalInfo.reference.Minor, generalInfo.allowPartialItemsMinor, zero.Minor); int max = generalInfo.totalItems.Major - 1; bool flag4 = zero.Minor == generalInfo.totalItems.Minor - 1; bool flag5 = generalInfo.totalItems.Minor * generalInfo.totalItems.Major > generalInfo.itemsCount; if (flag4 && flag5) { int num = generalInfo.itemsCount % generalInfo.totalItems.Major; if (num != 0) max = num - 1; } zero.Major = Math2.Clamp(zero.Major, 0, max); } else { zero.Minor = 0; if (!flag2) zero.Major = ApplyEdgeBias(biasUp, result1, generalInfo.reference.Major, generalInfo.allowPartialItemsMajor, zero.Major); } index = IndexFromGridPosition(zero, generation, generalInfo, out int _); } return !flag1; } private int ApplyEdgeBias( bool biasUp, int remainder, int reference, bool allowPartialItems, int currentGridPosition) { if (biasUp && (remainder >= reference || remainder != 0 && !allowPartialItems)) ++currentGridPosition; else if (!biasUp && (remainder == 0 || remainder < reference && !allowPartialItems)) --currentGridPosition; return currentGridPosition; } private int IndexFromGridPosition( MajorMinor gridPosition, int generation, GridLayout.GeneralFlowInfo generalInfo, out int normalizedIndex) { normalizedIndex = gridPosition.Minor * generalInfo.totalItems.Major + gridPosition.Major; int num = generalInfo.itemsCount * generation; return normalizedIndex + num; } private static int DivideIntegers(int a, int b, bool roundUp) { double num = a / (double)b; return roundUp ? (int)Math.Ceiling(num) : (int)Math.Floor(num); } private enum ViewIntersectionType { BeginOffscreen, BeginOnscreen, EndOnscreen, EndOffscreen, } private class GeneralFlowInfo { public Size constraint; public LayoutSlot slot; public int itemsCount; public Size referenceExtent; public bool repeating; public bool wrapping; public bool allowPartialItemsMajor; public bool allowPartialItemsMinor; public int? focusedItemIndex; public MajorMinor reference; public MajorMinor spacing; public MajorMinor referenceWithSpacing; public MajorMinor availableSpace; public MajorMinor viewSize; public MajorMinor fitItems; public MajorMinor totalItems; public MajorMinor repeatInstanceSize; public MajorMinor usedSize; public GeneralFlowInfo(int itemsCount, Size referenceExtent, Size constraint) { this.itemsCount = itemsCount; this.referenceExtent = referenceExtent; this.constraint = constraint; repeating = false; reference = MajorMinor.Zero; spacing = MajorMinor.Zero; referenceWithSpacing = MajorMinor.Zero; availableSpace = MajorMinor.Zero; viewSize = MajorMinor.Zero; totalItems = MajorMinor.Zero; repeatInstanceSize = MajorMinor.Zero; usedSize = MajorMinor.Zero; wrapping = false; allowPartialItemsMajor = false; allowPartialItemsMinor = false; focusedItemIndex = new int?(); } } private struct IndexRangeInfo { private int _beginIndex; private int _endIndex; private int _realBeginIndex; private int _realEndIndex; private bool _isValid; public IndexRangeInfo( int beginIndex, int endIndex, int realBeginIndex, int realEndIndex, GridLayout.GeneralFlowInfo generalInfo) { if (!generalInfo.repeating) { NormalizeRange(beginIndex, endIndex, generalInfo.itemsCount, out beginIndex, out endIndex); NormalizeRange(realBeginIndex, realEndIndex, generalInfo.itemsCount, out realBeginIndex, out realEndIndex); } _beginIndex = beginIndex; _endIndex = endIndex; _realBeginIndex = realBeginIndex; _realEndIndex = realEndIndex; _isValid = true; } private static void NormalizeRange( int begin, int end, int itemsCount, out int normalizedBegin, out int normalizedEnd) { int generationValue1; ListUtility.GetWrappedIndex(begin, itemsCount, out normalizedBegin, out generationValue1); int generationValue2; ListUtility.GetWrappedIndex(end, itemsCount, out normalizedEnd, out generationValue2); if (generationValue2 != generationValue1) { normalizedEnd = ListUtility.GetUnwrappedIndex(normalizedEnd, generationValue2 - generationValue1, itemsCount); normalizedBegin -= normalizedEnd - itemsCount; normalizedEnd = itemsCount; } normalizedBegin = Math2.Clamp(normalizedBegin, 0, itemsCount); normalizedEnd = Math2.Clamp(normalizedEnd, 0, itemsCount); } public int beginIndex => _beginIndex; public int endIndex => _endIndex; public int realBeginIndex => _realBeginIndex; public int realEndIndex => _realEndIndex; public bool nonEmptyRange => _isValid; } } }