using Content.Client.UserInterface.ControlExtensions; using Content.Client.UserInterface.RichText; using Content.Shared.Chat; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Shared.Input; using Robust.Shared.Utility; namespace Content.Client.UserInterface.Controls; /// /// Carries link data parsed and resolved from a TextLink , /// only one LinkType field per link should be populated at a time. /// public sealed partial class TextLinkLabel : Label { public string? LinkString { get; init; } // default links public NetEntity? LinkEntity { get; init; } // entity links public Color LinkColor { get; set; } [Dependency] private IEntityManager _entity = default!; private bool _canClickLink; public TextLinkLabel() { IoCManager.InjectDependencies(this); OnKeyBindDown += OnKeybindDown; OnMouseEntered += _ => OnHoverChanged(true); OnMouseExited += _ => OnHoverChanged(false); } /// /// Refreshes the label's properties based on the current link target /// and the viewer's permission to follow it.
Call after construction, /// and whenever that permission could have changed. ///
/// Whether the label should be shown at all. Defaults to true. /// Additional override to force the label non-clickable. Defaults to true. public void UpdateLabelProperties(SharedChatSystem? chatSystem, bool? visible = null, bool? clickable = null) { visible ??= true; Visible = visible.Value; clickable ??= true; _canClickLink = (LinkString != null || (LinkEntity is { } netEntity && (chatSystem?.CanClickMessageSender(netEntity) ?? false))) && (bool)clickable; MouseFilter = _canClickLink ? MouseFilterMode.Stop : MouseFilterMode.Ignore; DefaultCursorShape = _canClickLink ? CursorShape.Hand : CursorShape.Arrow; OnHoverChanged(false); } private void OnHoverChanged(bool hovering) { FontColorOverride = (_canClickLink, hovering) switch { (true, true) => Color.LightSkyBlue, // clickable and currently hovered _ => LinkColor, // not clickable, or not hovered }; } /// /// Delegates click to the nearest ancestor ILinkClickHandler or IEntityLinkClickHandler; /// TextLinkLabel has no idea what a click actually does. /// private void OnKeybindDown(GUIBoundKeyEventArgs args) { if (args.Function != EngineKeyFunctions.UIClick) return; if (LinkString is null && LinkEntity is null) return; if (LinkEntity is { } entity && this.TryGetParentHandler(out var entityLinkClickHandler)) { entityLinkClickHandler.HandleClick(entity); } else if (LinkString != null && this.TryGetParentHandler(out var linkClickHandler)) { linkClickHandler.HandleClick(LinkString); } } }