Unify Containers and Widgets by creating a base UIElement, add more anchor types, make anchor calculations an extension of Anchor.

This commit is contained in:
2025-06-22 23:28:30 +02:00
parent 95ae2de7ac
commit 61ac079f2b
9 changed files with 163 additions and 181 deletions

View File

@@ -0,0 +1,91 @@
using System.Numerics;
using Voile.Rendering;
namespace Voile.UI;
public abstract class UIElement : IElement, IRenderableElement, IResizeableElement, IUpdatableElement, IAnchorableElement
{
public bool Visible { get; set; } = true;
public bool IgnoreInput { get; set; } = false;
public Vector2 Position { get; set; } = Vector2.Zero;
public Rect Size
{
get => _size;
set
{
_size = value;
if (value.Width < MinimumSize.Width)
{
_size.Width = MinimumSize.Width;
}
if (value.Height < MinimumSize.Height)
{
_size.Height = MinimumSize.Height;
}
MarkDirty();
}
}
public Vector2 AnchorOffset { get; set; } = Vector2.Zero;
public Anchor Anchor { get; set; } = Anchor.TopLeft;
public abstract Rect MinimumSize { get; }
public bool Dirty => _dirty;
public virtual void MarkDirty() => _dirty = true;
public void Update()
{
if (!_dirty) return;
_dirty = false;
if (Size == Rect.Zero)
Size = MinimumSize;
OnUpdate();
if (_parentRect != Rect.Zero)
{
ApplyAnchor(_parentPosition, _parentRect);
}
}
public abstract void Render(RenderSystem renderer, Style style);
protected abstract void OnUpdate();
public void DrawSize(RenderSystem renderer)
{
renderer.SetTransform(Position, Vector2.Zero);
renderer.DrawRectangleOutline(new Vector2(Size.Width, Size.Height), Color.Red, 2.0f);
}
/// <summary>
/// Determines if this <see cref="UIElement"/> contains a point within its confines.
/// </summary>
/// <param name="pointPosition">A global position of the point.</param>
/// <returns>True if the point is inside the widget; otherwise, false.</returns>
public bool ContainsPoint(Vector2 point)
{
return point.X >= Position.X && point.Y >= Position.Y &&
point.X <= Position.X + Size.Width &&
point.Y <= Position.Y + Size.Height;
}
/// <summary>
/// Applies this <see cref="UIElement"/> anchor.
/// </summary>
public virtual void ApplyAnchor(Vector2 parentPosition, Rect parentRect)
{
_parentPosition = parentPosition;
_parentRect = parentRect;
Position = Anchor.Calculate(parentPosition, parentRect, Size) + new Vector2(AnchorOffset.X, AnchorOffset.Y);
}
private bool _dirty = true;
private Rect _size = Rect.Zero;
private Vector2 _parentPosition = Vector2.Zero;
private Rect _parentRect = Rect.Zero;
}