Add debug rectangle size rendering, auto-resize containers to fit all children.

This commit is contained in:
2025-06-20 18:57:36 +02:00
parent 1b09d80f7a
commit 3154b3fa10
12 changed files with 114 additions and 40 deletions

View File

@@ -1,29 +1,40 @@
using System.Numerics;
using Voile.Rendering;
namespace Voile.UI.Containers;
/// <summary>
/// A base class for all UI containers, used to position and rendering child <see cref="IElement">s.
/// </summary>
public abstract class Container : IElement, IParentableElement, IUpdatableElement
public abstract class Container : IElement, IParentableElement, IUpdatableElement, IResizeableElement, IRenderableElement
{
public IReadOnlyList<IElement> Children => _children;
public Vector2 Position { get; set; }
public Rect MinimumRect { get; set; } = Rect.Zero;
public Rect Size { get; set; } = Rect.Zero;
public bool Visible { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public Container()
{
}
public Container(List<IElement> children)
public Container(Rect minimumSize)
{
MinimumRect = minimumSize;
}
public Container(Rect minimumSize, List<IElement> children)
{
MinimumRect = minimumSize;
_children = children;
}
public void Update()
{
Arrange();
CalculateMinimumSize();
foreach (var child in _children)
{
if (child is not IUpdatableElement updatable) continue;
@@ -32,11 +43,59 @@ public abstract class Container : IElement, IParentableElement, IUpdatableElemen
}
public abstract void Arrange();
public void CalculateMinimumSize()
{
if (Children.Count == 0)
{
Size = MinimumRect;
return;
}
float minX = float.MaxValue;
float minY = float.MaxValue;
float maxX = float.MinValue;
float maxY = float.MinValue;
foreach (var child in Children)
{
var pos = child.Position;
var size = child.Size;
minX = MathF.Min(minX, pos.X);
minY = MathF.Min(minY, pos.Y);
maxX = MathF.Max(maxX, pos.X + size.Width);
maxY = MathF.Max(maxY, pos.Y + size.Height);
}
// Optionally apply padding
float padding = 0f; // or make this configurable
Size = new Rect(
maxX - minX + padding * 2,
maxY - minY + padding * 2
);
}
public void AddChild(IElement child)
{
_children.Add(child);
Update();
}
public void Render(RenderSystem renderer, Style style)
{
foreach (var child in Children)
{
if (child is not IRenderableElement renderable) continue;
renderable.Render(renderer, style);
}
}
public void DrawSize(RenderSystem renderer)
{
renderer.SetTransform(Position, Vector2.Zero);
renderer.DrawRectangleOutline(new Vector2(Size.Width, Size.Height), Color.Red, 2.0f);
}
private List<IElement> _children = new();
}