using Avalonia; using Avalonia.Controls; namespace LehrerApp.Desktop.Views.Groups; /// /// Ordnet Sitzplätze in einem Raster an und fügt zwischen ausgewählten Spalten zusätzliche /// transparente Breite ein. Anders als ein UniformGrid kann der Abstand je Spaltengrenze variieren. /// public sealed class SeatingPlanPanel : Panel { public static readonly StyledProperty ColumnsProperty = AvaloniaProperty.Register(nameof(Columns), 1); public static readonly StyledProperty> ColumnGapWidthsProperty = AvaloniaProperty.Register>( nameof(ColumnGapWidths), Array.Empty()); public int Columns { get => GetValue(ColumnsProperty); set => SetValue(ColumnsProperty, value); } public IReadOnlyList ColumnGapWidths { get => GetValue(ColumnGapWidthsProperty); set => SetValue(ColumnGapWidthsProperty, value); } static SeatingPlanPanel() => AffectsMeasure(ColumnsProperty, ColumnGapWidthsProperty); protected override Size MeasureOverride(Size availableSize) { foreach (var child in Children) child.Measure(Size.Infinity); if (Children.Count == 0) return default; var columns = Math.Max(1, Columns); var rows = (int)Math.Ceiling((double)Children.Count / columns); var cellWidth = Children.Max(child => child.DesiredSize.Width); var cellHeight = Children.Max(child => child.DesiredSize.Height); return new Size(cellWidth * columns + GapWidth(columns), cellHeight * rows); } protected override Size ArrangeOverride(Size finalSize) { if (Children.Count == 0) return finalSize; var columns = Math.Max(1, Columns); var cellWidth = Children.Max(child => child.DesiredSize.Width); var cellHeight = Children.Max(child => child.DesiredSize.Height); for (var index = 0; index < Children.Count; index++) { var column = index % columns; var row = index / columns; var child = Children[index]; var x = column * cellWidth + GapWidthBefore(column); var childX = x + Math.Max(0, (cellWidth - child.DesiredSize.Width) / 2); var childY = row * cellHeight + Math.Max(0, (cellHeight - child.DesiredSize.Height) / 2); child.Arrange(new Rect(childX, childY, child.DesiredSize.Width, child.DesiredSize.Height)); } return finalSize; } private double GapWidth(int columns) => Enumerable.Range(0, Math.Max(0, columns - 1)).Sum(GapAt); private double GapWidthBefore(int column) => Enumerable.Range(0, Math.Max(0, column)).Sum(GapAt); private double GapAt(int index) => index < ColumnGapWidths.Count ? Math.Clamp(ColumnGapWidths[index], 0, 300) : 0; }