diff --git a/CHANGELOG.md b/CHANGELOG.md
index 588e53c..b435f63 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,8 @@ Improvements
- Exposed the epsilon value used by Element calculations
- Made Image ScaleToImage take ui scale into account
- Added style properties for a lot of hardcoded default element styles
+- Allow style properties to set style values with a higher priority, which allows elements to style their default children
+- Allow changing the entire ui style for a single element
Fixes
- Fixed VerticalSpace height parameter being an integer
diff --git a/Demos/UiDemo.cs b/Demos/UiDemo.cs
index bc85457..45feeb0 100644
--- a/Demos/UiDemo.cs
+++ b/Demos/UiDemo.cs
@@ -69,7 +69,7 @@ namespace Demos {
this.UiRoot.AddChild(this.root);
this.root.AddChild(new Paragraph(Anchor.AutoLeft, 1, "This is a small demo for MLEM.Ui, a user interface library that is part of the MLEM Library for Extending MonoGame."));
- var image = this.root.AddChild(new Image(Anchor.AutoCenter, new Vector2(50, 50), new TextureRegion(this.testTexture, 0, 0, 8, 8)) {IsHidden = true, Padding = new Vector2(3)});
+ var image = this.root.AddChild(new Image(Anchor.AutoCenter, new Vector2(50, 50), new TextureRegion(this.testTexture, 0, 0, 8, 8)) {IsHidden = true, Padding = new Padding(3)});
// Setting the x or y coordinate of the size to 1 or a lower number causes the width or height to be a percentage of the parent's width or height
// (for example, setting the size's x to 0.75 would make the element's width be 0.75*parentWidth)
this.root.AddChild(new Button(Anchor.AutoCenter, new Vector2(1, 10), "Toggle Grass Image", "This button shows a grass tile above it to show the automatic anchoring of objects.") {
diff --git a/MLEM.Ui/Elements/Button.cs b/MLEM.Ui/Elements/Button.cs
index ee7fdd5..ed1744c 100644
--- a/MLEM.Ui/Elements/Button.cs
+++ b/MLEM.Ui/Elements/Button.cs
@@ -1,5 +1,6 @@
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
+using MLEM.Misc;
using MLEM.Textures;
using MLEM.Ui.Style;
@@ -81,7 +82,8 @@ namespace MLEM.Ui.Elements {
/// The text that should be displayed in a when hovering over this button
public Button(Anchor anchor, Vector2 size, string text = null, string tooltipText = null) : base(anchor, size) {
if (text != null) {
- this.Text = new Paragraph(Anchor.Center, 1, text, true) {Padding = new Vector2(1)};
+ this.Text = new Paragraph(Anchor.Center, 1, text, true);
+ this.Text.Padding.SetFromStyle(new Padding(1), 1);
this.AddChild(this.Text);
}
if (tooltipText != null)
diff --git a/MLEM.Ui/Elements/Element.cs b/MLEM.Ui/Elements/Element.cs
index 4d9abf6..19bfa3a 100644
--- a/MLEM.Ui/Elements/Element.cs
+++ b/MLEM.Ui/Elements/Element.cs
@@ -32,8 +32,17 @@ namespace MLEM.Ui.Elements {
internal set {
this.system = value;
this.Controls = value?.Controls;
- if (this.system != null)
- this.InitStyle(this.system.Style);
+ this.Style = value?.Style;
+ }
+ }
+ public UiStyle Style {
+ get => this.style;
+ set {
+ if (this.style != value) {
+ this.style = value;
+ if (value != null)
+ this.InitStyle(value);
+ }
}
}
///
@@ -109,31 +118,13 @@ namespace MLEM.Ui.Elements {
///
public Vector2 ScaledOffset => this.offset * this.Scale;
///
- /// The padding that this element has.
- /// The padding is subtracted from the element's , and it is an area that the element does not extend into. This means that this element's resulting does not include this padding.
- ///
- public Padding Padding;
- ///
/// The , but with applied.
///
- public Padding ScaledPadding => this.Padding * this.Scale;
- ///
- /// The child padding that this element has.
- /// The child padding moves any added to this element inwards by the given amount in each direction.
- ///
- public Padding ChildPadding {
- get => this.childPadding;
- set {
- if (this.childPadding == value)
- return;
- this.childPadding = value;
- this.SetAreaDirty();
- }
- }
+ public Padding ScaledPadding => this.Padding.Value * this.Scale;
///
/// The , but with applied.
///
- public Padding ScaledChildPadding => this.childPadding * this.Scale;
+ public Padding ScaledChildPadding => this.ChildPadding.Value * this.Scale;
///
/// This element's current , but with applied.
///
@@ -260,6 +251,7 @@ namespace MLEM.Ui.Elements {
/// Stores whether this element is its 's .
///
public bool IsSelected { get; protected set; }
+
///
/// A style property that contains the selection indicator that is displayed on this element if it is the
///
@@ -272,6 +264,17 @@ namespace MLEM.Ui.Elements {
/// A style property that contains the sound effect that is played when this element's is called
///
public StyleProp SecondActionSound;
+ ///
+ /// The padding that this element has.
+ /// The padding is subtracted from the element's , and it is an area that the element does not extend into. This means that this element's resulting does not include this padding.
+ ///
+ public StyleProp Padding;
+ ///
+ /// The child padding that this element has.
+ /// The child padding moves any added to this element inwards by the given amount in each direction.
+ /// When setting this style after this element has already been added to a ui, should be called.
+ ///
+ public StyleProp ChildPadding;
///
/// Event that is called after this element is drawn, but before its children are drawn
@@ -389,11 +392,11 @@ namespace MLEM.Ui.Elements {
private Anchor anchor;
private Vector2 size;
private Vector2 offset;
- private Padding childPadding;
private RectangleF area;
private bool areaDirty;
private bool isHidden;
private int priority;
+ private UiStyle style;
///
/// Creates a new element with the given anchor and size and sets up some default event reactions.
diff --git a/MLEM.Ui/Elements/ElementHelper.cs b/MLEM.Ui/Elements/ElementHelper.cs
index 8a50c6c..b7755f1 100644
--- a/MLEM.Ui/Elements/ElementHelper.cs
+++ b/MLEM.Ui/Elements/ElementHelper.cs
@@ -2,6 +2,7 @@ using System;
using System.Linq;
using Microsoft.Xna.Framework;
using MLEM.Input;
+using MLEM.Misc;
using MLEM.Textures;
namespace MLEM.Ui.Elements {
@@ -22,7 +23,8 @@ namespace MLEM.Ui.Elements {
/// An image button
public static Button ImageButton(Anchor anchor, Vector2 size, TextureRegion texture, string text = null, string tooltipText = null, float imagePadding = 2) {
var button = new Button(anchor, size, text, tooltipText);
- var image = new Image(Anchor.CenterLeft, Vector2.One, texture) {Padding = new Vector2(imagePadding)};
+ var image = new Image(Anchor.CenterLeft, Vector2.One, texture);
+ image.Padding.SetFromStyle(new Padding(imagePadding), 1);
button.OnAreaUpdated += e => image.Size = new Vector2(e.Area.Height, e.Area.Height) / e.Scale;
button.AddChild(image, 0);
return button;
diff --git a/MLEM.Ui/Elements/Panel.cs b/MLEM.Ui/Elements/Panel.cs
index 2428fcd..9c8d8dd 100644
--- a/MLEM.Ui/Elements/Panel.cs
+++ b/MLEM.Ui/Elements/Panel.cs
@@ -71,8 +71,12 @@ namespace MLEM.Ui.Elements {
AutoHideWhenEmpty = autoHideScrollbar,
IsHidden = autoHideScrollbar
};
- if (autoHideScrollbar)
- this.ScrollBar.OnAutoHide += e => this.ChildPadding += new Padding(0, this.ScrollerSize.Value.X, 0, 0) * (e.IsHidden ? -1 : 1);
+ if (autoHideScrollbar) {
+ this.ScrollBar.OnAutoHide += e => {
+ this.ChildPadding += new Padding(0, this.ScrollerSize.Value.X, 0, 0) * (e.IsHidden ? -1 : 1);
+ this.SetAreaDirty();
+ };
+ }
// handle automatic element selection, the scroller needs to scroll to the right location
this.OnSelectedElementChanged += (element, otherElement) => {
@@ -216,8 +220,7 @@ namespace MLEM.Ui.Elements {
this.Texture.SetFromStyle(style.PanelTexture);
this.StepPerScroll.SetFromStyle(style.PanelStepPerScroll);
this.ScrollerSize.SetFromStyle(style.PanelScrollerSize);
- if (this.ChildPadding == default)
- this.ChildPadding = style.PanelChildPadding;
+ this.ChildPadding.SetFromStyle(style.PanelChildPadding);
this.SetScrollBarStyle();
}
@@ -235,7 +238,7 @@ namespace MLEM.Ui.Elements {
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
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.Value.Height;
// update the render target
var targetArea = (Rectangle) this.GetRenderTargetArea();
diff --git a/MLEM.Ui/Elements/Tooltip.cs b/MLEM.Ui/Elements/Tooltip.cs
index 83c3c20..86ea485 100644
--- a/MLEM.Ui/Elements/Tooltip.cs
+++ b/MLEM.Ui/Elements/Tooltip.cs
@@ -79,10 +79,9 @@ namespace MLEM.Ui.Elements {
this.Texture.SetFromStyle(style.TooltipBackground);
this.MouseOffset.SetFromStyle(style.TooltipOffset);
this.Delay.SetFromStyle(style.TooltipDelay);
- this.ChildPadding = style.TooltipChildPadding;
+ this.ChildPadding.SetFromStyle(style.TooltipChildPadding);
if (this.Paragraph != null) {
- // we can't set from style here since it's a different element
- this.Paragraph.TextColor.Set(style.TooltipTextColor);
+ this.Paragraph.TextColor.SetFromStyle(style.TooltipTextColor, 1);
this.Paragraph.Size = new Vector2(style.TooltipTextWidth, 0);
}
}
diff --git a/MLEM.Ui/Style/StyleProp.cs b/MLEM.Ui/Style/StyleProp.cs
index 01fddee..02f6c4a 100644
--- a/MLEM.Ui/Style/StyleProp.cs
+++ b/MLEM.Ui/Style/StyleProp.cs
@@ -14,14 +14,14 @@ namespace MLEM.Ui.Style {
/// The currently applied style
///
public T Value { get; private set; }
- private bool isCustom;
+ private byte lastSetPriority;
///
/// Creates a new style property with the given custom style.
///
/// The custom style to apply
public StyleProp(T value) {
- this.isCustom = true;
+ this.lastSetPriority = byte.MaxValue;
this.Value = value;
}
@@ -30,9 +30,12 @@ namespace MLEM.Ui.Style {
/// This allows this property to be overridden by custom style settings using .
///
/// The style to apply
- public void SetFromStyle(T value) {
- if (!this.isCustom)
+ /// The priority that this style value has. Higher priority style values will override lower priority style values.
+ public void SetFromStyle(T value, byte priority = 0) {
+ if (priority >= this.lastSetPriority) {
this.Value = value;
+ this.lastSetPriority = priority;
+ }
}
///
@@ -41,7 +44,7 @@ namespace MLEM.Ui.Style {
///
///
public void Set(T value) {
- this.isCustom = true;
+ this.lastSetPriority = byte.MaxValue;
this.Value = value;
}
@@ -64,7 +67,7 @@ namespace MLEM.Ui.Style {
///
public override string ToString() {
- return $"{this.Value} (Custom: {this.isCustom})";
+ return this.Value?.ToString();
}
///
diff --git a/MLEM/Misc/Padding.cs b/MLEM/Misc/Padding.cs
index e69f631..7586f03 100644
--- a/MLEM/Misc/Padding.cs
+++ b/MLEM/Misc/Padding.cs
@@ -52,6 +52,14 @@ namespace MLEM.Misc {
this.Bottom = bottom;
}
+ ///
+ /// Creates a new padding with the specified value, which will be applied to each edge.
+ ///
+ /// The padding to apply to each edge
+ public Padding(float value) :
+ this(value, value) {
+ }
+
///
/// Creates a new padding with the specified x and y values, applying them to both edges.
///
diff --git a/Sandbox/GameImpl.cs b/Sandbox/GameImpl.cs
index 6167e28..70e4f18 100644
--- a/Sandbox/GameImpl.cs
+++ b/Sandbox/GameImpl.cs
@@ -224,7 +224,7 @@ namespace Sandbox {
var button = loadPanel.AddChild(new Button(Anchor.AutoLeft, new Vector2(1)) {
SetHeightBasedOnChildren = true,
Padding = new Padding(0, 0, 0, 1),
- ChildPadding = new Vector2(3)
+ ChildPadding = new Padding(3)
});
button.AddChild(new Group(Anchor.AutoLeft, new Vector2(0.5F, 30), false) {
CanBeMoused = false
diff --git a/Tests/UiTests.cs b/Tests/UiTests.cs
index 90822be..ef70dad 100644
--- a/Tests/UiTests.cs
+++ b/Tests/UiTests.cs
@@ -49,7 +49,7 @@ namespace Tests {
var button = panel.AddChild(new Button(Anchor.AutoLeft, new Vector2(1)) {
SetHeightBasedOnChildren = true,
Padding = new Padding(0, 0, 0, 1),
- ChildPadding = new Vector2(3)
+ ChildPadding = new Padding(3)
});
button.AddChild(new Group(Anchor.AutoLeft, new Vector2(0.5F, 30), false) {
CanBeMoused = false