You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

93 lines
2.9 KiB

using System;
using Avalonia;
using Avalonia.Controls;
namespace AuroraDesk.Presentation.Controls;
/// <summary>
/// 垂直均匀分布子元素的面板,用于渲染节点左右侧连接点。
/// </summary>
public class ConnectorColumnPanel : Panel
{
public static readonly StyledProperty<ConnectorColumnSide> SideProperty =
AvaloniaProperty.Register<ConnectorColumnPanel, ConnectorColumnSide>(nameof(Side), ConnectorColumnSide.Center);
public ConnectorColumnSide Side
{
get => GetValue(SideProperty);
set => SetValue(SideProperty, value);
}
protected override Size MeasureOverride(Size availableSize)
{
var maxWidth = 0d;
var totalHeight = 0d;
foreach (var child in Children)
{
child.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
var desired = child.DesiredSize;
var margin = (child as Control)?.Margin ?? new Thickness(0);
var horizontalMargin = Math.Abs(margin.Left) + Math.Abs(margin.Right);
var verticalMargin = Math.Max(0, margin.Top) + Math.Max(0, margin.Bottom);
maxWidth = Math.Max(maxWidth, desired.Width + horizontalMargin);
totalHeight += desired.Height + verticalMargin;
}
var height = double.IsInfinity(availableSize.Height) ? totalHeight : availableSize.Height;
return new Size(maxWidth, height);
}
protected override Size ArrangeOverride(Size finalSize)
{
var count = Children.Count;
if (count == 0)
{
return finalSize;
}
var totalHeight = 0d;
foreach (var child in Children)
{
var margin = (child as Control)?.Margin ?? new Thickness(0);
totalHeight += child.DesiredSize.Height + Math.Max(0, margin.Top) + Math.Max(0, margin.Bottom);
}
var availableHeight = finalSize.Height;
var spacing = count > 0
? Math.Max(0, (availableHeight - totalHeight) / (count + 1))
: 0;
var currentY = spacing;
foreach (var child in Children)
{
var childHeight = child.DesiredSize.Height;
var childWidth = child.DesiredSize.Width;
var margin = (child as Control)?.Margin ?? new Thickness(0);
double x = Side switch
{
ConnectorColumnSide.Left => margin.Left,
1 month ago
ConnectorColumnSide.Right => finalSize.Width - childWidth + margin.Left,
_ => (finalSize.Width - childWidth) / 2 + (margin.Left - margin.Right) / 2
};
var y = currentY + Math.Max(0, margin.Top);
child.Arrange(new Rect(x, y, childWidth, childHeight));
currentY += Math.Max(0, margin.Top) + childHeight + Math.Max(0, margin.Bottom) + spacing;
}
return finalSize;
}
}
public enum ConnectorColumnSide
{
Center,
Left,
Right
}