Files
MicrosoftIris/UIX/Microsoft/Iris/Layouts/ScrollingLayout.cs
T
2022-03-03 08:14:05 -06:00

334 lines
14 KiB
C#

// Decompiled with JetBrains decompiler
// Type: Microsoft.Iris.Layouts.ScrollingLayout
// 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.Layout;
using Microsoft.Iris.Library;
using Microsoft.Iris.Render;
using Microsoft.Iris.ViewItems;
using System;
namespace Microsoft.Iris.Layouts
{
internal class ScrollingLayout : ILayout
{
private Orientation _orientation;
private int _prefetch;
private static bool s_allowScrollFocusIntoView;
public ScrollingLayout(Orientation orientation, int prefetch)
{
_orientation = orientation;
_prefetch = prefetch;
}
public Orientation Orientation
{
get => _orientation;
set
{
if (_orientation == value)
return;
_orientation = value;
}
}
public int Prefetch
{
get => _prefetch;
set
{
if (_prefetch == value)
return;
_prefetch = value;
}
}
public ItemAlignment DefaultChildAlignment => ItemAlignment.Default;
Size ILayout.Measure(ILayoutNode layoutNode, Size constraint)
{
Size size;
if (!(layoutNode.GetLayoutInput(ScrollingLayoutInput.Data) is ScrollingLayoutInput layoutInput) || layoutInput.Enabled)
{
Size infiniteConstraint = GetInfiniteConstraint(constraint);
size = DefaultLayout.Measure(layoutNode, infiniteConstraint);
layoutNode.MeasureData = size;
}
else
size = DefaultLayout.Measure(layoutNode, constraint);
return size;
}
void ILayout.Arrange(ILayoutNode layoutNode, LayoutSlot slot)
{
if (!(layoutNode.GetLayoutInput(ScrollingLayoutInput.Data) is ScrollingLayoutInput sli))
sli = new ScrollingLayoutInput();
int scrollAmount = sli.ScrollAmount;
ScrollingLayoutOutput scrollingLayoutOutput = null;
if (layoutNode.LayoutChildrenCount > 0)
{
if (sli.Enabled)
{
scrollingLayoutOutput = Arrange(layoutNode, slot, sli, ref scrollAmount);
}
else
{
DefaultLayout.Arrange(layoutNode, slot);
scrollAmount = 0;
scrollingLayoutOutput = new ScrollingLayoutOutput();
}
}
sli.SetScrollAmount(scrollAmount);
if (scrollingLayoutOutput == null)
return;
layoutNode.SetExtendedLayoutOutput(scrollingLayoutOutput);
}
private ScrollingLayoutOutput Arrange(
ILayoutNode layoutNode,
LayoutSlot slot,
ScrollingLayoutInput sli,
ref int scrollAmount)
{
LayoutSlot childSlot;
Rectangle viewBounds;
GetChildSlot(slot, scrollAmount, out childSlot, out viewBounds);
int num = scrollAmount;
ScrollingLayoutOutput scrollingLayoutOutput = ArrangeChildren(layoutNode, slot, childSlot, viewBounds, sli, true, ref scrollAmount);
if (num != scrollAmount)
{
GetChildSlot(slot, scrollAmount, out childSlot, out viewBounds);
scrollingLayoutOutput = ArrangeChildren(layoutNode, slot, childSlot, viewBounds, sli, false, ref scrollAmount);
}
return scrollingLayoutOutput;
}
private void GetChildSlot(
LayoutSlot slot,
int scrollAmount,
out LayoutSlot childSlot,
out Rectangle viewBounds)
{
Size infiniteConstraint = GetInfiniteConstraint(slot.Bounds);
Size bounds = slot.Bounds;
viewBounds = new Rectangle(Point.Zero, bounds);
Point offset = ScrollAmountToOffset(_prefetch);
Rectangle viewPeripheralBounds = viewBounds;
viewPeripheralBounds.Inflate(offset.X, offset.Y);
childSlot = new LayoutSlot(infiniteConstraint, slot.Offset, viewBounds, viewPeripheralBounds);
}
private ScrollingLayoutOutput ArrangeChildren(
ILayoutNode layoutNode,
LayoutSlot slot,
LayoutSlot childSlot,
Rectangle viewBounds,
ScrollingLayoutInput sli,
bool applyPendingScrollData,
ref int scrollAmount)
{
Rectangle areaOfInterestBounds = Rectangle.Zero;
bool scrollAreaOfInterestIntoView = sli.ScrollIntoViewDisposition.Enabled;
bool flag1 = false;
VisibleIndexRangeLayoutOutput rangeLayoutOutput = null;
Rectangle rectangle1 = Rectangle.Zero;
Rectangle bounds = new Rectangle(new MajorMinor(-scrollAmount, 0).ToPoint(Orientation), Size.Max(slot.Bounds, (Size)layoutNode.MeasureData));
foreach (ILayoutNode layoutChild in layoutNode.LayoutChildren)
{
layoutChild.Arrange(childSlot, bounds);
rangeLayoutOutput = layoutChild.GetExtendedLayoutOutput(VisibleIndexRangeLayoutOutput.DataCookie) as VisibleIndexRangeLayoutOutput;
bool flag2 = true;
AreaOfInterest area1;
if (!layoutChild.TryGetAreaOfInterest(AreaOfInterestID.ScrollIntoViewRequest, out area1) && !layoutChild.TryGetAreaOfInterest(AreaOfInterestID.PendingFocus, out area1))
flag2 = layoutChild.TryGetAreaOfInterest(AreaOfInterestID.Focus, out area1);
if (flag2)
areaOfInterestBounds = area1.Rectangle;
if (IsFocusAreaOfInterest(area1.Id) && !sli.ScrollIntoViewDisposition.Enabled)
DisallowScrollFocusIntoView();
scrollAreaOfInterestIntoView &= ScrollFocusIntoView;
if (area1.Id == AreaOfInterestID.ScrollIntoViewRequest && !areaOfInterestBounds.IsZero)
{
scrollAreaOfInterestIntoView = true;
flag1 = true;
}
Rectangle rectangle2 = new Rectangle(Point.Zero, layoutChild.DesiredSize);
AreaOfInterest area2;
if (layoutChild.TryGetAreaOfInterest(AreaOfInterestID.ScrollableRange, out area2))
rectangle2 = Rectangle.Union(rectangle2, area2.Rectangle);
rectangle1 = Rectangle.Union(rectangle1, rectangle2);
}
ScrollingLayoutOutput scrollAmount1 = CalculateScrollAmount(layoutNode, viewBounds, rectangle1, sli, applyPendingScrollData, scrollAreaOfInterestIntoView, areaOfInterestBounds, ref scrollAmount);
scrollAmount1.VisibleIndices = rangeLayoutOutput;
scrollAmount1.ProcessedExplicitScrollIntoViewRequest = flag1;
scrollAmount1.ScrollFocusIntoView = ScrollFocusIntoView;
return scrollAmount1;
}
private bool IsFocusAreaOfInterest(AreaOfInterestID areaOfInterestID) => areaOfInterestID == AreaOfInterestID.PendingFocus || areaOfInterestID == AreaOfInterestID.Focus;
private ScrollingLayoutOutput CalculateScrollAmount(
ILayoutNode layoutNode,
Rectangle viewBounds,
Rectangle scrollableBounds,
ScrollingLayoutInput sli,
bool applyPendingScrollData,
bool scrollAreaOfInterestIntoView,
Rectangle areaOfInterestBounds,
ref int scrollAmount)
{
int space1 = ItemToSpace(viewBounds.Size);
int space2 = ItemToSpace(scrollableBounds.Size);
int num1 = -(space1 - space2);
int num2 = (int)Math.Round(space1 * (double)sli.PageStep);
int num3 = ItemToSpace(scrollableBounds.Location.ToSize());
int num4 = num3 + num1;
if (num1 < 0)
{
num3 = 0;
num4 = 0;
}
if (!areaOfInterestBounds.IsZero && scrollAreaOfInterestIntoView)
{
scrollAmount = ScrollIntoView(layoutNode, areaOfInterestBounds, scrollAmount, space1, space2, num3, num4, sli.ScrollIntoViewDisposition);
if (sli.SecondaryScrollIntoViewDisposition != null && sli.SecondaryScrollIntoViewDisposition.Enabled)
scrollAmount = ScrollIntoView(layoutNode, areaOfInterestBounds, scrollAmount, space1, space2, num3, num4, sli.SecondaryScrollIntoViewDisposition);
scrollAmount = Math.Max(scrollAmount, num3);
scrollAmount = Math.Min(scrollAmount, num4);
}
else if (num1 > 0)
{
if (applyPendingScrollData)
{
float position = 0.0f;
if (sli.GetPendingScrollPosition(out position))
{
int num5 = (int)Math2.Blend(num3, num4, position, false);
scrollAmount = num5;
}
int amount = 0;
if (sli.GetPendingPageRequests(out amount))
{
int num5 = amount * num2;
scrollAmount += num5;
}
}
scrollAmount = Math.Max(scrollAmount, num3);
scrollAmount = Math.Min(scrollAmount, num4);
}
else
scrollAmount = 0;
int space3 = ItemToSpace(scrollableBounds.Location.ToSize());
bool flag1 = -scrollAmount < space3;
bool flag2 = -scrollAmount + space2 > space1;
float num6 = 1f;
float val2 = 1f;
float num7 = 0.0f;
float num8 = 1f;
float num9 = num1;
float num10 = scrollAmount;
if (num2 > 0)
{
val2 = (float)(num9 / (double)num2 + 1.0);
num6 = Math.Max(Math.Min((float)(num10 / (double)num2 + 1.0), val2), 0.0f);
}
if (num1 > 0)
{
num7 = num10 / space2;
num8 = (num10 + space1) / space2;
}
return new ScrollingLayoutOutput()
{
CanScrollNegative = flag1,
CanScrollPositive = flag2,
CurrentPage = num6,
TotalPages = val2,
ViewNear = num7,
ViewFar = num8
};
}
private int ScrollIntoView(
ILayoutNode layoutNode,
Rectangle areaOfInterestBounds,
int scrollAmount,
int viewMajorSpace,
int naturalMajorSpace,
int naturalMinScroll,
int naturalMaxScroll,
ScrollIntoViewDisposition scrollIntoView)
{
Rectangle rectangle = areaOfInterestBounds;
int num1 = ItemToSpace(rectangle.Location.ToSize());
int space = ItemToSpace(rectangle.Size);
int num2 = num1 + space;
int num3 = scrollAmount;
int num4 = viewMajorSpace;
int num5 = num3 + num4;
int num6 = num3;
int num7 = num5;
int beginPadding = scrollIntoView.BeginPadding;
switch (scrollIntoView.BeginPaddingRelativeTo)
{
case RelativeEdge.Near:
num6 = num3 + beginPadding;
break;
case RelativeEdge.Far:
num6 = num5 - beginPadding;
break;
}
int endPadding = scrollIntoView.EndPadding;
switch (scrollIntoView.EndPaddingRelativeTo)
{
case RelativeEdge.Near:
num7 = num3 + endPadding;
break;
case RelativeEdge.Far:
num7 = num5 - endPadding;
break;
}
int num8 = num6 - num3;
int num9 = num7 - num5;
if (scrollIntoView.Locked)
{
float num10 = num7 - num6;
float num11 = num10 * scrollIntoView.LockedPosition;
float num12 = num10 * (1f - scrollIntoView.LockedPosition);
int num13 = num1 + (int)(space * (double)scrollIntoView.LockedAlignment);
num1 = num13 - (int)num11;
num2 = num13 + (int)num12;
}
int num14 = scrollAmount;
if (num2 > num7)
{
scrollAmount = num2 - num4 - num9;
int num10 = scrollAmount - num14;
num6 += num10;
int num11 = num7 + num10;
}
if (num1 < num6)
scrollAmount = num1 - num8;
if (scrollIntoView.ContentPositioningBehavior == ContentPositioningPolicy.ShowMaximalContent)
scrollAmount = Math2.Clamp(scrollAmount, naturalMinScroll, naturalMaxScroll);
return scrollAmount;
}
private int ItemToSpace(Size size) => new MajorMinor(size, _orientation).Major;
protected Point ScrollAmountToOffset(int scrollAmount) => new MajorMinor(scrollAmount, 0).ToPoint(_orientation);
protected Size GetInfiniteConstraint(Size maxExtent) => new MajorMinor(maxExtent, _orientation)
{
Major = 16777215
}.ToSize(_orientation);
public static void ResetScrollFocusIntoView() => s_allowScrollFocusIntoView = true;
public static bool ScrollFocusIntoView => s_allowScrollFocusIntoView;
public static void DisallowScrollFocusIntoView() => s_allowScrollFocusIntoView = false;
}
}