1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-11-25 22:18:34 +01:00

Added Panel.ScrollToElement

This commit is contained in:
Ell 2022-09-24 18:46:33 +02:00
parent d6a51776e5
commit 92f9164256
2 changed files with 64 additions and 46 deletions

View file

@ -32,6 +32,7 @@ Additions
- Added Element.AutoSizeAddedAbsolute to allow for more granular control of auto-sizing
- Added Element.OnAddedToUi and Element.OnRemovedFromUi
- Added ScrollBar.MouseDragScrolling
- Added Panel.ScrollToElement
Improvements
- Allow elements to auto-adjust their size even when their children are aligned oddly

View file

@ -84,9 +84,7 @@ namespace MLEM.Ui.Elements {
return;
if (e == null || !e.GetParentTree().Contains(this))
return;
var firstChild = this.Children.FirstOrDefault(c => c != this.ScrollBar);
if (firstChild != null)
this.ScrollBar.CurrentValue = (e.Area.Center.Y - this.Area.Height / 2 - firstChild.Area.Top) / e.Scale + this.ChildPadding.Value.Height / 2;
this.ScrollToElement(e);
};
this.AddChild(this.ScrollBar);
}
@ -116,15 +114,6 @@ namespace MLEM.Ui.Elements {
this.ScrollSetup();
}
private void ScrollChildren() {
if (!this.scrollOverflow)
return;
// we ignore false grandchildren so that the children of the scroll bar stay in place
foreach (var child in this.GetChildren(c => c != this.ScrollBar, true, true))
child.ScrollOffset.Y = -this.ScrollBar.CurrentValue;
this.relevantChildrenDirty = true;
}
/// <inheritdoc />
public override void ForceUpdateSortedChildren() {
base.ForceUpdateSortedChildren();
@ -144,26 +133,6 @@ namespace MLEM.Ui.Elements {
base.RemoveChildren(e => e != this.ScrollBar && (condition == null || condition(e)));
}
/// <inheritdoc />
protected override IList<Element> GetRelevantChildren() {
var relevant = base.GetRelevantChildren();
if (this.scrollOverflow) {
if (this.relevantChildrenDirty)
this.ForceUpdateRelevantChildren();
relevant = this.relevantChildren;
}
return relevant;
}
/// <inheritdoc />
protected override void OnChildAreaDirty(Element child, bool grandchild) {
base.OnChildAreaDirty(child, grandchild);
// we only need to scroll when a grandchild changes, since all of our children are forced
// to be auto-anchored and so will automatically propagate their changes up to us
if (grandchild)
this.ScrollChildren();
}
/// <inheritdoc />
public override void Draw(GameTime time, SpriteBatch batch, float alpha, SpriteBatchContext context) {
// draw children onto the render target if we have one
@ -208,11 +177,32 @@ namespace MLEM.Ui.Elements {
return base.GetElementUnderPos(position);
}
private RectangleF GetRenderTargetArea() {
var area = this.ChildPaddedArea;
area.X = this.DisplayArea.X;
area.Width = this.DisplayArea.Width;
return area;
/// <inheritdoc />
public override void Dispose() {
if (this.renderTarget != null) {
this.renderTarget.Dispose();
this.renderTarget = null;
}
base.Dispose();
}
/// <summary>
/// Scrolls this panel's <see cref="ScrollBar"/> to the given <see cref="Element"/> in such a way that its center is positioned in the center of this panel.
/// </summary>
/// <param name="element">The element to scroll to.</param>
public void ScrollToElement(Element element) {
this.ScrollToElement(element.Area.Center.Y);
}
/// <summary>
/// Scrolls this panel's <see cref="ScrollBar"/> to the given <paramref name="elementY"/> coordinate in such a way that the coordinate is positioned in the center of this panel.
/// </summary>
/// <param name="elementY">The y coordinate to scroll to, which should have this element's <see cref="Element.Scale"/> applied.</param>
public void ScrollToElement(float elementY) {
var firstChild = this.Children.FirstOrDefault(c => c != this.ScrollBar);
if (firstChild == null)
return;
this.ScrollBar.CurrentValue = (elementY - this.Area.Height / 2 - firstChild.Area.Top) / this.Scale + this.ChildPadding.Value.Height / 2;
}
/// <inheritdoc />
@ -226,6 +216,26 @@ namespace MLEM.Ui.Elements {
this.SetScrollBarStyle();
}
/// <inheritdoc />
protected override IList<Element> GetRelevantChildren() {
var relevant = base.GetRelevantChildren();
if (this.scrollOverflow) {
if (this.relevantChildrenDirty)
this.ForceUpdateRelevantChildren();
relevant = this.relevantChildren;
}
return relevant;
}
/// <inheritdoc />
protected override void OnChildAreaDirty(Element child, bool grandchild) {
base.OnChildAreaDirty(child, grandchild);
// we only need to scroll when a grandchild changes, since all of our children are forced
// to be auto-anchored and so will automatically propagate their changes up to us
if (grandchild)
this.ScrollChildren();
}
/// <summary>
/// Prepares the panel for auto-scrolling, creating the render target and setting up the scroll bar's maximum value.
/// </summary>
@ -274,15 +284,6 @@ namespace MLEM.Ui.Elements {
}
}
/// <inheritdoc />
public override void Dispose() {
if (this.renderTarget != null) {
this.renderTarget.Dispose();
this.renderTarget = null;
}
base.Dispose();
}
private void SetScrollBarStyle() {
if (this.ScrollBar == null)
return;
@ -309,5 +310,21 @@ namespace MLEM.Ui.Elements {
}
}
private RectangleF GetRenderTargetArea() {
var area = this.ChildPaddedArea;
area.X = this.DisplayArea.X;
area.Width = this.DisplayArea.Width;
return area;
}
private void ScrollChildren() {
if (!this.scrollOverflow)
return;
// we ignore false grandchildren so that the children of the scroll bar stay in place
foreach (var child in this.GetChildren(c => c != this.ScrollBar, true, true))
child.ScrollOffset.Y = -this.ScrollBar.CurrentValue;
this.relevantChildrenDirty = true;
}
}
}