mirror of
https://github.com/Ellpeck/MLEM.git
synced 2024-12-24 01:09:23 +01:00
added a dropdown menu and also fixed some issues
This commit is contained in:
parent
0ad17fc40c
commit
8afe9962fb
6 changed files with 80 additions and 29 deletions
|
@ -185,6 +185,13 @@ namespace Demos {
|
|||
var bar4 = root.AddChild(new ProgressBar(Anchor.AutoInline, new Vector2(8, 30), Direction2.Up, 10) {PositionOffset = new Vector2(1, 1)});
|
||||
CoroutineHandler.Start(this.WobbleProgressBar(bar4));
|
||||
|
||||
root.AddChild(new VerticalSpace(3));
|
||||
var dropdown = root.AddChild(new Dropdown(Anchor.AutoLeft, new Vector2(1, 10), "Dropdown Menu"));
|
||||
dropdown.AddElement("First Option");
|
||||
dropdown.AddElement("Second Option");
|
||||
dropdown.AddElement("Third Option");
|
||||
dropdown.AddElement(new Button(Anchor.AutoLeft, new Vector2(1, 10), "Button Option"));
|
||||
|
||||
root.AddChild(new VerticalSpace(3));
|
||||
root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "There are also some additional \"components\" which are created as combinations of other components. You can find all of them in the ElementHelper class. Here are some examples:"));
|
||||
root.AddChild(ElementHelper.NumberField(Anchor.AutoLeft, new Vector2(1, 10))).PositionOffset = new Vector2(0, 1);
|
||||
|
@ -205,14 +212,14 @@ namespace Demos {
|
|||
// Below are some querying examples that help you find certain elements easily
|
||||
|
||||
var children = root.GetChildren();
|
||||
var totalChildren = root.GetChildren(regardChildrensChildren: true);
|
||||
var totalChildren = root.GetChildren(regardGrandchildren: true);
|
||||
Console.WriteLine($"The root has {children.Count()} children, but there are {totalChildren.Count()} when regarding children's children");
|
||||
|
||||
var textFields = root.GetChildren<TextField>();
|
||||
Console.WriteLine($"The root has {textFields.Count()} text fields");
|
||||
|
||||
var paragraphs = root.GetChildren<Paragraph>();
|
||||
var totalParagraphs = root.GetChildren<Paragraph>(regardChildrensChildren: true);
|
||||
var totalParagraphs = root.GetChildren<Paragraph>(regardGrandchildren: true);
|
||||
Console.WriteLine($"The root has {paragraphs.Count()} paragraphs, but there are {totalParagraphs.Count()} when regarding children's children");
|
||||
|
||||
var autoWidthChildren = root.GetChildren(e => e.Size.X == 1);
|
||||
|
|
43
MLEM.Ui/Elements/Dropdown.cs
Normal file
43
MLEM.Ui/Elements/Dropdown.cs
Normal file
|
@ -0,0 +1,43 @@
|
|||
using Microsoft.Xna.Framework;
|
||||
|
||||
namespace MLEM.Ui.Elements {
|
||||
public class Dropdown : Button {
|
||||
|
||||
public readonly Panel Panel;
|
||||
public bool IsOpen {
|
||||
get => !this.Panel.IsHidden;
|
||||
set => this.Panel.IsHidden = !value;
|
||||
}
|
||||
|
||||
public Dropdown(Anchor anchor, Vector2 size, string text = null, string tooltipText = null, float tooltipWidth = 50) : base(anchor, size, text, tooltipText, tooltipWidth) {
|
||||
this.Panel = this.AddChild(new Panel(Anchor.TopCenter, size, Vector2.Zero, true) {
|
||||
IsHidden = true
|
||||
});
|
||||
this.OnAreaUpdated += e => this.Panel.PositionOffset = new Vector2(0, e.Area.Height / this.Scale);
|
||||
this.Priority = 10000;
|
||||
this.OnPressed += e => this.IsOpen = !this.IsOpen;
|
||||
}
|
||||
|
||||
public void AddElement(Element element) {
|
||||
this.Panel.AddChild(element);
|
||||
}
|
||||
|
||||
public void AddElement(string text, GenericCallback pressed = null) {
|
||||
this.AddElement(p => text, pressed);
|
||||
}
|
||||
|
||||
public void AddElement(Paragraph.TextCallback text, GenericCallback pressed = null) {
|
||||
var paragraph = new Paragraph(Anchor.AutoLeft, 1, text) {
|
||||
CanBeMoused = true,
|
||||
CanBeSelected = true,
|
||||
PositionOffset = new Vector2(0, 1)
|
||||
};
|
||||
if (pressed != null)
|
||||
paragraph.OnPressed += pressed;
|
||||
paragraph.OnMouseEnter += e => paragraph.TextColor = Color.LightGray;
|
||||
paragraph.OnMouseExit += e => paragraph.TextColor = Color.White;
|
||||
this.AddElement(paragraph);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -268,9 +268,9 @@ namespace MLEM.Ui.Elements {
|
|||
if (this.Anchor >= Anchor.AutoLeft) {
|
||||
Element previousChild;
|
||||
if (this.Anchor == Anchor.AutoInline || this.Anchor == Anchor.AutoInlineIgnoreOverflow) {
|
||||
previousChild = this.GetOlderSibling(false, false);
|
||||
previousChild = this.GetOlderSibling(e => !e.IsHidden && e.CanAutoAnchorsAttach);
|
||||
} else {
|
||||
previousChild = this.GetLowestOlderSibling(false, false);
|
||||
previousChild = this.GetLowestOlderSibling(e => !e.IsHidden && e.CanAutoAnchorsAttach);
|
||||
}
|
||||
if (previousChild != null) {
|
||||
var prevArea = previousChild.GetAreaForAutoAnchors();
|
||||
|
@ -304,12 +304,11 @@ namespace MLEM.Ui.Elements {
|
|||
child.ForceUpdateArea();
|
||||
|
||||
if (this.SetHeightBasedOnChildren && this.Children.Count > 0) {
|
||||
var lowest = this.GetLowestChild(false, true);
|
||||
var lowest = this.GetLowestChild(e => !e.IsHidden);
|
||||
var newHeight = (lowest.UnscrolledArea.Bottom - pos.Y + this.ScaledChildPadding.Y) / this.Scale;
|
||||
if (newHeight != this.size.Y) {
|
||||
this.size.Y = newHeight;
|
||||
if (this.Anchor > Anchor.TopRight)
|
||||
this.ForceUpdateArea();
|
||||
this.ForceUpdateArea();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -324,12 +323,12 @@ namespace MLEM.Ui.Elements {
|
|||
return this.UnscrolledArea;
|
||||
}
|
||||
|
||||
public Element GetLowestChild(bool hiddenAlso, bool unattachableAlso) {
|
||||
public Element GetLowestChild(Func<Element, bool> condition = null) {
|
||||
Element lowest = null;
|
||||
// the lowest child is expected to be towards the back, so search is usually faster if done backwards
|
||||
for (var i = this.Children.Count - 1; i >= 0; i--) {
|
||||
var child = this.Children[i];
|
||||
if (!hiddenAlso && child.IsHidden || !unattachableAlso && !child.CanAutoAnchorsAttach)
|
||||
if (condition != null && !condition(child))
|
||||
continue;
|
||||
if (child.Anchor > Anchor.TopRight && child.Anchor < Anchor.AutoLeft)
|
||||
continue;
|
||||
|
@ -339,14 +338,14 @@ namespace MLEM.Ui.Elements {
|
|||
return lowest;
|
||||
}
|
||||
|
||||
public Element GetLowestOlderSibling(bool hiddenAlso, bool unattachableAlso) {
|
||||
public Element GetLowestOlderSibling(Func<Element, bool> condition = null) {
|
||||
if (this.Parent == null)
|
||||
return null;
|
||||
Element lowest = null;
|
||||
foreach (var child in this.Parent.Children) {
|
||||
if (child == this)
|
||||
break;
|
||||
if (!hiddenAlso && child.IsHidden || !unattachableAlso && !child.CanAutoAnchorsAttach)
|
||||
if (condition != null && !condition(child))
|
||||
continue;
|
||||
if (lowest == null || child.UnscrolledArea.Bottom >= lowest.UnscrolledArea.Bottom)
|
||||
lowest = child;
|
||||
|
@ -354,50 +353,52 @@ namespace MLEM.Ui.Elements {
|
|||
return lowest;
|
||||
}
|
||||
|
||||
public Element GetOlderSibling(bool hiddenAlso, bool unattachableAlso) {
|
||||
public Element GetOlderSibling(Func<Element, bool> condition = null) {
|
||||
if (this.Parent == null)
|
||||
return null;
|
||||
Element older = null;
|
||||
foreach (var child in this.Parent.Children) {
|
||||
if (child == this)
|
||||
break;
|
||||
if (!hiddenAlso && child.IsHidden || !unattachableAlso && !child.CanAutoAnchorsAttach)
|
||||
if (condition != null && !condition(child))
|
||||
continue;
|
||||
older = child;
|
||||
}
|
||||
return older;
|
||||
}
|
||||
|
||||
public IEnumerable<Element> GetSiblings(bool hiddenAlso) {
|
||||
public IEnumerable<Element> GetSiblings(Func<Element, bool> condition = null) {
|
||||
if (this.Parent == null)
|
||||
yield break;
|
||||
foreach (var child in this.Parent.Children) {
|
||||
if (!hiddenAlso && child.IsHidden)
|
||||
if (condition != null && !condition(child))
|
||||
continue;
|
||||
if (child != this)
|
||||
yield return child;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<Element> GetChildren(Func<Element, bool> condition = null, bool regardChildrensChildren = false) {
|
||||
public IEnumerable<Element> GetChildren(Func<Element, bool> condition = null, bool regardGrandchildren = false, bool ignoreFalseGrandchildren = false) {
|
||||
foreach (var child in this.Children) {
|
||||
if (regardChildrensChildren) {
|
||||
foreach (var cc in child.GetChildren(condition, true))
|
||||
var applies = condition == null || condition(child);
|
||||
if (applies)
|
||||
yield return child;
|
||||
if (regardGrandchildren && (!ignoreFalseGrandchildren || applies)) {
|
||||
foreach (var cc in child.GetChildren(condition, true, ignoreFalseGrandchildren))
|
||||
yield return cc;
|
||||
}
|
||||
if (condition == null || condition(child))
|
||||
yield return child;
|
||||
}
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetChildren<T>(Func<T, bool> condition = null, bool regardChildrensChildren = false) where T : Element {
|
||||
public IEnumerable<T> GetChildren<T>(Func<T, bool> condition = null, bool regardGrandchildren = false, bool ignoreFalseGrandchildren = false) where T : Element {
|
||||
foreach (var child in this.Children) {
|
||||
if (regardChildrensChildren) {
|
||||
foreach (var cc in child.GetChildren(condition, true))
|
||||
var applies = child is T t && (condition == null || condition(t));
|
||||
if (applies)
|
||||
yield return (T) child;
|
||||
if (regardGrandchildren && (!ignoreFalseGrandchildren || applies)) {
|
||||
foreach (var cc in child.GetChildren(condition, true, ignoreFalseGrandchildren))
|
||||
yield return cc;
|
||||
}
|
||||
if (child is T t && (condition == null || condition(t)))
|
||||
yield return t;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace MLEM.Ui.Elements {
|
|||
return;
|
||||
// the "real" first child is the scroll bar, which we want to ignore
|
||||
var firstChild = this.Children[1];
|
||||
var lowestChild = this.GetLowestChild(false, true);
|
||||
var lowestChild = this.GetLowestChild(e => !e.IsHidden);
|
||||
// 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;
|
||||
this.ScrollBar.MaxValue = ((childrenHeight - this.Area.Height) / this.Scale + this.ChildPadding.Y * 2).Ceil();
|
||||
|
|
|
@ -14,7 +14,7 @@ namespace MLEM.Ui.Elements {
|
|||
// don't += because we want to override the checking + unchecking behavior of Checkbox
|
||||
this.OnPressed = element => {
|
||||
this.Checked = true;
|
||||
foreach (var sib in this.GetSiblings(true)) {
|
||||
foreach (var sib in this.GetSiblings()) {
|
||||
if (sib is RadioButton radio && radio.Group == this.Group)
|
||||
radio.Checked = false;
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ namespace MLEM.Ui {
|
|||
protected virtual Element GetTabNextElement(bool backward) {
|
||||
if (this.ActiveRoot == null)
|
||||
return null;
|
||||
var children = this.ActiveRoot.Element.GetChildren(regardChildrensChildren: true).Append(this.ActiveRoot.Element);
|
||||
var children = this.ActiveRoot.Element.GetChildren(c => !c.IsHidden, true, true).Append(this.ActiveRoot.Element);
|
||||
if (this.SelectedElement?.Root != this.ActiveRoot) {
|
||||
return backward ? children.LastOrDefault(c => c.CanBeSelected) : children.FirstOrDefault(c => c.CanBeSelected);
|
||||
} else {
|
||||
|
@ -165,7 +165,7 @@ namespace MLEM.Ui {
|
|||
protected virtual Element GetGamepadNextElement(Rectangle searchArea) {
|
||||
if (this.ActiveRoot == null)
|
||||
return null;
|
||||
var children = this.ActiveRoot.Element.GetChildren(regardChildrensChildren: true).Append(this.ActiveRoot.Element);
|
||||
var children = this.ActiveRoot.Element.GetChildren(c => !c.IsHidden, true, true).Append(this.ActiveRoot.Element);
|
||||
if (this.SelectedElement?.Root != this.ActiveRoot) {
|
||||
return children.FirstOrDefault(c => c.CanBeSelected);
|
||||
} else {
|
||||
|
|
Loading…
Reference in a new issue