mirror of
https://github.com/ZuneDev/MicrosoftIris.git
synced 2026-07-27 13:13:29 -07:00
334 lines
14 KiB
C#
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;
|
|
}
|
|
}
|