using System;
namespace Avalonia.Controls.Primitives
{
///
/// A with uniform column and row sizes.
///
public class UniformGrid : Panel
{
///
/// Defines the property.
///
public static readonly StyledProperty RowsProperty =
AvaloniaProperty.Register(nameof(Rows));
///
/// Defines the property.
///
public static readonly StyledProperty ColumnsProperty =
AvaloniaProperty.Register(nameof(Columns));
///
/// Defines the property.
///
public static readonly StyledProperty FirstColumnProperty =
AvaloniaProperty.Register(nameof(FirstColumn));
private int _rows;
private int _columns;
///
/// Specifies the row count. If set to 0, row count will be calculated automatically.
///
public int Rows
{
get => GetValue(RowsProperty);
set => SetValue(RowsProperty, value);
}
///
/// Specifies the column count. If set to 0, column count will be calculated automatically.
///
public int Columns
{
get => GetValue(ColumnsProperty);
set => SetValue(ColumnsProperty, value);
}
///
/// Specifies, for the first row, the column where the items should start.
///
public int FirstColumn
{
get => GetValue(FirstColumnProperty);
set => SetValue(FirstColumnProperty, value);
}
protected override Size MeasureOverride(Size availableSize)
{
UpdateRowsAndColumns();
var maxWidth = 0d;
var maxHeight = 0d;
var childAvailableSize = new Size(availableSize.Width / _columns, availableSize.Height / _rows);
foreach (var child in Children)
{
child.Measure(childAvailableSize);
if (child.DesiredSize.Width > maxWidth)
{
maxWidth = child.DesiredSize.Width;
}
if (child.DesiredSize.Height > maxHeight)
{
maxHeight = child.DesiredSize.Height;
}
}
return new Size(maxWidth * _columns, maxHeight * _rows);
}
protected override Size ArrangeOverride(Size finalSize)
{
var x = FirstColumn;
var y = 0;
var width = finalSize.Width / _columns;
var height = finalSize.Height / _rows;
foreach (var child in Children)
{
if (!child.IsVisible)
{
continue;
}
child.Arrange(new Rect(x * width, y * height, width, height));
x++;
if (x >= _columns)
{
x = 0;
y++;
}
}
return finalSize;
}
private void UpdateRowsAndColumns()
{
_rows = Rows;
_columns = Columns;
if (FirstColumn >= Columns)
{
FirstColumn = 0;
}
var itemCount = FirstColumn;
foreach (var child in Children)
{
if (child.IsVisible)
{
itemCount++;
}
}
if (_rows == 0)
{
if (_columns == 0)
{
_rows = _columns = (int)Math.Ceiling(Math.Sqrt(itemCount));
}
else
{
_rows = Math.DivRem(itemCount, _columns, out int rem);
if (rem != 0)
{
_rows++;
}
}
}
else if (_columns == 0)
{
_columns = Math.DivRem(itemCount, _rows, out int rem);
if (rem != 0)
{
_columns++;
}
}
}
}
}