mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-22 12:58:33 +01:00
fixed a rare stack overflow where scroll bars could get stuck in an auto-hide loop
This commit is contained in:
parent
b1ff703fe1
commit
82b8c0ab49
3 changed files with 19 additions and 13 deletions
|
@ -626,26 +626,30 @@ namespace MLEM.Ui.Elements {
|
||||||
|
|
||||||
if (this.Children.Count > 0) {
|
if (this.Children.Count > 0) {
|
||||||
Element foundChild = null;
|
Element foundChild = null;
|
||||||
var autoSize = this.Area.Size;
|
var autoSize = this.UnscrolledArea.Size;
|
||||||
if (this.SetHeightBasedOnChildren) {
|
if (this.SetHeightBasedOnChildren) {
|
||||||
var lowest = this.GetLowestChild(e => !e.IsHidden);
|
var lowest = this.GetLowestChild(e => !e.IsHidden);
|
||||||
var newY = lowest?.UnscrolledArea.Bottom - pos.Y + this.ScaledChildPadding.Bottom;
|
if (lowest != null) {
|
||||||
if (newY != null && autoSize.Y != newY) {
|
var newHeight = lowest.UnscrolledArea.Bottom - pos.Y + this.ScaledChildPadding.Bottom;
|
||||||
autoSize.Y = newY.Value;
|
if (!newHeight.Equals(autoSize.Y, 0.01F)) {
|
||||||
|
autoSize.Y = newHeight;
|
||||||
foundChild = lowest;
|
foundChild = lowest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (this.SetWidthBasedOnChildren) {
|
if (this.SetWidthBasedOnChildren) {
|
||||||
var rightmost = this.GetRightmostChild(e => !e.IsHidden);
|
var rightmost = this.GetRightmostChild(e => !e.IsHidden);
|
||||||
var newX = rightmost?.UnscrolledArea.Right - pos.X + this.ScaledChildPadding.Right;
|
if (rightmost != null) {
|
||||||
if (newX != null && autoSize.X != newX) {
|
var newWidth = rightmost.UnscrolledArea.Right - pos.X + this.ScaledChildPadding.Right;
|
||||||
autoSize.X = newX.Value;
|
if (!newWidth.Equals(autoSize.X, 0.01F)) {
|
||||||
|
autoSize.X = newWidth;
|
||||||
foundChild = rightmost;
|
foundChild = rightmost;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (this.TreatSizeAsMinimum)
|
if (this.TreatSizeAsMinimum)
|
||||||
autoSize = Vector2.Max(autoSize, actualSize);
|
autoSize = Vector2.Max(autoSize, actualSize);
|
||||||
if (!this.Area.Size.Equals(autoSize, 0.01F)) {
|
if (foundChild != null) {
|
||||||
recursion++;
|
recursion++;
|
||||||
if (recursion >= 16) {
|
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?");
|
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?");
|
||||||
|
|
|
@ -218,7 +218,7 @@ namespace MLEM.Ui.Elements {
|
||||||
return;
|
return;
|
||||||
// the "real" first child is the scroll bar, which we want to ignore
|
// the "real" first child is the scroll bar, which we want to ignore
|
||||||
var firstChild = this.Children.First(c => c != this.ScrollBar);
|
var firstChild = this.Children.First(c => c != this.ScrollBar);
|
||||||
var lowestChild = this.GetLowestChild(e => !e.IsHidden);
|
var lowestChild = this.GetLowestChild(c => c != this.ScrollBar && !c.IsHidden);
|
||||||
// the max value of the scrollbar is the amount of non-scaled pixels taken up by overflowing components
|
// the max value of the scrollbar is the amount of non-scaled pixels taken up by overflowing components
|
||||||
var childrenHeight = lowestChild.Area.Bottom - firstChild.Area.Top;
|
var childrenHeight = lowestChild.Area.Bottom - firstChild.Area.Top;
|
||||||
this.ScrollBar.MaxValue = (childrenHeight - this.Area.Height) / this.Scale + this.ChildPadding.Height;
|
this.ScrollBar.MaxValue = (childrenHeight - this.Area.Height) / this.Scale + this.ChildPadding.Height;
|
||||||
|
|
|
@ -44,8 +44,10 @@ namespace MLEM.Ui.Elements {
|
||||||
this.maxValue = Math.Max(0, value);
|
this.maxValue = Math.Max(0, value);
|
||||||
// force current value to be clamped
|
// force current value to be clamped
|
||||||
this.CurrentValue = this.CurrentValue;
|
this.CurrentValue = this.CurrentValue;
|
||||||
if (this.AutoHideWhenEmpty && this.IsHidden != this.maxValue <= 0) {
|
// auto-hide if necessary
|
||||||
this.IsHidden = this.maxValue <= 0;
|
var shouldHide = this.maxValue <= 0.01F;
|
||||||
|
if (this.AutoHideWhenEmpty && this.IsHidden != shouldHide) {
|
||||||
|
this.IsHidden = shouldHide;
|
||||||
this.OnAutoHide?.Invoke(this);
|
this.OnAutoHide?.Invoke(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue