Skip to content

Commit a76e62f

Browse files
committed
Refactored Arrange to operate by rows
1 parent 5c8a3d8 commit a76e62f

File tree

2 files changed

+230
-198
lines changed

2 files changed

+230
-198
lines changed
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
namespace CommunityToolkit.WinUI.Controls;
6+
7+
public partial class StretchPanel
8+
{
9+
/// <summary>
10+
/// A struct representing the specifications of a row or column in the panel.
11+
/// </summary>
12+
private struct RowSpec
13+
{
14+
public RowSpec(GridLength layout, UVCoord desiredSize)
15+
{
16+
switch (layout.GridUnitType)
17+
{
18+
case GridUnitType.Auto:
19+
ReservedSpace = desiredSize.U;
20+
break;
21+
case GridUnitType.Pixel:
22+
ReservedSpace = layout.Value;
23+
break;
24+
case GridUnitType.Star:
25+
PortionsSum = layout.Value;
26+
MinPortionSize = desiredSize.U / layout.Value;
27+
break;
28+
}
29+
30+
MaxOffAxisSize = desiredSize.V;
31+
ItemsCount = 1;
32+
}
33+
34+
/// <summary>
35+
/// Gets the total reserved space for spacing in the row/column.
36+
/// </summary>
37+
/// <remarks>
38+
/// Items with a fixed size or auto size contribute to this value.
39+
/// </remarks>
40+
public double ReservedSpace { get; private set; }
41+
42+
/// <summary>
43+
/// Gets the sum of portions in the row/column.
44+
/// </summary>
45+
/// <remarks>
46+
/// Items with a star-sized length contribute to this value.
47+
/// </remarks>
48+
public double PortionsSum { get; private set; }
49+
50+
/// <summary>
51+
/// Gets the maximum width/height of items in the row/column.
52+
/// </summary>
53+
/// <remarks>
54+
/// Width in vertical orientation, height in horizontal orientation.
55+
/// </remarks>
56+
public double MaxOffAxisSize { get; private set; }
57+
58+
/// <summary>
59+
/// Gets the minimum size of a portion in the row/column.
60+
/// </summary>
61+
public double MinPortionSize { get; private set; }
62+
63+
/// <summary>
64+
/// Gets the number of items in the row/column.
65+
/// </summary>
66+
public int ItemsCount { get; private set; }
67+
68+
public bool TryAdd(RowSpec addend, double spacing, double maxSize)
69+
{
70+
// Check if adding the new spec would exceed the maximum size
71+
var sum = this + addend;
72+
if (sum.Measure(spacing) > maxSize)
73+
return false;
74+
75+
// Update the current spec to include the new spec
76+
this = sum;
77+
return true;
78+
}
79+
80+
public readonly double Measure(double spacing)
81+
{
82+
var totalSpacing = (ItemsCount - 1) * spacing;
83+
var totalSize = ReservedSpace + totalSpacing;
84+
85+
// Add star-sized items if applicable
86+
if (!double.IsNaN(MinPortionSize) && !double.IsInfinity(MinPortionSize))
87+
totalSize += MinPortionSize * PortionsSum;
88+
89+
return totalSize;
90+
}
91+
92+
public static RowSpec operator +(RowSpec a, RowSpec b)
93+
{
94+
var combined = new RowSpec
95+
{
96+
ReservedSpace = a.ReservedSpace + b.ReservedSpace,
97+
PortionsSum = a.PortionsSum + b.PortionsSum,
98+
MinPortionSize = Math.Max(a.MinPortionSize, b.MinPortionSize),
99+
MaxOffAxisSize = Math.Max(a.MaxOffAxisSize, b.MaxOffAxisSize),
100+
ItemsCount = a.ItemsCount + b.ItemsCount
101+
};
102+
return combined;
103+
}
104+
}
105+
106+
/// <summary>
107+
/// A struct for mapping X/Y coordinates to an orientation adjusted U/V coordinate system.
108+
/// </summary>
109+
private struct UVCoord(double x, double y, Orientation orientation)
110+
{
111+
private readonly bool _horizontal = orientation is Orientation.Horizontal;
112+
113+
public UVCoord(Size size, Orientation orientation) : this(size.Width, size.Height, orientation)
114+
{
115+
}
116+
117+
public double X { get; set; } = x;
118+
119+
public double Y { get; set; } = y;
120+
121+
public double U
122+
{
123+
readonly get => _horizontal ? X : Y;
124+
set
125+
{
126+
if (_horizontal)
127+
{
128+
X = value;
129+
}
130+
else
131+
{
132+
Y = value;
133+
}
134+
}
135+
}
136+
137+
public double V
138+
{
139+
readonly get => _horizontal ? Y : X;
140+
set
141+
{
142+
if (_horizontal)
143+
{
144+
Y = value;
145+
}
146+
else
147+
{
148+
X = value;
149+
}
150+
}
151+
}
152+
153+
public readonly Size Size => new(X, Y);
154+
}
155+
}

0 commit comments

Comments
 (0)