Neue Abwensenheitsmodi plus Upgrade Sitzplan

This commit is contained in:
2026-08-19 12:27:12 +02:00
parent 1731e5088e
commit b2c1b15167
16 changed files with 383 additions and 30 deletions
@@ -0,0 +1,77 @@
using Avalonia;
using Avalonia.Controls;
namespace LehrerApp.Desktop.Views.Groups;
/// <summary>
/// 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.
/// </summary>
public sealed class SeatingPlanPanel : Panel
{
public static readonly StyledProperty<int> ColumnsProperty =
AvaloniaProperty.Register<SeatingPlanPanel, int>(nameof(Columns), 1);
public static readonly StyledProperty<IReadOnlyList<double>> ColumnGapWidthsProperty =
AvaloniaProperty.Register<SeatingPlanPanel, IReadOnlyList<double>>(
nameof(ColumnGapWidths), Array.Empty<double>());
public int Columns
{
get => GetValue(ColumnsProperty);
set => SetValue(ColumnsProperty, value);
}
public IReadOnlyList<double> ColumnGapWidths
{
get => GetValue(ColumnGapWidthsProperty);
set => SetValue(ColumnGapWidthsProperty, value);
}
static SeatingPlanPanel() =>
AffectsMeasure<SeatingPlanPanel>(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;
}