// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
namespace FlaxEngine.GUI
{
///
/// A panel that divides up available space between all of its children.
///
///
[ActorToolbox("GUI")]
public class GridPanel : ContainerControl
{
private Margin _slotPadding;
private float[] _cellsV;
private float[] _cellsH;
///
/// Gets or sets the padding applied to each item slot.
///
[EditorOrder(0), Tooltip("The padding margin applied to each item slot.")]
public Margin SlotPadding
{
get => _slotPadding;
set
{
if (_slotPadding != value)
{
_slotPadding = value;
PerformLayout();
}
}
}
///
/// The cells heights in container height percentage (from top to bottom). Use negative values to set fixed widths for the cells.
///
[EditorOrder(10), Limit(float.MinValue, float.MaxValue, 0.001f), Tooltip("The cells heights in container height percentage (from top to bottom). Use negative values to set fixed height for the cells.")]
public float[] RowFill
{
get => _cellsV;
set
{
_cellsV = value ?? throw new ArgumentNullException();
PerformLayout();
}
}
///
/// The cells heights in container width percentage (from left to right). Use negative values to set fixed heights for the cells.
///
[EditorOrder(20), Limit(float.MinValue, float.MaxValue, 0.001f), Tooltip("The cells heights in container width percentage (from left to right). Use negative values to set fixed width for the cells.")]
public float[] ColumnFill
{
get => _cellsH;
set
{
_cellsH = value ?? throw new ArgumentNullException();
PerformLayout();
}
}
///
/// Initializes a new instance of the class.
///
public GridPanel()
: this(2)
{
}
///
/// Initializes a new instance of the class.
///
/// The slot padding.
public GridPanel(float slotPadding)
{
AutoFocus = false;
SlotPadding = new Margin(slotPadding);
_cellsH = new[]
{
0.5f,
0.5f
};
_cellsV = new[]
{
0.5f,
0.5f
};
}
///
protected override void PerformLayoutBeforeChildren()
{
base.PerformLayoutBeforeChildren();
int i = 0;
var upperLeft = Float2.Zero;
float remainingHeight = Height;
for (int rowIndex = 0; rowIndex < _cellsV.Length; rowIndex++)
{
upperLeft.X = 0;
float cellHeight = _cellsV[rowIndex] * remainingHeight;
if (_cellsV[rowIndex] < 0)
{
cellHeight = -_cellsV[rowIndex];
remainingHeight -= cellHeight;
}
float remainingWidth = Width;
for (int columnIndex = 0; columnIndex < _cellsH.Length; columnIndex++)
{
if (i >= ChildrenCount)
break;
float cellWidth = _cellsH[columnIndex] * remainingWidth;
if (_cellsH[columnIndex] < 0)
{
cellWidth = -_cellsH[columnIndex];
remainingWidth -= cellWidth;
}
var slotBounds = new Rectangle(upperLeft, cellWidth, cellHeight);
_slotPadding.ShrinkRectangle(ref slotBounds);
var c = _children[i++];
c.Bounds = slotBounds;
upperLeft.X += cellWidth;
}
upperLeft.Y += cellHeight;
}
}
}
}