using System;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
using JetBrains.Annotations;
using Robust.Client.Graphics;
using Robust.Client.UserInterface.RichText;
using Robust.Shared.IoC;
using Robust.Shared.Maths;
using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Robust.Client.UserInterface.Controls
{
[Virtual]
public partial class RichTextLabel : Control
{
[Dependency] private MarkupTagManager _tagManager = default!;
private RichTextEntry? _entry;
private float _lineHeightScale = 1;
private bool _lineHeightOverride;
[ViewVariables(VVAccess.ReadWrite)]
public float LineHeightScale
{
get
{
if (!_lineHeightOverride && TryGetStyleProperty(nameof(LineHeightScale), out float value))
return value;
return _lineHeightScale;
}
set
{
_lineHeightScale = value;
_lineHeightOverride = true;
InvalidateMeasure();
}
}
///
/// Gets or sets the markup string displayed by this control.
///
///
///
/// This method converts the given string with .
/// The original markup string is not kept,
/// so setting and then getting the function may provide a different result.
///
///
/// Unlike ,
/// no tag whitelist will be set on the rendered message. Do not pass untrusted user input to this!
///
///
public string? Text
{
get => _entry?.Message.ToMarkup();
set
{
if (value == null)
Clear();
else
SetMessage(FormattedMessage.FromMarkupPermissive(value), tagsAllowed: null);
}
}
public void Clear()
{
_entry?.RemoveControls();
_entry = null;
InvalidateMeasure();
}
public IEnumerable Controls => _entry?.Controls?.Values ?? Enumerable.Empty();
public IReadOnlyList Nodes => _entry?.Message.Nodes ?? Array.Empty();
public RichTextLabel()
{
IoCManager.InjectDependencies(this);
VerticalAlignment = VAlignment.Center;
}
///
/// Sets the formatted message displayed by this control.
///
/// The message to display.
/// If provided, the default color to use for this message rendering.
///
/// This method sets the set of allowed tags to only include a small amount of safe formatting tags.
/// Use if this is not desired.
///
public void SetMessage(FormattedMessage message, Color? defaultColor = null)
{
SetMessage(message, RichTextEntry.DefaultTags, defaultColor);
}
///
/// Sets the formatted message displayed by this control.
///
/// The message to display.
///
/// The set of allowed markup tags that will be displayed.
/// If null, all tags are allowed.
/// If provided, the default color to use for this message rendering.
///
/// This method sets the set of allowed tags to only include a small amount of safe formatting tags.
/// Use if this is not desired.
///
public void SetMessage(FormattedMessage message, Type[]? tagsAllowed, Color? defaultColor = null)
{
_entry?.RemoveControls();
_entry = new RichTextEntry(message, this, _tagManager, tagsAllowed, defaultColor);
InvalidateMeasure();
}
public void SetMessage(string message, Color? defaultColor = null)
{
SetMessage(message, RichTextEntry.DefaultTags, defaultColor);
}
public void SetMessage(string message, Type[]? tagsAllowed, Color? defaultColor = null)
{
var msg = new FormattedMessage();
msg.AddText(message);
SetMessage(msg, tagsAllowed, defaultColor);
}
public string? GetMessage() => _entry?.Message.ToMarkup();
///
/// Returns a copy of the currently used formatted message.
///
public FormattedMessage? GetFormattedMessage() => _entry == null ? null : new FormattedMessage(_entry.Value.Message);
protected override Vector2 MeasureOverride(Vector2 availableSize)
{
if (_entry == null)
return Vector2.Zero;
var font = _getFont();
// _entry is nullable struct.
// cannot just call _entry.Value.Update() as that doesn't actually update _entry.
_entry = _entry.Value.Update(_tagManager, font, availableSize.X * UIScale, UIScale, LineHeightScale);
return new Vector2(_entry.Value.Width / UIScale, _entry.Value.Height / UIScale);
}
protected internal override void Draw(DrawingHandleScreen handle)
{
base.Draw(handle);
_entry?.Draw(_tagManager, handle, _getFont(), SizeBox, 0, new MarkupDrawingContext(), UIScale, LineHeightScale);
}
[Pure]
private Font _getFont()
{
if (TryGetStyleProperty("font", out var font))
{
return font;
}
return UserInterfaceManager.ThemeDefaults.DefaultFont;
}
}
}