Files
LuaCsForBarotraumaEP/Barotrauma/BarotraumaClient/Source/GUI/GUILayoutGroup.cs
2019-03-18 20:39:27 +02:00

138 lines
4.4 KiB
C#

using Microsoft.Xna.Framework;
using System.Linq;
namespace Barotrauma
{
public class GUILayoutGroup : GUIComponent
{
private bool isHorizontal;
public bool IsHorizontal
{
get { return isHorizontal; }
set
{
isHorizontal = value;
needsToRecalculate = true;
}
}
private bool stretch;
/// <summary>
/// Note that stretching cannot be undone, because the previous child sizes are not stored.
/// </summary>
public bool Stretch
{
get { return stretch; }
set
{
stretch = value;
needsToRecalculate = true;
}
}
private int absoluteSpacing;
public int AbsoluteSpacing
{
get { return absoluteSpacing; }
set
{
absoluteSpacing = MathHelper.Clamp(value, 0, int.MaxValue);
needsToRecalculate = true;
}
}
private float relativeSpacing;
public float RelativeSpacing
{
get { return relativeSpacing; }
set
{
relativeSpacing = MathHelper.Clamp(value, -1, 1);
needsToRecalculate = true;
}
}
private Anchor childAnchor;
public Anchor ChildAnchor
{
get { return childAnchor; }
set
{
childAnchor = value;
needsToRecalculate = true;
}
}
private bool needsToRecalculate;
public bool NeedsToRecalculate
{
get { return needsToRecalculate; }
}
public GUILayoutGroup(RectTransform rectT, bool isHorizontal = false, Anchor childAnchor = Anchor.TopLeft) : base(null, rectT)
{
this.isHorizontal = isHorizontal;
this.childAnchor = childAnchor;
rectT.ChildrenChanged += (child) => needsToRecalculate = true;
rectT.ScaleChanged += () => needsToRecalculate = true;
rectT.SizeChanged += () => needsToRecalculate = true;
}
public void Recalculate()
{
float stretchFactor = 1.0f;
if (stretch && RectTransform.Children.Count() > 0)
{
float totalSize = RectTransform.Children
.Where(c => !c.GUIComponent.IgnoreLayoutGroups)
.Sum(c => isHorizontal ? c.Rect.Width : c.Rect.Height);
totalSize +=
(RectTransform.Children.Count() - 1) *
(absoluteSpacing + relativeSpacing * (isHorizontal ? Rect.Width : Rect.Height));
stretchFactor = totalSize <= 0.0f ? 1.0f : (isHorizontal ? Rect.Width: Rect.Height) / totalSize;
}
int absPos = 0;
float relPos = 0;
foreach (var child in RectTransform.Children)
{
if (child.GUIComponent.IgnoreLayoutGroups) { continue; }
child.SetPosition(childAnchor);
if (isHorizontal)
{
child.RelativeOffset = new Vector2(relPos, child.RelativeOffset.Y);
child.AbsoluteOffset = new Point(absPos, child.AbsoluteOffset.Y);
absPos += (int)((child.Rect.Width + absoluteSpacing) * stretchFactor);
if (stretch)
{
child.RelativeSize = new Vector2(child.RelativeSize.X * stretchFactor, child.RelativeSize.Y);
}
}
else
{
child.RelativeOffset = new Vector2(child.RelativeOffset.X, relPos);
child.AbsoluteOffset = new Point(child.AbsoluteOffset.X, absPos);
absPos += (int)((child.Rect.Height + absoluteSpacing) * stretchFactor);
if (stretch)
{
child.RelativeSize = new Vector2(child.RelativeSize.X, child.RelativeSize.Y * stretchFactor);
}
}
relPos += relativeSpacing * stretchFactor;
}
needsToRecalculate = false;
}
protected override void Update(float deltaTime)
{
base.Update(deltaTime);
if (needsToRecalculate)
{
Recalculate();
}
}
}
}