1
0
Fork 0
mirror of https://github.com/Ellpeck/MLEM.git synced 2024-11-17 19:20:07 +01:00
MLEM/MLEM.Ui/Elements/Tooltip.cs

144 lines
6.1 KiB
C#
Raw Normal View History

2019-08-13 23:54:29 +02:00
using System;
using System.Linq;
2019-08-13 23:54:29 +02:00
using Microsoft.Xna.Framework;
using MLEM.Ui.Style;
namespace MLEM.Ui.Elements {
2020-05-22 17:02:24 +02:00
/// <summary>
/// A tooltip element for use inside of a <see cref="UiSystem"/>.
/// A tooltip is a <see cref="Panel"/> with a custom cursor that always follows the position of the mouse.
/// Tooltips can easily be configured to be hooked onto an element, causing them to appear when it is moused, and disappear when it is not moused anymore.
/// </summary>
public class Tooltip : Panel {
2019-08-13 23:54:29 +02:00
2020-05-22 17:02:24 +02:00
/// <summary>
/// The offset that this tooltip's top left corner should have from the mouse position
/// </summary>
public StyleProp<Vector2> MouseOffset;
2020-05-22 17:02:24 +02:00
/// <summary>
2020-12-05 16:42:21 +01:00
/// The amount of time that the mouse has to be over an element before it appears
/// </summary>
public StyleProp<TimeSpan> Delay;
/// <summary>
2020-05-22 17:02:24 +02:00
/// The paragraph of text that this tooltip displays
/// </summary>
public Paragraph Paragraph;
2019-08-13 23:54:29 +02:00
2020-12-05 16:42:21 +01:00
private TimeSpan delayCountdown;
2020-05-22 17:02:24 +02:00
/// <summary>
/// Creates a new tooltip with the given settings
/// </summary>
/// <param name="width">The width of the tooltip</param>
/// <param name="text">The text to display on the tooltip</param>
/// <param name="elementToHover">The element that should automatically cause the tooltip to appear and disappear when hovered and not hovered, respectively</param>
public Tooltip(float width, string text = null, Element elementToHover = null) :
base(Anchor.TopLeft, Vector2.One, Vector2.Zero) {
if (text != null)
this.Paragraph = this.AddChild(new Paragraph(Anchor.TopLeft, width, text));
this.Init(elementToHover);
}
/// <summary>
/// Creates a new tooltip with the given settings
/// </summary>
/// <param name="width">The width of the tooltip</param>
/// <param name="textCallback">The text to display on the tooltip</param>
/// <param name="elementToHover">The element that should automatically cause the tooltip to appear and disappear when hovered and not hovered, respectively</param>
public Tooltip(float width, Paragraph.TextCallback textCallback, Element elementToHover = null) :
base(Anchor.TopLeft, Vector2.One, Vector2.Zero) {
this.Paragraph = this.AddChild(new Paragraph(Anchor.TopLeft, width, textCallback));
this.Init(elementToHover);
2019-08-13 23:54:29 +02:00
}
2020-05-22 17:02:24 +02:00
/// <inheritdoc />
2019-08-13 23:54:29 +02:00
public override void Update(GameTime time) {
base.Update(time);
this.SnapPositionToMouse();
2020-12-05 16:42:21 +01:00
if (this.IsHidden && this.delayCountdown > TimeSpan.Zero) {
this.delayCountdown -= time.ElapsedGameTime;
if (this.delayCountdown <= TimeSpan.Zero)
this.IsHidden = false;
}
}
2020-05-22 17:02:24 +02:00
/// <inheritdoc />
public override void ForceUpdateArea() {
if (this.Parent != null)
throw new NotSupportedException($"A tooltip shouldn't be the child of another element ({this.Parent})");
base.ForceUpdateArea();
}
2020-05-22 17:02:24 +02:00
/// <inheritdoc />
protected override void InitStyle(UiStyle style) {
base.InitStyle(style);
this.Texture.SetFromStyle(style.TooltipBackground);
this.MouseOffset.SetFromStyle(style.TooltipOffset);
2020-12-05 16:42:21 +01:00
this.Delay.SetFromStyle(style.TooltipDelay);
2020-10-31 17:55:46 +01:00
// we can't set from style here since it's a different element
this.Paragraph?.TextColor.Set(style.TooltipTextColor);
}
2020-05-22 17:02:24 +02:00
/// <summary>
/// Causes this tooltip's position to be snapped to the mouse position.
/// </summary>
public void SnapPositionToMouse() {
var viewport = this.System.Viewport.Size;
var offset = (this.Input.MousePosition.ToVector2() + this.MouseOffset.Value) / this.Scale;
if (offset.X < 0)
offset.X = 0;
if (offset.Y < 0)
offset.Y = 0;
if (offset.X * this.Scale + this.Area.Width >= viewport.X)
offset.X = (viewport.X - this.Area.Width) / this.Scale;
if (offset.Y * this.Scale + this.Area.Height >= viewport.Y)
offset.Y = (viewport.Y - this.Area.Height) / this.Scale;
this.PositionOffset = offset;
2019-08-13 23:54:29 +02:00
}
/// <summary>
/// Adds this tooltip to the given <see cref="UiSystem"/> and either displays it directly or starts the <see cref="Delay"/> timer.
/// </summary>
/// <param name="system">The system to add this tooltip to</param>
/// <param name="name">The name that this tooltip should use</param>
public void Display(UiSystem system, string name) {
system.Add(name, this);
if (this.Delay <= TimeSpan.Zero) {
this.IsHidden = false;
this.SnapPositionToMouse();
} else {
this.IsHidden = true;
this.delayCountdown = this.Delay;
}
}
/// <summary>
/// Removes this tooltip from its <see cref="UiSystem"/> and resets the <see cref="Delay"/> timer, if there is one.
/// </summary>
public void Remove() {
this.delayCountdown = TimeSpan.Zero;
if (this.System != null)
this.System.Remove(this.Root.Name);
}
private void Init(Element elementToHover) {
this.Paragraph.AutoAdjustWidth = true;
this.SetWidthBasedOnChildren = true;
this.SetHeightBasedOnChildren = true;
this.ChildPadding = new Vector2(2);
this.CanBeMoused = false;
if (elementToHover != null) {
elementToHover.OnMouseEnter += element => {
// only display the tooltip if there is anything in it
if (this.Children.Any(c => !c.IsHidden))
this.Display(element.System, element.GetType().Name + "Tooltip");
};
elementToHover.OnMouseExit += element => this.Remove();
}
}
2019-08-13 23:54:29 +02:00
}
}