260 lines
8.4 KiB
C#
260 lines
8.4 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Diagnostics;
|
|
|
|
using Barotrauma;
|
|
using Microsoft.Xna.Framework;
|
|
using Microsoft.Xna.Framework.Input;
|
|
using Microsoft.Xna.Framework.Graphics;
|
|
|
|
namespace QICrabUI
|
|
{
|
|
/// <summary>
|
|
/// Resizing components to it's Width and placing them sequentially
|
|
/// </summary>
|
|
public class CUILayoutVerticalList : CUILayout
|
|
{
|
|
internal float TotalHeight;
|
|
public CUIDirection Direction;
|
|
|
|
public float Gap { get; set; }
|
|
|
|
public bool ResizeToHostWidth { get; set; } = true;
|
|
|
|
|
|
private class CUIComponentSize
|
|
{
|
|
public CUIComponent Component;
|
|
public Vector2 Size;
|
|
public CUIComponentSize(CUIComponent component, Vector2 size)
|
|
{
|
|
Component = component;
|
|
Size = size;
|
|
}
|
|
}
|
|
private List<CUIComponentSize> Sizes = new List<CUIComponentSize>();
|
|
private List<CUIComponentSize> Resizible = new List<CUIComponentSize>();
|
|
|
|
internal override void Update()
|
|
{
|
|
Stopwatch sw = new Stopwatch();
|
|
|
|
if (Changed)
|
|
{
|
|
Host.InvokeOnLayoutUpdated();
|
|
|
|
Sizes.Clear();
|
|
Resizible.Clear();
|
|
|
|
TotalHeight = 0;
|
|
|
|
sw.Restart();
|
|
foreach (CUIComponent c in Host.Children)
|
|
{
|
|
float h = 0;
|
|
float w = 0;
|
|
|
|
if (ResizeToHostWidth)
|
|
{
|
|
w = Host.Real.Width;
|
|
}
|
|
else
|
|
{
|
|
if (c.Relative.Width.HasValue) w = c.Relative.Width.Value * Host.Real.Width;
|
|
if (c.CrossRelative.Width.HasValue) w = c.CrossRelative.Width.Value * Host.Real.Height;
|
|
if (c.Absolute.Width.HasValue) w = c.Absolute.Width.Value;
|
|
|
|
if (c.RelativeMin.Width.HasValue) w = Math.Max(w, c.RelativeMin.Width.Value * Host.Real.Width);
|
|
if (c.AbsoluteMin.Width.HasValue) w = Math.Max(w, c.AbsoluteMin.Width.Value);
|
|
|
|
if (!c.RelativeMin.Width.HasValue && !c.AbsoluteMin.Width.HasValue && c.ForcedMinSize.X.HasValue)
|
|
{
|
|
w = Math.Max(w, c.ForcedMinSize.X.Value);
|
|
}
|
|
|
|
if (c.RelativeMax.Width.HasValue) w = Math.Min(w, c.RelativeMax.Width.Value * Host.Real.Width);
|
|
if (c.AbsoluteMax.Width.HasValue) w = Math.Min(w, c.AbsoluteMax.Width.Value);
|
|
}
|
|
|
|
Vector2 s = new Vector2(w, h);
|
|
|
|
|
|
if (!c.FillEmptySpace.Y && !c.Ghost.Y)
|
|
{
|
|
if (c.Relative.Height.HasValue)
|
|
{
|
|
h = c.Relative.Height.Value * Host.Real.Height;
|
|
CUIDebug.Capture(Host, c, "VerticalList.Update", "Relative.Height", "h", h.ToString());
|
|
}
|
|
if (c.CrossRelative.Height.HasValue)
|
|
{
|
|
h = c.CrossRelative.Height.Value * Host.Real.Width;
|
|
CUIDebug.Capture(Host, c, "VerticalList.Update", "CrossRelative.Height", "h", h.ToString());
|
|
}
|
|
if (c.Absolute.Height.HasValue)
|
|
{
|
|
h = c.Absolute.Height.Value;
|
|
CUIDebug.Capture(Host, c, "VerticalList.Update", "Absolute.Height", "h", h.ToString());
|
|
}
|
|
|
|
if (c.RelativeMin.Height.HasValue)
|
|
{
|
|
h = Math.Max(h, c.RelativeMin.Height.Value * Host.Real.Height);
|
|
CUIDebug.Capture(Host, c, "VerticalList.Update", "RelativeMin.Height", "h", h.ToString());
|
|
}
|
|
if (c.AbsoluteMin.Height.HasValue)
|
|
{
|
|
h = Math.Max(h, c.AbsoluteMin.Height.Value);
|
|
CUIDebug.Capture(Host, c, "VerticalList.Update", "AbsoluteMin.Height", "h", h.ToString());
|
|
}
|
|
if (!c.RelativeMin.Height.HasValue && !c.AbsoluteMin.Height.HasValue && c.ForcedMinSize.Y.HasValue)
|
|
{
|
|
h = Math.Max(h, c.ForcedMinSize.Y.Value);
|
|
CUIDebug.Capture(Host, c, "VerticalList.Update", "ForcedMinSize.Y", "h", h.ToString());
|
|
}
|
|
|
|
if (c.RelativeMax.Height.HasValue)
|
|
{
|
|
h = Math.Min(h, c.RelativeMax.Height.Value * Host.Real.Height);
|
|
CUIDebug.Capture(Host, c, "VerticalList.Update", "RelativeMax.Height", "h", h.ToString());
|
|
}
|
|
if (c.AbsoluteMax.Height.HasValue)
|
|
{
|
|
h = Math.Min(h, c.AbsoluteMax.Height.Value);
|
|
CUIDebug.Capture(Host, c, "VerticalList.Update", "AbsoluteMax.Height", "h", h.ToString());
|
|
}
|
|
|
|
s = new Vector2(w, h);
|
|
Vector2 okSize = c.AmIOkWithThisSize(s);
|
|
CUIDebug.Capture(Host, c, "VerticalList.Update", "AmIOkWithThisSize", "s", okSize.ToString());
|
|
|
|
s = okSize;
|
|
|
|
if (!c.Fixed) s = new Vector2(s.X, s.Y / c.Scale);
|
|
|
|
TotalHeight += s.Y;
|
|
}
|
|
|
|
CUIComponentSize size = new CUIComponentSize(c, s);
|
|
Sizes.Add(size);
|
|
|
|
if (c.FillEmptySpace.Y) Resizible.Add(size);
|
|
}
|
|
|
|
TotalHeight += Math.Max(0, Host.Children.Count - 1) * Gap;
|
|
|
|
sw.Stop();
|
|
//CUI.Log($"{Host} vlist measuring {sw.ElapsedMilliseconds}");
|
|
|
|
float dif = Math.Max(0, Host.Real.Height - TotalHeight);
|
|
|
|
Resizible.ForEach(c =>
|
|
{
|
|
c.Size = c.Component.AmIOkWithThisSize(new Vector2(c.Size.X, (float)Math.Round(dif / Resizible.Count)));
|
|
//c.Size = new Vector2(c.Size.X, dif / Resizible.Count);
|
|
|
|
CUIDebug.Capture(Host, c.Component, "VerticalList.Update", "Resizible.ForEach", "c.Size", c.Size.ToString());
|
|
});
|
|
|
|
|
|
CUI3DOffset offset = Host.ChildOffsetBounds.Check(Host.ChildrenOffset);
|
|
|
|
|
|
|
|
if (Direction == CUIDirection.Straight)
|
|
{
|
|
float y = 0;
|
|
foreach (CUIComponentSize c in Sizes)
|
|
{
|
|
CUIRect real;
|
|
|
|
if (Host.ChildrenBoundaries != null) real = Host.ChildrenBoundaries(Host.Real).Check(0, y, c.Size.X, c.Size.Y);
|
|
else real = new CUIRect(0, y, c.Size.X, c.Size.Y);
|
|
|
|
real = offset.Transform(real);
|
|
real = real.Shift(Host.Real.Position);
|
|
|
|
c.Component.SetReal(real, "VerticalList.Update");
|
|
|
|
y += c.Size.Y + Gap;
|
|
}
|
|
}
|
|
|
|
if (Direction == CUIDirection.Reverse)
|
|
{
|
|
float y = Host.Real.Height;
|
|
foreach (CUIComponentSize c in Sizes)
|
|
{
|
|
y -= c.Size.Y + Gap;
|
|
CUIRect real;
|
|
if (Host.ChildrenBoundaries != null) real = Host.ChildrenBoundaries(Host.Real).Check(0, y, c.Size.X, c.Size.Y);
|
|
else real = new CUIRect(0, y, c.Size.X, c.Size.Y);
|
|
|
|
real = offset.Transform(real);
|
|
real = real.Shift(Host.Real.Position);
|
|
|
|
c.Component.SetReal(real, "VerticalList.Update");
|
|
}
|
|
}
|
|
}
|
|
|
|
base.Update();
|
|
}
|
|
|
|
internal override void ResizeToContent()
|
|
{
|
|
if (AbsoluteChanged && Host.FitContent.X)
|
|
{
|
|
float tw = 0;
|
|
foreach (CUIComponent c in Host.Children)
|
|
{
|
|
if (c.Ghost.X) continue;
|
|
|
|
float w = 0;
|
|
if (c.Absolute.Width.HasValue) w = c.Absolute.Width.Value;
|
|
if (c.AbsoluteMin.Width.HasValue) w = Math.Max(w, c.AbsoluteMin.Width.Value);
|
|
else if (c.ForcedMinSize.X.HasValue) w = Math.Max(w, c.ForcedMinSize.X.Value);
|
|
if (c.AbsoluteMax.Width.HasValue) w = Math.Min(w, c.AbsoluteMax.Width.Value);
|
|
|
|
tw = Math.Max(tw, w);
|
|
}
|
|
|
|
CUIDebug.Capture(null, Host, "VerticalList.ResizeToContent", "tw", "ForcedMinSize.W", tw.ToString());
|
|
Host.SetForcedMinSize(Host.ForcedMinSize with { X = tw });
|
|
}
|
|
|
|
if (AbsoluteChanged && Host.FitContent.Y)
|
|
{
|
|
float th = 0;
|
|
foreach (CUIComponent c in Host.Children)
|
|
{
|
|
if (c.Ghost.Y) continue;
|
|
|
|
float h = 0;
|
|
if (!c.FillEmptySpace.Y)
|
|
{
|
|
if (c.Absolute.Height.HasValue) h = c.Absolute.Height.Value;
|
|
if (c.AbsoluteMin.Height.HasValue) h = Math.Max(h, c.AbsoluteMin.Height.Value);
|
|
else if (c.ForcedMinSize.Y.HasValue) h = Math.Max(h, c.ForcedMinSize.Y.Value);
|
|
if (c.AbsoluteMax.Height.HasValue) h = Math.Min(h, c.AbsoluteMax.Height.Value);
|
|
th += h;
|
|
}
|
|
}
|
|
|
|
CUIDebug.Capture(null, Host, "VerticalList.ResizeToContent", "th", "ForcedMinSize.Y", th.ToString());
|
|
Host.SetForcedMinSize(Host.ForcedMinSize with { Y = th });
|
|
}
|
|
|
|
base.ResizeToContent();
|
|
}
|
|
|
|
public CUILayoutVerticalList() : base() { }
|
|
|
|
public CUILayoutVerticalList(CUIDirection d, CUIComponent host = null) : base(host)
|
|
{
|
|
Direction = d;
|
|
}
|
|
}
|
|
} |