Browse Source

Initial port of WPF StackPanel

pull/2644/head
Wiesław Šoltés 7 years ago
parent
commit
1c2e270155
  1. 136
      src/Avalonia.Controls/StackPanel.cs

136
src/Avalonia.Controls/StackPanel.cs

@ -2,9 +2,7 @@
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Linq;
using Avalonia.Input;
using Avalonia.Layout;
using Avalonia.Input
namespace Avalonia.Controls
{
@ -155,106 +153,118 @@ namespace Avalonia.Controls
}
/// <summary>
/// Measures the control.
/// General StackPanel layout behavior is to grow unbounded in the "stacking" direction (Size To Content).
/// Children in this dimension are encouraged to be as large as they like. In the other dimension,
/// StackPanel will assume the maximum size of its children.
/// </summary>
/// <param name="availableSize">The available size.</param>
/// <returns>The desired size of the control.</returns>
protected override Size MeasureOverride(Size availableSize)
/// <param name="constraint">Constraint</param>
/// <returns>Desired size</returns>
protected override Size MeasureOverride(Size constraint)
{
double childAvailableWidth = double.PositiveInfinity;
double childAvailableHeight = double.PositiveInfinity;
Size stackDesiredSize = new Size();
var children = Children;
Size layoutSlotSize = constraint;
bool fHorizontal = (Orientation == Orientation.Horizontal);
double spacing = Spacing;
bool hasVisibleChild = false;
if (Orientation == Orientation.Vertical)
//
// Initialize child sizing and iterator data
// Allow children as much size as they want along the stack.
//
if (fHorizontal)
{
childAvailableWidth = availableSize.Width;
if (!double.IsNaN(Width))
{
childAvailableWidth = Width;
}
childAvailableWidth = Math.Min(childAvailableWidth, MaxWidth);
childAvailableWidth = Math.Max(childAvailableWidth, MinWidth);
layoutSlotSize = layoutSlotSize.WithWidth(Double.PositiveInfinity);
}
else
{
childAvailableHeight = availableSize.Height;
layoutSlotSize = layoutSlotSize.WithHeight(Double.PositiveInfinity);
}
if (!double.IsNaN(Height))
{
childAvailableHeight = Height;
}
//
// Iterate through children.
// While we still supported virtualization, this was hidden in a child iterator (see source history).
//
for (int i = 0, count = children.Count; i < count; ++i)
{
// Get next child.
var child = children[i];
childAvailableHeight = Math.Min(childAvailableHeight, MaxHeight);
childAvailableHeight = Math.Max(childAvailableHeight, MinHeight);
}
if (child == null)
{ continue; }
double measuredWidth = 0;
double measuredHeight = 0;
double spacing = Spacing;
bool hasVisibleChild = Children.Any(c => c.IsVisible);
if (child.IsVisible)
{
hasVisibleChild = true;
}
foreach (Control child in Children)
{
child.Measure(new Size(childAvailableWidth, childAvailableHeight));
Size size = child.DesiredSize;
// Measure the child.
child.Measure(layoutSlotSize);
Size childDesiredSize = child.DesiredSize;
if (Orientation == Orientation.Vertical)
// Accumulate child size.
if (fHorizontal)
{
measuredHeight += size.Height + (child.IsVisible ? spacing : 0);
measuredWidth = Math.Max(measuredWidth, size.Width);
stackDesiredSize = stackDesiredSize.WithWidth(stackDesiredSize.Width + childDesiredSize.Width + (child.IsVisible ? spacing : 0));
stackDesiredSize = stackDesiredSize.WithHeight(Math.Max(stackDesiredSize.Height, childDesiredSize.Height));
}
else
{
measuredWidth += size.Width + (child.IsVisible ? spacing : 0);
measuredHeight = Math.Max(measuredHeight, size.Height);
stackDesiredSize = stackDesiredSize.WithWidth(Math.Max(stackDesiredSize.Width, childDesiredSize.Width));
stackDesiredSize = stackDesiredSize.WithHeight(stackDesiredSize.Height + childDesiredSize.Height + (child.IsVisible ? spacing : 0));
}
}
if (Orientation == Orientation.Vertical)
{
measuredHeight -= (hasVisibleChild ? spacing : 0);
stackDesiredSize = stackDesiredSize.WithHeight(stackDesiredSize.Height - (hasVisibleChild ? spacing : 0));
}
else
{
measuredWidth -= (hasVisibleChild ? spacing : 0);
stackDesiredSize = stackDesiredSize.WithWidth(stackDesiredSize.Width - (hasVisibleChild ? spacing : 0));
}
return new Size(measuredWidth, measuredHeight).Constrain(availableSize);
return stackDesiredSize;
}
/// <inheritdoc/>
/// <summary>
/// Content arrangement.
/// </summary>
/// <param name="finalSize">Arrange size</param>
protected override Size ArrangeOverride(Size finalSize)
{
var orientation = Orientation;
var children = Children;
bool fHorizontal = (Orientation == Orientation.Horizontal);
Rect rcChild = new Rect(finalSize);
double previousChildSize = 0.0;
var spacing = Spacing;
var finalRect = new Rect(finalSize);
var pos = 0.0;
foreach (Control child in Children)
//
// Arrange and Position Children.
//
for (int i = 0, count = children.Count; i < count; ++i)
{
if (!child.IsVisible)
{
continue;
}
var child = children[i];
double childWidth = child.DesiredSize.Width;
double childHeight = child.DesiredSize.Height;
if (child == null)
{ continue; }
if (orientation == Orientation.Vertical)
if (fHorizontal)
{
var rect = new Rect(0, pos, childWidth, childHeight)
.Align(finalRect, child.HorizontalAlignment, VerticalAlignment.Top);
ArrangeChild(child, rect, finalSize, orientation);
pos += childHeight + spacing;
rcChild = rcChild.WithX(rcChild.X + previousChildSize);
previousChildSize = child.DesiredSize.Width;
rcChild = rcChild.WithWidth(previousChildSize);
rcChild = rcChild.WithHeight(Math.Max(finalSize.Height, child.DesiredSize.Height) + (child.IsVisible ? spacing : 0));
}
else
{
var rect = new Rect(pos, 0, childWidth, childHeight)
.Align(finalRect, HorizontalAlignment.Left, child.VerticalAlignment);
ArrangeChild(child, rect, finalSize, orientation);
pos += childWidth + spacing;
rcChild = rcChild.WithY(rcChild.Y + previousChildSize);
previousChildSize = child.DesiredSize.Height;
rcChild = rcChild.WithHeight(previousChildSize);
rcChild = rcChild.WithWidth(Math.Max(finalSize.Width, child.DesiredSize.Width) + (child.IsVisible ? spacing : 0));
}
child.Arrange(rcChild);
}
return finalSize;

Loading…
Cancel
Save