mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-22 12:58:33 +01:00
fixed stack overflow with nested auto-sized children
This commit is contained in:
parent
3e20aaf6c5
commit
79ba6864e7
2 changed files with 52 additions and 22 deletions
|
@ -1,6 +1,7 @@
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.ObjectModel;
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.Xna.Framework;
|
using Microsoft.Xna.Framework;
|
||||||
using Microsoft.Xna.Framework.Graphics;
|
using Microsoft.Xna.Framework.Graphics;
|
||||||
|
@ -524,27 +525,10 @@ namespace MLEM.Ui.Elements {
|
||||||
var parentArea = this.Parent != null ? this.Parent.ChildPaddedArea : (RectangleF) this.system.Viewport;
|
var parentArea = this.Parent != null ? this.Parent.ChildPaddedArea : (RectangleF) this.system.Viewport;
|
||||||
var parentCenterX = parentArea.X + parentArea.Width / 2;
|
var parentCenterX = parentArea.X + parentArea.Width / 2;
|
||||||
var parentCenterY = parentArea.Y + parentArea.Height / 2;
|
var parentCenterY = parentArea.Y + parentArea.Height / 2;
|
||||||
|
|
||||||
var actualSize = this.CalcActualSize(parentArea);
|
var actualSize = this.CalcActualSize(parentArea);
|
||||||
UpdateDisplayArea(actualSize);
|
|
||||||
|
|
||||||
if (this.Children.Count > 0) {
|
var recursion = 0;
|
||||||
var autoSize = this.DisplayArea.Size;
|
UpdateDisplayArea(actualSize);
|
||||||
if (this.SetHeightBasedOnChildren) {
|
|
||||||
var lowest = this.GetLowestChild(e => !e.IsHidden);
|
|
||||||
if (lowest != null)
|
|
||||||
autoSize.Y = lowest.UnscrolledArea.Bottom - this.DisplayArea.Y + this.ScaledChildPadding.Bottom;
|
|
||||||
}
|
|
||||||
if (this.SetWidthBasedOnChildren) {
|
|
||||||
var rightmost = this.GetRightmostChild(e => !e.IsHidden);
|
|
||||||
if (rightmost != null)
|
|
||||||
autoSize.X = rightmost.UnscrolledArea.Right - this.DisplayArea.X + this.ScaledChildPadding.Right;
|
|
||||||
}
|
|
||||||
if (this.TreatSizeAsMinimum)
|
|
||||||
autoSize = Vector2.Max(autoSize, actualSize);
|
|
||||||
if (autoSize != this.DisplayArea.Size)
|
|
||||||
UpdateDisplayArea(autoSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
void UpdateDisplayArea(Vector2 newSize) {
|
void UpdateDisplayArea(Vector2 newSize) {
|
||||||
var pos = new Vector2();
|
var pos = new Vector2();
|
||||||
|
@ -639,9 +623,38 @@ namespace MLEM.Ui.Elements {
|
||||||
this.System.OnElementAreaUpdated?.Invoke(this);
|
this.System.OnElementAreaUpdated?.Invoke(this);
|
||||||
|
|
||||||
foreach (var child in this.Children)
|
foreach (var child in this.Children)
|
||||||
child.SetAreaDirty();
|
child.ForceUpdateArea();
|
||||||
// clear the dirty flag again in case our children just set us dirty
|
|
||||||
this.areaDirty = false;
|
if (this.Children.Count > 0) {
|
||||||
|
Element foundChild = null;
|
||||||
|
var autoSize = this.Area.Size;
|
||||||
|
if (this.SetHeightBasedOnChildren) {
|
||||||
|
var lowest = this.GetLowestChild(e => !e.IsHidden);
|
||||||
|
var newY = lowest?.UnscrolledArea.Bottom - pos.Y + this.ScaledChildPadding.Bottom;
|
||||||
|
if (newY != null && autoSize.Y != newY) {
|
||||||
|
autoSize.Y = newY.Value;
|
||||||
|
foundChild = lowest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.SetWidthBasedOnChildren) {
|
||||||
|
var rightmost = this.GetRightmostChild(e => !e.IsHidden);
|
||||||
|
var newX = rightmost?.UnscrolledArea.Right - pos.X + this.ScaledChildPadding.Right;
|
||||||
|
if (newX != null && autoSize.X != newX) {
|
||||||
|
autoSize.X = newX.Value;
|
||||||
|
foundChild = rightmost;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (this.TreatSizeAsMinimum)
|
||||||
|
autoSize = Vector2.Max(autoSize, actualSize);
|
||||||
|
if (autoSize != this.Area.Size) {
|
||||||
|
recursion++;
|
||||||
|
if (recursion >= 16) {
|
||||||
|
throw new ArithmeticException($"The area of {this} with root {this.Root?.Name} has recursively updated too often. Does its child {foundChild} contain any conflicting auto-sizing settings?");
|
||||||
|
} else {
|
||||||
|
UpdateDisplayArea(autoSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ using MLEM.Ui;
|
||||||
using MLEM.Ui.Elements;
|
using MLEM.Ui.Elements;
|
||||||
using MLEM.Ui.Style;
|
using MLEM.Ui.Style;
|
||||||
using MonoGame.Extended.Tiled;
|
using MonoGame.Extended.Tiled;
|
||||||
|
using Group = MLEM.Ui.Elements.Group;
|
||||||
|
|
||||||
namespace Sandbox {
|
namespace Sandbox {
|
||||||
public class GameImpl : MlemGame {
|
public class GameImpl : MlemGame {
|
||||||
|
@ -205,6 +206,22 @@ namespace Sandbox {
|
||||||
invalidPanel.AddChild(new Paragraph(Anchor.AutoRight, 1, "This is some test text!", true));
|
invalidPanel.AddChild(new Paragraph(Anchor.AutoRight, 1, "This is some test text!", true));
|
||||||
invalidPanel.AddChild(new VerticalSpace(1));
|
invalidPanel.AddChild(new VerticalSpace(1));
|
||||||
this.UiSystem.Add("Invalid", invalidPanel);*/
|
this.UiSystem.Add("Invalid", invalidPanel);*/
|
||||||
|
|
||||||
|
var loadGroup = new Group(Anchor.TopLeft, Vector2.One, false);
|
||||||
|
var loadPanel = loadGroup.AddChild(new Panel(Anchor.Center, new Vector2(150, 150), Vector2.Zero, false, true, new Point(5, 10), false) {
|
||||||
|
ChildPadding = new Padding(5, 10, 5, 5)
|
||||||
|
});
|
||||||
|
for (var i = 0; i < 1; i++) {
|
||||||
|
var button = loadPanel.AddChild(new Button(Anchor.AutoLeft, new Vector2(1)) {
|
||||||
|
SetHeightBasedOnChildren = true,
|
||||||
|
Padding = new Padding(0, 0, 0, 1),
|
||||||
|
ChildPadding = new Vector2(3)
|
||||||
|
});
|
||||||
|
button.AddChild(new Group(Anchor.AutoLeft, new Vector2(0.5F, 30), false) {
|
||||||
|
CanBeMoused = false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.UiSystem.Add("Load", loadGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void DoUpdate(GameTime gameTime) {
|
protected override void DoUpdate(GameTime gameTime) {
|
||||||
|
|
Loading…
Reference in a new issue