2023-05-11 23:11:39 -04:00
|
|
|
|
using Avalonia;
|
|
|
|
|
using Avalonia.Controls;
|
|
|
|
|
using SPTInstaller.Behaviors;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
|
2023-07-12 09:19:33 +02:00
|
|
|
|
namespace SPTInstaller.CustomControls;
|
|
|
|
|
|
|
|
|
|
public class DistributedSpacePanel : Panel
|
2023-05-11 23:11:39 -04:00
|
|
|
|
{
|
2023-07-12 09:19:33 +02:00
|
|
|
|
protected override Size MeasureOverride(Size availableSize)
|
2023-05-11 23:11:39 -04:00
|
|
|
|
{
|
2023-07-12 09:19:33 +02:00
|
|
|
|
var children = Children;
|
2023-05-11 23:11:39 -04:00
|
|
|
|
|
2023-07-12 09:19:33 +02:00
|
|
|
|
for (int i = 0; i < children.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
// measure child objects so we can use their desired size in the arrange override
|
|
|
|
|
var child = children[i];
|
|
|
|
|
child.Measure(availableSize);
|
2023-05-11 23:11:39 -04:00
|
|
|
|
}
|
|
|
|
|
|
2023-07-12 09:19:33 +02:00
|
|
|
|
// we want to use all available space
|
|
|
|
|
return availableSize;
|
|
|
|
|
}
|
2023-05-11 23:11:39 -04:00
|
|
|
|
|
2023-07-12 09:19:33 +02:00
|
|
|
|
protected override Size ArrangeOverride(Size finalSize)
|
|
|
|
|
{
|
|
|
|
|
var children = Children;
|
|
|
|
|
Rect rcChild = new Rect(finalSize);
|
|
|
|
|
double previousChildSize = 0.0;
|
2023-05-11 23:11:39 -04:00
|
|
|
|
|
2023-07-12 09:19:33 +02:00
|
|
|
|
// get child objects that don't want to span the entire control
|
|
|
|
|
var nonSpanningChildren = children.Where(x => x.GetValue(SpanBehavior.SpanProperty) == false).ToList();
|
2023-05-11 23:11:39 -04:00
|
|
|
|
|
2023-07-12 09:19:33 +02:00
|
|
|
|
// get the total height off all non-spanning child objects
|
|
|
|
|
var totalChildHeight = nonSpanningChildren.Select(x => x.DesiredSize.Height).Sum();
|
2023-05-11 23:11:39 -04:00
|
|
|
|
|
2023-07-12 09:19:33 +02:00
|
|
|
|
// remove the total child height from our controls final size and divide it by the total non-spanning child objects
|
|
|
|
|
// except the last one, since it needs no space after it
|
|
|
|
|
var spacing = (finalSize.Height - totalChildHeight) / (nonSpanningChildren.Count - 1);
|
2023-05-11 23:11:39 -04:00
|
|
|
|
|
2023-07-12 09:19:33 +02:00
|
|
|
|
for (int i = 0; i < children.Count; i++)
|
|
|
|
|
{
|
|
|
|
|
var child = children[i];
|
2023-05-11 23:11:39 -04:00
|
|
|
|
|
2023-07-12 09:19:33 +02:00
|
|
|
|
var spanChild = child.GetValue(SpanBehavior.SpanProperty);
|
2023-05-11 23:11:39 -04:00
|
|
|
|
|
2023-07-12 09:19:33 +02:00
|
|
|
|
if (spanChild)
|
|
|
|
|
{
|
|
|
|
|
// move any spanning children to the top of the array to push them behind the other controls (visually)
|
|
|
|
|
children.Move(i, 0);
|
2023-05-11 23:11:39 -04:00
|
|
|
|
|
2023-07-12 09:19:33 +02:00
|
|
|
|
rcChild = rcChild.WithY(0)
|
|
|
|
|
.WithX(0)
|
|
|
|
|
.WithHeight(finalSize.Height)
|
|
|
|
|
.WithWidth(finalSize.Width);
|
2023-05-11 23:11:39 -04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2023-07-12 09:19:33 +02:00
|
|
|
|
child.Arrange(rcChild);
|
|
|
|
|
continue;
|
|
|
|
|
};
|
2023-05-11 23:11:39 -04:00
|
|
|
|
|
2023-07-12 09:19:33 +02:00
|
|
|
|
rcChild = rcChild.WithY(rcChild.Y + previousChildSize);
|
|
|
|
|
previousChildSize = child.DesiredSize.Height;
|
|
|
|
|
rcChild = rcChild.WithHeight(previousChildSize)
|
|
|
|
|
.WithWidth(Math.Max(finalSize.Width, child.DesiredSize.Width));
|
2023-05-11 23:11:39 -04:00
|
|
|
|
|
2023-07-12 09:19:33 +02:00
|
|
|
|
previousChildSize += spacing;
|
2023-05-11 23:11:39 -04:00
|
|
|
|
|
2023-07-12 09:19:33 +02:00
|
|
|
|
child.Arrange(rcChild);
|
2023-05-11 23:11:39 -04:00
|
|
|
|
}
|
2023-07-12 09:19:33 +02:00
|
|
|
|
|
|
|
|
|
return finalSize;
|
2023-05-11 23:11:39 -04:00
|
|
|
|
}
|
2023-07-12 09:19:33 +02:00
|
|
|
|
}
|