mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-11-27 06:58:34 +01:00
Compare commits
5 commits
550bf28320
...
a119db553f
Author | SHA1 | Date | |
---|---|---|---|
a119db553f | |||
7bf22fa8f3 | |||
4d7d628486 | |||
237334b1c9 | |||
f6bc206c1f |
5 changed files with 50 additions and 14 deletions
|
@ -22,6 +22,11 @@ Additions
|
||||||
Fixes
|
Fixes
|
||||||
- Fixed TextInput not working correctly when using surrogate pairs
|
- Fixed TextInput not working correctly when using surrogate pairs
|
||||||
|
|
||||||
|
### MLEM.Ui
|
||||||
|
Improvements
|
||||||
|
- Allow scrolling panels to contain other scrolling panels
|
||||||
|
- Allow dropdowns to have scrolling panels
|
||||||
|
|
||||||
## 6.2.0
|
## 6.2.0
|
||||||
|
|
||||||
### MLEM
|
### MLEM
|
||||||
|
|
|
@ -223,6 +223,15 @@ namespace Demos {
|
||||||
PositionOffset = new Vector2(0, 1)
|
PositionOffset = new Vector2(0, 1)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var subPanel = this.root.AddChild(new Panel(Anchor.AutoLeft, new Vector2(1, 25), Vector2.Zero, false, true) {
|
||||||
|
PositionOffset = new Vector2(0, 1),
|
||||||
|
Texture = null,
|
||||||
|
ChildPadding = Padding.Empty
|
||||||
|
});
|
||||||
|
subPanel.AddChild(new Paragraph(Anchor.AutoLeft, 1, "This is a nested scrolling panel!"));
|
||||||
|
for (var i = 1; i <= 5; i++)
|
||||||
|
subPanel.AddChild(new Button(Anchor.AutoLeft, new Vector2(1, 10), $"Button {i}") {PositionOffset = new Vector2(0, 1)});
|
||||||
|
|
||||||
const string alignText = "Paragraphs can have <l Left>left</l> aligned text, <l Right>right</l> aligned text and <l Center>center</l> aligned text.";
|
const string alignText = "Paragraphs can have <l Left>left</l> aligned text, <l Right>right</l> aligned text and <l Center>center</l> aligned text.";
|
||||||
this.root.AddChild(new VerticalSpace(3));
|
this.root.AddChild(new VerticalSpace(3));
|
||||||
var alignPar = this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, alignText));
|
var alignPar = this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, alignText));
|
||||||
|
|
|
@ -36,12 +36,15 @@ namespace MLEM.Ui.Elements {
|
||||||
/// <param name="size">The dropdown button's size</param>
|
/// <param name="size">The dropdown button's size</param>
|
||||||
/// <param name="text">The text displayed on the dropdown button</param>
|
/// <param name="text">The text displayed on the dropdown button</param>
|
||||||
/// <param name="tooltipText">The text displayed as a tooltip when hovering over the dropdown button</param>
|
/// <param name="tooltipText">The text displayed as a tooltip when hovering over the dropdown button</param>
|
||||||
public Dropdown(Anchor anchor, Vector2 size, string text = null, string tooltipText = null) : base(anchor, size, text, tooltipText) {
|
/// <param name="panelHeight">The height of the <see cref="Panel"/>. If this is 0, the panel will be set to <see cref="Element.SetHeightBasedOnChildren"/>.</param>
|
||||||
this.Panel = this.AddChild(new Panel(Anchor.TopCenter, Vector2.Zero, Vector2.Zero, true) {
|
/// <param name="scrollPanel">Whether this dropdown's <see cref="Panel"/> should automatically add a scroll bar to scroll towards elements that are beyond the area it covers.</param>
|
||||||
|
/// <param name="autoHidePanelScrollbar">Whether this dropdown's <see cref="Panel"/>'s scroll bar should be hidden automatically if the panel does not contain enough children to allow for scrolling. This only has an effect if <paramref name="scrollPanel"/> is <see langword="true"/>.</param>
|
||||||
|
public Dropdown(Anchor anchor, Vector2 size, string text = null, string tooltipText = null, float panelHeight = 0, bool scrollPanel = false, bool autoHidePanelScrollbar = true) : base(anchor, size, text, tooltipText) {
|
||||||
|
this.Panel = this.AddChild(new Panel(Anchor.TopCenter, Vector2.Zero, Vector2.Zero, panelHeight == 0, scrollPanel, autoHidePanelScrollbar) {
|
||||||
IsHidden = true
|
IsHidden = true
|
||||||
});
|
});
|
||||||
this.OnAreaUpdated += e => {
|
this.OnAreaUpdated += e => {
|
||||||
this.Panel.Size = new Vector2(e.Area.Width / e.Scale, 0);
|
this.Panel.Size = new Vector2(e.Area.Width / e.Scale, panelHeight);
|
||||||
this.Panel.PositionOffset = new Vector2(0, e.Area.Height / e.Scale);
|
this.Panel.PositionOffset = new Vector2(0, e.Area.Height / e.Scale);
|
||||||
};
|
};
|
||||||
this.OnOpenedOrClosed += e => this.Priority = this.IsOpen ? 10000 : 0;
|
this.OnOpenedOrClosed += e => this.Priority = this.IsOpen ? 10000 : 0;
|
||||||
|
|
|
@ -61,6 +61,7 @@ namespace MLEM.Ui.Elements {
|
||||||
private bool relevantChildrenDirty;
|
private bool relevantChildrenDirty;
|
||||||
private float scrollBarChildOffset;
|
private float scrollBarChildOffset;
|
||||||
private StyleProp<float> scrollBarOffset;
|
private StyleProp<float> scrollBarOffset;
|
||||||
|
private float lastScrollOffset;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new panel with the given settings.
|
/// Creates a new panel with the given settings.
|
||||||
|
@ -70,7 +71,7 @@ namespace MLEM.Ui.Elements {
|
||||||
/// <param name="positionOffset">The panel's offset from its anchor point</param>
|
/// <param name="positionOffset">The panel's offset from its anchor point</param>
|
||||||
/// <param name="setHeightBasedOnChildren">Whether the panel should automatically calculate its height based on its children's size</param>
|
/// <param name="setHeightBasedOnChildren">Whether the panel should automatically calculate its height based on its children's size</param>
|
||||||
/// <param name="scrollOverflow">Whether this panel should automatically add a scroll bar to scroll towards elements that are beyond the area this panel covers</param>
|
/// <param name="scrollOverflow">Whether this panel should automatically add a scroll bar to scroll towards elements that are beyond the area this panel covers</param>
|
||||||
/// <param name="autoHideScrollbar">Whether the scroll bar should be hidden automatically if the panel does not contain enough children to allow for scrolling</param>
|
/// <param name="autoHideScrollbar">Whether the scroll bar should be hidden automatically if the panel does not contain enough children to allow for scrolling. This only has an effect if <paramref name="scrollOverflow"/> is <see langword="true"/>.</param>
|
||||||
public Panel(Anchor anchor, Vector2 size, Vector2 positionOffset, bool setHeightBasedOnChildren = false, bool scrollOverflow = false, bool autoHideScrollbar = true) : base(anchor, size) {
|
public Panel(Anchor anchor, Vector2 size, Vector2 positionOffset, bool setHeightBasedOnChildren = false, bool scrollOverflow = false, bool autoHideScrollbar = true) : base(anchor, size) {
|
||||||
this.PositionOffset = positionOffset;
|
this.PositionOffset = positionOffset;
|
||||||
this.SetHeightBasedOnChildren = setHeightBasedOnChildren;
|
this.SetHeightBasedOnChildren = setHeightBasedOnChildren;
|
||||||
|
@ -277,10 +278,10 @@ namespace MLEM.Ui.Elements {
|
||||||
|
|
||||||
// update child padding based on whether the scroll bar is visible
|
// update child padding based on whether the scroll bar is visible
|
||||||
var childOffset = this.ScrollBar.IsHidden ? 0 : this.ScrollerSize.Value.X + this.ScrollBarOffset;
|
var childOffset = this.ScrollBar.IsHidden ? 0 : this.ScrollerSize.Value.X + this.ScrollBarOffset;
|
||||||
if (!this.scrollBarChildOffset.Equals(childOffset, Element.Epsilon)) {
|
var childOffsetDelta = childOffset - this.scrollBarChildOffset;
|
||||||
this.ChildPadding += new Padding(0, -this.scrollBarChildOffset + childOffset, 0, 0);
|
if (!childOffsetDelta.Equals(0, Element.Epsilon)) {
|
||||||
this.scrollBarChildOffset = childOffset;
|
this.scrollBarChildOffset = childOffset;
|
||||||
this.SetAreaDirty();
|
this.ChildPadding += new Padding(0, childOffsetDelta, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// the scroller height has the same relation to the scroll bar height as the visible area has to the total height of the panel's content
|
// the scroller height has the same relation to the scroll bar height as the visible area has to the total height of the panel's content
|
||||||
|
@ -288,15 +289,15 @@ namespace MLEM.Ui.Elements {
|
||||||
this.ScrollBar.ScrollerSize = new Vector2(this.ScrollerSize.Value.X, Math.Max(this.ScrollerSize.Value.Y, scrollerHeight));
|
this.ScrollBar.ScrollerSize = new Vector2(this.ScrollerSize.Value.X, Math.Max(this.ScrollerSize.Value.Y, scrollerHeight));
|
||||||
|
|
||||||
// update the render target
|
// update the render target
|
||||||
var targetArea = (Rectangle) this.GetRenderTargetArea();
|
var area = (Rectangle) this.GetRenderTargetArea();
|
||||||
if (targetArea.Width <= 0 || targetArea.Height <= 0) {
|
if (area.Width <= 0 || area.Height <= 0) {
|
||||||
this.renderTarget?.Dispose();
|
this.renderTarget?.Dispose();
|
||||||
this.renderTarget = null;
|
this.renderTarget = null;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (this.renderTarget == null || targetArea.Width != this.renderTarget.Width || targetArea.Height != this.renderTarget.Height) {
|
if (this.renderTarget == null || area.Width != this.renderTarget.Width || area.Height != this.renderTarget.Height) {
|
||||||
this.renderTarget?.Dispose();
|
this.renderTarget?.Dispose();
|
||||||
this.renderTarget = targetArea.IsEmpty ? null : new RenderTarget2D(this.System.Game.GraphicsDevice, targetArea.Width, targetArea.Height, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents);
|
this.renderTarget = new RenderTarget2D(this.System.Game.GraphicsDevice, area.Width, area.Height, false, SurfaceFormat.Color, DepthFormat.None, 0, RenderTargetUsage.PreserveContents);
|
||||||
this.relevantChildrenDirty = true;
|
this.relevantChildrenDirty = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -328,7 +329,7 @@ namespace MLEM.Ui.Elements {
|
||||||
}
|
}
|
||||||
|
|
||||||
private RectangleF GetRenderTargetArea() {
|
private RectangleF GetRenderTargetArea() {
|
||||||
var area = this.ChildPaddedArea;
|
var area = this.ChildPaddedArea.OffsetCopy(this.ScaledScrollOffset);
|
||||||
area.X = this.DisplayArea.X;
|
area.X = this.DisplayArea.X;
|
||||||
area.Width = this.DisplayArea.Width;
|
area.Width = this.DisplayArea.Width;
|
||||||
return area;
|
return area;
|
||||||
|
@ -339,7 +340,8 @@ namespace MLEM.Ui.Elements {
|
||||||
return;
|
return;
|
||||||
// we ignore false grandchildren so that the children of the scroll bar stay in place
|
// 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))
|
foreach (var child in this.GetChildren(c => c != this.ScrollBar, true, true))
|
||||||
child.ScrollOffset.Y = -this.ScrollBar.CurrentValue;
|
child.ScrollOffset.Y += (this.lastScrollOffset - this.ScrollBar.CurrentValue);
|
||||||
|
this.lastScrollOffset = this.ScrollBar.CurrentValue;
|
||||||
this.relevantChildrenDirty = true;
|
this.relevantChildrenDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -158,7 +158,7 @@ namespace MLEM.Ui.Elements {
|
||||||
if (this.isMouseScrolling)
|
if (this.isMouseScrolling)
|
||||||
this.ScrollToPos(this.TransformInverseAll(this.Input.ViewportMousePosition.ToVector2()));
|
this.ScrollToPos(this.TransformInverseAll(this.Input.ViewportMousePosition.ToVector2()));
|
||||||
if (!this.Horizontal) {
|
if (!this.Horizontal) {
|
||||||
if (moused != null && (moused == this.Parent || moused.GetParentTree().Contains(this.Parent))) {
|
if (this.IsMousedForScrolling(moused)) {
|
||||||
var scroll = this.Input.LastScrollWheel - this.Input.ScrollWheel;
|
var scroll = this.Input.LastScrollWheel - this.Input.ScrollWheel;
|
||||||
if (scroll != 0)
|
if (scroll != 0)
|
||||||
this.CurrentValue += this.StepPerScroll * Math.Sign(scroll);
|
this.CurrentValue += this.StepPerScroll * Math.Sign(scroll);
|
||||||
|
@ -244,6 +244,23 @@ namespace MLEM.Ui.Elements {
|
||||||
this.SmoothScrollFactor = this.SmoothScrollFactor.OrStyle(style.ScrollBarSmoothScrollFactor);
|
this.SmoothScrollFactor = this.SmoothScrollFactor.OrStyle(style.ScrollBarSmoothScrollFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private bool IsMousedForScrolling(Element moused) {
|
||||||
|
if (moused == null || (moused != this.Parent && !moused.GetParentTree().Contains(this.Parent)))
|
||||||
|
return false;
|
||||||
|
// if we're moused, check if there are any scroll bars deeper than us that should take precedence
|
||||||
|
var foundMe = false;
|
||||||
|
foreach (var child in this.Parent.GetChildren(regardGrandchildren: true)) {
|
||||||
|
if (foundMe) {
|
||||||
|
if (child is ScrollBar b && !b.Horizontal && b.IsMousedForScrolling(moused))
|
||||||
|
return false;
|
||||||
|
} else if (child == this) {
|
||||||
|
// once we found ourselves, all subsequent children are deeper/older!
|
||||||
|
foundMe = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A delegate method used for <see cref="ScrollBar.OnValueChanged"/>
|
/// A delegate method used for <see cref="ScrollBar.OnValueChanged"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
Loading…
Reference in a new issue