Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add FrameworkElement.VerticalAlignment and FrameworkElement.HorizontalAlignment support to WrapPanel #3471

Merged
26 commits merged into from
Oct 29, 2020
Merged
Show file tree
Hide file tree
Changes from 11 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
9696fc0
code is working
vgromfeld Sep 11, 2020
471504b
optimized code + updated sample
vgromfeld Sep 11, 2020
45a290c
add horizontal alignment support
vgromfeld Sep 11, 2020
ff80d0f
remove min width/height
vgromfeld Sep 11, 2020
dd49756
removed duplicated code
vgromfeld Sep 11, 2020
97b9dba
removed custom DP
vgromfeld Sep 14, 2020
06c1763
Merge branch 'master' into wrapPanel.verticalAlignment
vgromfeld Sep 15, 2020
c0f9b5a
removed unneeded code
vgromfeld Sep 22, 2020
14fc908
Merge branch 'wrapPanel.verticalAlignment' of https://github.com/vgro…
vgromfeld Sep 22, 2020
5ecf806
Merge branch 'master' into wrapPanel.verticalAlignment
vgromfeld Sep 22, 2020
241e1b8
Merge branch 'master' into wrapPanel.verticalAlignment
michael-hawker Sep 22, 2020
088b1c9
changed Row to struct
vgromfeld Sep 24, 2020
cf81a75
Merge branch 'wrapPanel.verticalAlignment' of https://github.com/vgro…
vgromfeld Sep 24, 2020
5bf1787
Merge branch 'master' into wrapPanel.verticalAlignment
Kyaa-dost Sep 25, 2020
030444f
update logic to reuse the computation result
vgromfeld Oct 6, 2020
1952e16
Merge remote-tracking branch 'origin/master' into wrapPanel.verticalA…
vgromfeld Oct 6, 2020
f800ae9
reuse logic between measure and arrange
vgromfeld Oct 7, 2020
b5ae627
fix crash
vgromfeld Oct 23, 2020
91949d4
pr comments
vgromfeld Oct 23, 2020
e3595fd
Merge branch 'wrapPanel.verticalAlignment' of https://github.com/vgro…
vgromfeld Oct 23, 2020
792bc93
Merge branch 'master' into wrapPanel.verticalAlignment
vgromfeld Oct 23, 2020
86803d8
Merge branch 'master' into wrapPanel.verticalAlignment
michael-hawker Oct 26, 2020
959e732
fix stylecop issue
vgromfeld Oct 28, 2020
2f8825c
Merge branch 'master' into wrapPanel.verticalAlignment
vgromfeld Oct 28, 2020
20d95c1
Merge branch 'master' into wrapPanel.verticalAlignment
vgromfeld Oct 29, 2020
a9c59ae
Merge branch 'master' into wrapPanel.verticalAlignment
michael-hawker Oct 29, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,16 @@
HorizontalSpacing="@[HorizontalSpacing:Slider:5:0-200]@" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ListView.ItemContainerStyle>
<Style TargetType="ListViewItem">
<!-- Change those values to change the WrapPanel's children alignment -->
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="Padding" Value="0" />
<Setter Property="MinWidth" Value="0" />
<Setter Property="MinHeight" Value="0" />
</Style>
</ListView.ItemContainerStyle>
vgromfeld marked this conversation as resolved.
Show resolved Hide resolved
</ListView>
</Grid>
</Page>
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,8 @@ private void AddButton_Click(object sender, Windows.UI.Xaml.RoutedEventArgs e)
{
Category = "Remove",
Thumbnail = "ms-appx:///Assets/Photos/BigFourSummerHeat.jpg",
Width = Rand.Next(120, 180),
Height = Rand.Next(80, 130)
Width = Rand.Next(60, 180),
Height = Rand.Next(40, 140)
});
}

Expand Down
59 changes: 58 additions & 1 deletion Microsoft.Toolkit.Uwp.UI.Controls/WrapPanel/WrapPanel.Data.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using Windows.Foundation;
using Windows.UI.Xaml.Controls;

namespace Microsoft.Toolkit.Uwp.UI.Controls
Expand All @@ -14,12 +17,17 @@ public partial class WrapPanel
[System.Diagnostics.DebuggerDisplay("U = {U} V = {V}")]
private struct UvMeasure
{
internal static readonly UvMeasure Zero = default(UvMeasure);
internal static readonly UvMeasure Zero = default;
vgromfeld marked this conversation as resolved.
Show resolved Hide resolved

internal double U { get; set; }

internal double V { get; set; }

public UvMeasure(Orientation orientation, Size size)
: this(orientation, size.Width, size.Height)
{
}

public UvMeasure(Orientation orientation, double width, double height)
{
if (orientation == Orientation.Horizontal)
Expand All @@ -33,6 +41,55 @@ public UvMeasure(Orientation orientation, double width, double height)
V = width;
}
}

public UvMeasure Add(double u, double v)
=> new UvMeasure { U = U + u, V = V + v };
}

private struct UvRect
{
public UvMeasure Position { get; set; }

public UvMeasure Size { get; set; }

public Rect ToRect(Orientation orientation)
{
switch (orientation)
{
case Orientation.Vertical:
return new Rect(Position.V, Position.U, Size.V, Size.U);
case Orientation.Horizontal:
return new Rect(Position.U, Position.V, Size.U, Size.V);
default:
throw new NotSupportedException();
vgromfeld marked this conversation as resolved.
Show resolved Hide resolved
}
}
}

private class Row
{
private readonly List<UvRect> _childrenRects;
private UvMeasure _rowSize;

public Row()
{
_childrenRects = new List<UvRect>();
_rowSize = UvMeasure.Zero;
}

public IReadOnlyList<UvRect> ChildrenRects => _childrenRects;
vgromfeld marked this conversation as resolved.
Show resolved Hide resolved

/// <summary>
/// Gets the size of the row.
/// </summary>
public UvMeasure Size => _rowSize;
vgromfeld marked this conversation as resolved.
Show resolved Hide resolved

public void Add(UvMeasure position, UvMeasure size)
{
_childrenRects.Add(new UvRect { Position = position, Size = size });
_rowSize.U = Math.Max(_rowSize.U, position.U + size.U);
vgromfeld marked this conversation as resolved.
Show resolved Hide resolved
_rowSize.V = Math.Max(_rowSize.V, size.V);
}
}
}
}
50 changes: 35 additions & 15 deletions Microsoft.Toolkit.Uwp.UI.Controls/WrapPanel/WrapPanel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// See the LICENSE file in the project root for more information.

using System;
using System.Collections.Generic;
using Windows.Foundation;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
Expand Down Expand Up @@ -141,7 +142,7 @@ protected override Size MeasureOverride(Size availableSize)
foreach (var child in Children)
{
child.Measure(availableSize);
var currentMeasure = new UvMeasure(Orientation, child.DesiredSize.Width, child.DesiredSize.Height);
var currentMeasure = new UvMeasure(Orientation, child.DesiredSize);
if (currentMeasure.U == 0)
{
continue; // ignore collapsed items
Expand Down Expand Up @@ -199,6 +200,7 @@ protected override Size MeasureOverride(Size availableSize)
/// <inheritdoc />
protected override Size ArrangeOverride(Size finalSize)
{
var rows = new List<Row>();
if (Children.Count > 0)
{
var parentMeasure = new UvMeasure(Orientation, finalSize.Width, finalSize.Height);
Expand All @@ -207,10 +209,10 @@ protected override Size ArrangeOverride(Size finalSize)
var paddingEnd = new UvMeasure(Orientation, Padding.Right, Padding.Bottom);
var position = new UvMeasure(Orientation, Padding.Left, Padding.Top);

double currentV = 0;
var currentRow = new Row();
vgromfeld marked this conversation as resolved.
Show resolved Hide resolved
vgromfeld marked this conversation as resolved.
Show resolved Hide resolved
void Arrange(UIElement child, bool isLast = false)
{
var desiredMeasure = new UvMeasure(Orientation, child.DesiredSize.Width, child.DesiredSize.Height);
var desiredMeasure = new UvMeasure(Orientation, child.DesiredSize);
if (desiredMeasure.U == 0)
{
return; // if an item is collapsed, avoid adding the spacing
Expand All @@ -220,8 +222,10 @@ void Arrange(UIElement child, bool isLast = false)
{
// next row!
position.U = paddingStart.U;
position.V += currentV + spacingMeasure.V;
currentV = 0;
position.V += currentRow.Size.V + spacingMeasure.V;

rows.Add(currentRow);
currentRow = new Row();
}

// Stretch the last item to fill the available space
Expand All @@ -230,19 +234,10 @@ void Arrange(UIElement child, bool isLast = false)
desiredMeasure.U = parentMeasure.U - position.U;
}

// place the item
if (Orientation == Orientation.Horizontal)
{
child.Arrange(new Rect(position.U, position.V, desiredMeasure.U, desiredMeasure.V));
}
else
{
child.Arrange(new Rect(position.V, position.U, desiredMeasure.V, desiredMeasure.U));
}
currentRow.Add(position, desiredMeasure);

// adjust the location for the next items
position.U += desiredMeasure.U + spacingMeasure.U;
currentV = Math.Max(desiredMeasure.V, currentV);
}

var lastIndex = Children.Count - 1;
Expand All @@ -252,6 +247,31 @@ void Arrange(UIElement child, bool isLast = false)
}

Arrange(Children[lastIndex], StretchChild == StretchChild.Last);
if (currentRow.ChildrenRects.Count > 0)
{
rows.Add(currentRow);
}
}

if (rows.Count > 0)
{
// Now that we have all the data, we do the actual arrange pass
var childIndex = 0;
foreach (var row in rows)
{
foreach (var rect in row.ChildrenRects)
{
var child = Children[childIndex++];
var arrangeRect = new UvRect
{
Position = rect.Position,
Size = new UvMeasure { U = rect.Size.U, V = row.Size.V },
};

var finalRect = arrangeRect.ToRect(Orientation);
child.Arrange(finalRect);
}
}
}

return finalSize;
Expand Down