mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-09-06 17:58:05 +02:00
RobustToolbox projects should be named Robust.* This PR changes the RobustToolbox projects from SS14.* to Robust.* Updates SS14.* prefixes/namespaces to Robust.* Updates SpaceStation14.sln to RobustToolbox.sln Updates MSBUILD/SS14.* to MSBUILD/Robust.* Updates CSProject and MSBuild references for the above Updates git_helper.py Removes Runserver and Runclient as they are unusable
263 lines
7.5 KiB
C#
263 lines
7.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using Robust.Shared.Maths;
|
|
|
|
namespace Robust.Client.UserInterface.Controls
|
|
{
|
|
[ControlWrap(typeof(BoxContainer))]
|
|
public abstract class BoxContainer : Container
|
|
{
|
|
public const string StylePropertySeparation = "separation";
|
|
|
|
private const int DefaultSeparation = 1;
|
|
private protected abstract bool Vertical { get; }
|
|
|
|
protected BoxContainer()
|
|
{
|
|
}
|
|
|
|
protected BoxContainer(string name) : base(name)
|
|
{
|
|
}
|
|
|
|
internal BoxContainer(Godot.BoxContainer sceneControl) : base(sceneControl)
|
|
{
|
|
}
|
|
|
|
private AlignMode _align;
|
|
|
|
public AlignMode Align
|
|
{
|
|
get => GameController.OnGodot ? (AlignMode) SceneControl.Get("align_mode") : _align;
|
|
set
|
|
{
|
|
if (GameController.OnGodot)
|
|
{
|
|
SceneControl.Set("align_mode", (int) value);
|
|
}
|
|
else
|
|
{
|
|
_align = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
private int ActualSeparation
|
|
{
|
|
get
|
|
{
|
|
if (TryGetStyleProperty(StylePropertySeparation, out int separation))
|
|
{
|
|
return separation;
|
|
}
|
|
|
|
return _separationOverride ?? 1;
|
|
}
|
|
}
|
|
|
|
private int? _separationOverride;
|
|
|
|
public int? SeparationOverride
|
|
{
|
|
get => _separationOverride ?? GetConstantOverride("separation");
|
|
set => SetConstantOverride("separation", _separationOverride = value);
|
|
}
|
|
|
|
protected override void SortChildren()
|
|
{
|
|
var separation = ActualSeparation;
|
|
|
|
// Step one: figure out the sizes of all our children and whether they want to stretch.
|
|
var sizeList = new List<(Control control, int minSize, int finalSize, bool stretch)>();
|
|
var totalStretchRatio = 0f;
|
|
// Amount of space not available for stretching.
|
|
var stretchMin = 0;
|
|
|
|
foreach (var child in Children)
|
|
{
|
|
if (!child.Visible)
|
|
{
|
|
continue;
|
|
}
|
|
var childMinSize = child.CombinedMinimumSize;
|
|
int minSize;
|
|
bool stretch;
|
|
|
|
if (Vertical)
|
|
{
|
|
minSize = (int) childMinSize.Y;
|
|
stretch = (child.SizeFlagsVertical & SizeFlags.Expand) == SizeFlags.Expand;
|
|
}
|
|
else
|
|
{
|
|
minSize = (int) childMinSize.X;
|
|
stretch = (child.SizeFlagsHorizontal & SizeFlags.Expand) == SizeFlags.Expand;
|
|
}
|
|
|
|
if (!stretch)
|
|
{
|
|
stretchMin += minSize;
|
|
}
|
|
else
|
|
{
|
|
totalStretchRatio += child.SizeFlagsStretchRatio;
|
|
}
|
|
|
|
sizeList.Add((child, minSize, minSize, stretch));
|
|
}
|
|
|
|
int stretchMax;
|
|
if (Vertical)
|
|
{
|
|
stretchMax = (int) Size.Y;
|
|
}
|
|
else
|
|
{
|
|
stretchMax = (int) Size.X;
|
|
}
|
|
|
|
stretchMax -= separation * (ChildCount - 1);
|
|
// This is the amount of space allocated for stretchable children.
|
|
var stretchAvail = Math.Max(0, stretchMax - stretchMin);
|
|
|
|
// Step two: figure out which that want to stretch need to suck it,
|
|
// because due to their stretch ratio they would be smaller than minSize.
|
|
// Treat those as non-stretching.
|
|
for (var i = 0; i < sizeList.Count; i++)
|
|
{
|
|
var (control, minSize, _, stretch) = sizeList[i];
|
|
if (!stretch)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
var share = (int) (stretchAvail * (control.SizeFlagsStretchRatio / totalStretchRatio));
|
|
if (share < minSize)
|
|
{
|
|
sizeList[i] = (control, minSize, minSize, false);
|
|
stretchAvail -= minSize;
|
|
totalStretchRatio -= control.SizeFlagsStretchRatio;
|
|
}
|
|
}
|
|
|
|
// Step three: allocate space for all the stretchable children.
|
|
var stretchingAtAll = false;
|
|
for (var i = 0; i < sizeList.Count; i++)
|
|
{
|
|
var (control, minSize, _, stretch) = sizeList[i];
|
|
if (!stretch)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
stretchingAtAll = true;
|
|
|
|
var share = (int) (stretchAvail * (control.SizeFlagsStretchRatio / totalStretchRatio));
|
|
sizeList[i] = (control, minSize, share, false);
|
|
}
|
|
|
|
// Step four: actually lay them out one by one.
|
|
var offset = 0;
|
|
if (!stretchingAtAll)
|
|
{
|
|
switch (_align)
|
|
{
|
|
case AlignMode.Begin:
|
|
break;
|
|
case AlignMode.Center:
|
|
offset = stretchAvail / 2;
|
|
break;
|
|
case AlignMode.End:
|
|
offset = stretchAvail;
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
|
|
var first = true;
|
|
foreach (var (control, _, size, _) in sizeList)
|
|
{
|
|
if (!first)
|
|
{
|
|
offset += separation;
|
|
}
|
|
|
|
first = false;
|
|
|
|
UIBox2 targetBox;
|
|
if (Vertical)
|
|
{
|
|
targetBox = new UIBox2(0, offset, Size.X, offset+size);
|
|
}
|
|
else
|
|
{
|
|
targetBox = new UIBox2(offset, 0, offset+size, Size.Y);
|
|
}
|
|
|
|
FitChildInBox(control, targetBox);
|
|
|
|
offset += size;
|
|
}
|
|
}
|
|
|
|
protected override Vector2 CalculateMinimumSize()
|
|
{
|
|
if (GameController.OnGodot)
|
|
{
|
|
return base.CalculateMinimumSize();
|
|
}
|
|
var separation = ActualSeparation;
|
|
|
|
var minWidth = 0f;
|
|
var minHeight = 0f;
|
|
var first = true;
|
|
|
|
foreach (var child in Children)
|
|
{
|
|
var (childWidth, childHeight) = child.CombinedMinimumSize;
|
|
if (Vertical)
|
|
{
|
|
minHeight += childHeight;
|
|
if (!first)
|
|
{
|
|
minHeight += separation;
|
|
}
|
|
|
|
first = false;
|
|
|
|
minWidth = Math.Max(minWidth, childWidth);
|
|
}
|
|
else
|
|
{
|
|
minWidth += childWidth;
|
|
if (!first)
|
|
{
|
|
minWidth += separation;
|
|
}
|
|
|
|
first = false;
|
|
|
|
minHeight = Math.Max(minHeight, childHeight);
|
|
}
|
|
}
|
|
|
|
return new Vector2(minWidth, minHeight);
|
|
}
|
|
|
|
protected override void SetDefaults()
|
|
{
|
|
base.SetDefaults();
|
|
|
|
MouseFilter = MouseFilterMode.Pass;
|
|
}
|
|
|
|
public enum AlignMode
|
|
{
|
|
Begin = 0,
|
|
Center = 1,
|
|
End = 2,
|
|
}
|
|
}
|
|
}
|