Add MarginContainer, mark parent elements dirty when child gets marked dirty too.

This commit is contained in:
2025-06-25 00:35:35 +02:00
parent 5bf052db96
commit 64d3dba42d
5 changed files with 111 additions and 13 deletions

View File

@@ -60,6 +60,18 @@ public abstract class Container : UIElement, IParentableElement
}
}
public override void MarkDirty()
{
base.MarkDirty();
foreach (var child in _children)
{
if (child is not IUpdatableElement updatable) continue;
updatable.MarkDirty();
}
}
/// <summary>
/// Called when this <see cref="Container"/> has to rearrange its children.
/// </summary>

View File

@@ -51,9 +51,6 @@ public class FillContainer : Container
protected override void OnUpdate()
{
base.OnUpdate();
if (Size == _lastParentSize) return;
Size = _lastParentSize;
}

View File

@@ -0,0 +1,78 @@
using System.Numerics;
namespace Voile.UI.Containers;
/// <summary>
/// Represents the margin offsets applied around an element.
/// </summary>
public struct Margin
{
public float Left;
public float Right;
public float Top;
public float Bottom;
public Margin(float uniform)
{
Left = Right = Top = Bottom = uniform;
}
public Margin(float horizontal, float vertical)
{
Left = Right = horizontal;
Top = Bottom = vertical;
}
public Margin(float left, float right, float top, float bottom)
{
Left = left;
Right = right;
Top = top;
Bottom = bottom;
}
public static Margin Zero => new Margin(0);
}
public class MarginContainer : Container
{
/// <summary>
/// The margin to apply around the contents of this container.
/// </summary>
public Margin Margin { get; set; }
/// <summary>
/// Specifies if this <see cref="MarginContainer"/> will fill to parent size.
/// </summary>
public bool Fill { get; set; } = true;
public MarginContainer() : this(new Margin()) { }
public MarginContainer(Margin margin)
{
Margin = margin;
}
protected override void OnUpdate()
{
base.OnUpdate();
if (Parent == null) return;
Size = Parent.Size;
}
public override void Arrange()
{
foreach (var child in Children)
{
var newPosition = new Vector2(Margin.Left, Margin.Top);
var newSize = new Rect(
Size.Width - Margin.Left - Margin.Right,
Size.Height - Margin.Top - Margin.Bottom
);
child.Size = newSize;
child.LocalPosition = newPosition;
}
}
}

View File

@@ -23,8 +23,6 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme
get => _size;
set
{
_size = value;
if (value.Width < MinimumSize.Width)
{
_size.Width = MinimumSize.Width;
@@ -35,7 +33,12 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme
_size.Height = MinimumSize.Height;
}
MarkDirty();
if (_size != value)
{
MarkDirty();
}
_size = value;
}
}
public Vector2 AnchorOffset { get; set; } = Vector2.Zero;
@@ -44,7 +47,15 @@ public abstract class UIElement : IElement, IRenderableElement, IResizeableEleme
public abstract Rect MinimumSize { get; }
public bool Dirty => _dirty;
public virtual void MarkDirty() => _dirty = true;
public virtual void MarkDirty()
{
if (Parent != null && !Parent.Dirty)
{
Parent.MarkDirty();
}
_dirty = true;
}
/// <summary>
/// Sets a parent element for this <see cref="UIElement"/>.