Files
Toolkit2/Toolkit.UI.Controls.Avalonia/SpacedGrid/SpacedGrid.cs
T
2024-04-13 11:41:33 +01:00

166 lines
5.0 KiB
C#

using Avalonia;
using Avalonia.Controls;
using System.Collections.Specialized;
namespace Toolkit.UI.Controls.Avalonia;
public class SpacedGrid : Grid
{
public static readonly StyledProperty<double> ColumnSpacingProperty =
AvaloniaProperty.Register<SpacedGrid, double>(nameof(ColumnSpacing), 3);
public static readonly StyledProperty<double> RowSpacingProperty =
AvaloniaProperty.Register<SpacedGrid, double>(nameof(RowSpacing), 3);
public SpacedGrid() => Children.CollectionChanged += OnCollectionChanged;
public double ColumnSpacing
{
get => GetValue(ColumnSpacingProperty);
set => SetValue(ColumnSpacingProperty, value);
}
public double RowSpacing
{
get => GetValue(RowSpacingProperty);
set => SetValue(RowSpacingProperty, value);
}
public IEnumerable<ColumnDefinition> UserDefinedColumnDefinitions =>
ColumnDefinitions.Where(definition => definition is not ISpacingDefinition);
public IEnumerable<RowDefinition> UserDefinedRowDefinitions =>
RowDefinitions.Where(definition => definition is not ISpacingDefinition);
protected override void OnInitialized()
{
base.OnInitialized();
RowDefinitions.CollectionChanged += delegate { UpdateSpacedRows(); };
ColumnDefinitions.CollectionChanged += delegate { UpdateSpacedColumns(); };
UpdateSpacedRows();
UpdateSpacedColumns();
}
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);
switch (change.Property.Name)
{
case nameof(RowSpacing):
RecalculateRowSpacing();
break;
case nameof(ColumnSpacing):
RecalculateColumnSpacing();
break;
}
}
private void OnCollectionChanged(object? sender,
NotifyCollectionChangedEventArgs args)
{
if (args.Action == NotifyCollectionChangedAction.Add || args.Action == NotifyCollectionChangedAction.Replace)
{
if (args.NewItems is not null)
{
foreach (Control item in args.NewItems)
{
SetRow(item, GetRow(item) * 2);
SetRowSpan(item, GetRowSpan(item) * 2 - 1);
SetColumn(item, GetColumn(item) * 2);
SetColumnSpan(item, GetColumnSpan(item) * 2 - 1);
}
}
}
}
private void OnInitialized(object? sender, EventArgs args)
{
if (sender is Control item)
{
item.Initialized -= OnInitialized;
SetRow(item, GetRow(item) * 2);
SetRowSpan(item, GetRowSpan(item) * 2 - 1);
var d = GetColumn(item);
SetColumn(item, GetColumn(item) * 2);
SetColumnSpan(item, GetColumnSpan(item) * 2 - 1);
}
}
private void RecalculateColumnSpacing()
{
foreach (ISpacingDefinition spacingColumn in ColumnDefinitions.OfType<ISpacingDefinition>())
{
spacingColumn.Spacing = ColumnSpacing;
}
}
private void RecalculateRowSpacing()
{
foreach (ISpacingDefinition spacingRow in RowDefinitions.OfType<ISpacingDefinition>())
{
spacingRow.Spacing = RowSpacing;
}
}
private void UpdateSpacedColumns()
{
List<ColumnDefinition> userColumnDefinitions = UserDefinedColumnDefinitions.ToList();
ColumnDefinitions actualColumnDefinitions = [];
int currentUserDefinition = 0;
int currentActualDefinition = 0;
while (currentUserDefinition < userColumnDefinitions.Count)
{
if (currentActualDefinition % 2 == 0)
{
actualColumnDefinitions.Add(userColumnDefinitions[currentUserDefinition]);
currentUserDefinition++;
}
else
{
actualColumnDefinitions.Add(new SpacingColumnDefinition(ColumnSpacing));
}
currentActualDefinition++;
}
ColumnDefinitions = actualColumnDefinitions;
ColumnDefinitions.CollectionChanged += delegate { UpdateSpacedColumns(); };
}
private void UpdateSpacedRows()
{
List<RowDefinition> userRowDefinitions = UserDefinedRowDefinitions.ToList();
RowDefinitions actualRowDefinitions = [];
int currentUserDefinition = 0;
int currentActualDefinition = 0;
while (currentUserDefinition < userRowDefinitions.Count)
{
if (currentActualDefinition % 2 == 0)
{
actualRowDefinitions.Add(userRowDefinitions[currentUserDefinition]);
currentUserDefinition++;
}
else
{
actualRowDefinitions.Add(new SpacingRowDefinition(RowSpacing));
}
currentActualDefinition++;
}
RowDefinitions = actualRowDefinitions;
RowDefinitions.CollectionChanged += delegate { UpdateSpacedRows(); };
}
}