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:
91
Voile/Source/UI/UIElement.cs
Normal file
91
Voile/Source/UI/UIElement.cs
Normal 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;
|
||||
}
|
||||
Reference in New Issue
Block a user