using System.Numerics; using Robust.Client.AutoGenerated; using Robust.Client.Graphics; using Robust.Client.ResourceManagement; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.RichText; using Robust.Client.UserInterface.XAML; using Robust.Shared.Utility; using static Content.Shared._White.InteractiveBoard.SharedInteractiveBoardComponent; namespace Content.Client._White.InteractiveBoard.UI { [GenerateTypedNameReferences] public sealed partial class InteractiveBoardWindow : BaseWindow { private static readonly Color DefaultTextColor = new(255, 255, 255); private const int MarginSize = 12; private StyleBoxTexture _contentTex = new(); private float _contentLineScale = 1.0f; private DragMode _allowedResizeModes = ~DragMode.None; private readonly Type[] _allowedTags = new Type[] { typeof(BoldItalicTag), typeof(BoldTag), typeof(BulletTag), typeof(ColorTag), typeof(HeadingTag), typeof(ItalicTag) }; public InteractiveBoardWindow() { RobustXamlLoader.Load(this); CloseButton.OnPressed += _ => Close(); CopyButton.OnPressed += _ => CopyToClipboard(); } public void InitVisuals(EntityUid entity, InteractiveBoardVisualsComponent visuals) { var resCache = IoCManager.Resolve(); Background.ModulateSelfOverride = visuals.BackgroundModulate; var backgroundImage = resCache.GetResource(visuals.ImagePath); { var backgroundImageMode = visuals.BackgroundImageTile ? StyleBoxTexture.StretchMode.Tile : StyleBoxTexture.StretchMode.Stretch; var backgroundPatchMargin = visuals.BackgroundPatchMargin; Background.PanelOverride = new StyleBoxTexture { Texture = backgroundImage, TextureScale = visuals.BackgroundScale, Mode = backgroundImageMode, PatchMarginLeft = backgroundPatchMargin.Left, PatchMarginBottom = backgroundPatchMargin.Bottom, PatchMarginRight = backgroundPatchMargin.Right, PatchMarginTop = backgroundPatchMargin.Top }; } if (visuals.HeaderImagePath != null) { HeaderImage.TexturePath = visuals.HeaderImagePath; HeaderImage.MinSize = HeaderImage.TextureNormal?.Size ?? Vector2.Zero; } HeaderImage.ModulateSelfOverride = visuals.HeaderImageModulate; HeaderImage.Margin = new Thickness(visuals.HeaderMargin.Left, visuals.HeaderMargin.Top, visuals.HeaderMargin.Right, visuals.HeaderMargin.Bottom); Content.ModulateSelfOverride = visuals.ContentImageModulate; WrittenTextLabel.ModulateSelfOverride = visuals.FontAccentColor; var contentImage = visuals.ContentImagePath != null ? resCache.GetResource(visuals.ContentImagePath) : null; if (contentImage != null) { _contentTex = new StyleBoxTexture { Texture = contentImage, Mode = StyleBoxTexture.StretchMode.Tile, }; Content.PanelOverride = _contentTex; _contentLineScale = visuals.ContentImageNumLines; } Content.Margin = new Thickness( visuals.ContentMargin.Left, visuals.ContentMargin.Top, visuals.ContentMargin.Right, visuals.ContentMargin.Bottom); if (visuals.MaxWritableArea != null) { var a = (Vector2)visuals.MaxWritableArea; ScrollingContents.MinSize = Vector2.Zero; ScrollingContents.MinSize = a; if (a.X > 0.0f) { ScrollingContents.MaxWidth = a.X; _allowedResizeModes &= ~(DragMode.Left | DragMode.Right); SetWidth = float.NaN; } if (a.Y > 0.0f) { ScrollingContents.MaxHeight = a.Y; _allowedResizeModes &= ~(DragMode.Top | DragMode.Bottom); SetHeight = float.NaN; } } } protected override void Draw(DrawingHandleScreen handle) { if (WrittenTextLabel.TryGetStyleProperty("font", out var font)) { float fontLineHeight = font.GetLineHeight(1.0f); _contentTex.ExpandMarginTop = font.GetDescent(UIScale); var scaleY = _contentLineScale * fontLineHeight / _contentTex.Texture?.Height ?? fontLineHeight; _contentTex.TextureScale = new Vector2(1, scaleY); { var headerHeight = HeaderImage.Size.Y + HeaderImage.Margin.Top + HeaderImage.Margin.Bottom; var headerInLines = headerHeight / (fontLineHeight * _contentLineScale); var paddingRequiredInLines = (float)Math.Ceiling(headerInLines) - headerInLines; var verticalMargin = fontLineHeight * paddingRequiredInLines * _contentLineScale; TextAlignmentPadding.Margin = new Thickness(0.0f, verticalMargin, 0.0f, 0.0f); } } base.Draw(handle); } public void Populate(InteractiveBoardBoundUserInterfaceState state) { var isEditing = state.Mode == InteractiveBoardAction.Write; var wasEditing = InputContainer.Visible; InputContainer.Visible = isEditing; var msg = new FormattedMessage(); msg.AddMarkupPermissive(state.Text); var shouldCopyText = 0 == Input.TextLength && 0 != state.Text.Length; if (!wasEditing || shouldCopyText) { Input.TextRope = Rope.Leaf.Empty; Input.CursorPosition = new TextEdit.CursorPos(); Input.InsertAtCursor(state.Text); } WrittenTextLabel.SetMessage(msg, _allowedTags, DefaultTextColor); WrittenTextLabel.Visible = !isEditing && state.Text.Length > 0; BlankIndicator.Visible = !isEditing && state.Text.Length == 0; } protected override DragMode GetDragModeFor(Vector2 relativeMousePos) { var mode = DragMode.None; if (relativeMousePos.Y < MarginSize) { mode |= DragMode.Top; } else if (relativeMousePos.Y > Size.Y - MarginSize) { mode |= DragMode.Bottom; } if (relativeMousePos.X < MarginSize) { mode |= DragMode.Left; } else if (relativeMousePos.X > Size.X - MarginSize) { mode |= DragMode.Right; } if((mode & _allowedResizeModes) == DragMode.None) { return DragMode.Move; } return mode & _allowedResizeModes; } private void CopyToClipboard() { if (WrittenTextLabel.GetMessage() == null) return; if (InputContainer.Visible) { InputContainer.Visible = false; Input.Editable = true; WrittenTextLabel.Visible = true; return; } InputContainer.Visible = true; Input.Editable = false; WrittenTextLabel.Visible = false; } } }