From f781fd8ab6cd314a67f402279c5713699ca20f5e Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 5 Aug 2022 15:29:37 +0200 Subject: [PATCH] Add horizontal alignment tags for rich text box --- .../UI/GUI/Common/RichTextBox.Parsing.cs | 40 +++++++++++---- .../Engine/UI/GUI/Common/RichTextBox.Tags.cs | 49 +++++++++++++++++-- Source/Engine/UI/GUI/Common/RichTextBox.cs | 9 ++++ Source/Engine/UI/GUI/TextBlockStyle.cs | 21 ++++++++ 4 files changed, 107 insertions(+), 12 deletions(-) diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs b/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs index 12ad082a4..c65b7caf0 100644 --- a/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs +++ b/Source/Engine/UI/GUI/Common/RichTextBox.Parsing.cs @@ -26,12 +26,12 @@ namespace FlaxEngine.GUI /// Current caret location for the new text blocks origin. /// public Float2 Caret; - + /// /// Index of the current line start character. /// public int LineStartCharacterIndex; - + /// /// Index of the current line start text block. /// @@ -50,12 +50,12 @@ namespace FlaxEngine.GUI { // Post-processing Control.PostProcessBlock?.Invoke(ref this, ref textBlock); - + // Add to the text blocks Control._textBlocks.Add(textBlock); } } - + /// /// The delegate for text blocks post-processing. /// @@ -68,7 +68,7 @@ namespace FlaxEngine.GUI /// [HideInEditor] public PostProcessBlockDelegate PostProcessBlock; - + /// /// The delegate for HTML tag processing. /// @@ -91,6 +91,8 @@ namespace FlaxEngine.GUI { "size", ProcessSize }, { "img", ProcessImage }, { "valign", ProcessVAlign }, + { "align", ProcessAlign }, + { "center", ProcessCenter }, }; private HtmlParser _parser = new HtmlParser(); @@ -104,7 +106,7 @@ namespace FlaxEngine.GUI ParseTextBlocks(_text, _textBlocks); return; } - + // Setup parsing _parser.Reset(_text); _styleStack.Clear(); @@ -206,7 +208,7 @@ namespace FlaxEngine.GUI context.AddTextBlock(ref textBlock); } - + // Update the caret location ref var lastLine = ref lines[lines.Length - 1]; if (lines.Length == 1) @@ -226,7 +228,7 @@ namespace FlaxEngine.GUI var lineOrigin = textBlocks[context.LineStartTextBlockIndex].Bounds.Location; var lineSize = Float2.Zero; var lineAscender = 0.0f; - for(int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++) + for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++) { ref TextBlock textBlock = ref textBlocks[i]; var textBlockSize = textBlock.Bounds.BottomRight - lineOrigin; @@ -242,10 +244,12 @@ namespace FlaxEngine.GUI } // Organize text blocks within line - for(int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++) + var horizontalAlignments = TextBlockStyle.Alignments.Baseline; + for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++) { ref TextBlock textBlock = ref textBlocks[i]; var vOffset = lineSize.Y - textBlock.Bounds.Height; + horizontalAlignments |= textBlock.Style.Alignment & TextBlockStyle.Alignments.HorizontalMask; switch (textBlock.Style.Alignment & TextBlockStyle.Alignments.VerticalMask) { case TextBlockStyle.Alignments.Baseline: @@ -279,6 +283,24 @@ namespace FlaxEngine.GUI } } } + var hOffset = Width - lineSize.X; + if ((horizontalAlignments & TextBlockStyle.Alignments.Center) == TextBlockStyle.Alignments.Center) + { + hOffset *= 0.5f; + for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++) + { + ref TextBlock textBlock = ref textBlocks[i]; + textBlock.Bounds.Location.X += hOffset; + } + } + else if ((horizontalAlignments & TextBlockStyle.Alignments.Right) == TextBlockStyle.Alignments.Right) + { + for (int i = context.LineStartTextBlockIndex; i < _textBlocks.Count; i++) + { + ref TextBlock textBlock = ref textBlocks[i]; + textBlock.Bounds.Location.X += hOffset; + } + } // Move to the next line context.LineStartCharacterIndex = lineEnd + 1; diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs b/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs index 3fd6e80ff..3840e6dc8 100644 --- a/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs +++ b/Source/Engine/UI/GUI/Common/RichTextBox.Tags.cs @@ -14,7 +14,7 @@ namespace FlaxEngine.GUI if (font) context.Caret.Y += font.Height; } - + private static void ProcessColor(ref ParsingContext context, ref HtmlTag tag) { if (tag.IsSlash) @@ -198,7 +198,7 @@ namespace FlaxEngine.GUI context.AddTextBlock(ref imageBlock); context.Caret.X += imageBlock.Bounds.Size.X; } - + private static void ProcessVAlign(ref ParsingContext context, ref HtmlTag tag) { if (tag.IsSlash) @@ -211,7 +211,7 @@ namespace FlaxEngine.GUI if (tag.Attributes.TryGetValue(string.Empty, out var valign)) { style.Alignment &= ~TextBlockStyle.Alignments.VerticalMask; - switch(valign) + switch (valign) { case "top": style.Alignment = TextBlockStyle.Alignments.Top; @@ -231,6 +231,49 @@ namespace FlaxEngine.GUI } } + private static void ProcessAlign(ref ParsingContext context, ref HtmlTag tag) + { + if (tag.IsSlash) + { + context.StyleStack.Pop(); + } + else + { + var style = context.StyleStack.Peek(); + if (tag.Attributes.TryGetValue(string.Empty, out var valign)) + { + style.Alignment &= ~TextBlockStyle.Alignments.VerticalMask; + switch (valign) + { + case "left": + style.Alignment = TextBlockStyle.Alignments.Left; + break; + case "right": + style.Alignment = TextBlockStyle.Alignments.Right; + break; + case "center": + style.Alignment = TextBlockStyle.Alignments.Center; + break; + } + } + context.StyleStack.Push(style); + } + } + + private static void ProcessCenter(ref ParsingContext context, ref HtmlTag tag) + { + if (tag.IsSlash) + { + context.StyleStack.Pop(); + } + else + { + var style = context.StyleStack.Peek(); + style.Alignment = TextBlockStyle.Alignments.Center; + context.StyleStack.Push(style); + } + } + private static Asset FindAsset(string name, System.Type type) { var ids = Content.GetAllAssetsByType(type); diff --git a/Source/Engine/UI/GUI/Common/RichTextBox.cs b/Source/Engine/UI/GUI/Common/RichTextBox.cs index af0a45eec..54522399e 100644 --- a/Source/Engine/UI/GUI/Common/RichTextBox.cs +++ b/Source/Engine/UI/GUI/Common/RichTextBox.cs @@ -50,5 +50,14 @@ namespace FlaxEngine.GUI BackgroundSelectedBrush = new SolidColorBrush(style.BackgroundSelected), }; } + + /// + protected override void OnSizeChanged() + { + base.OnSizeChanged(); + + // Refresh textblocks since thos emight depend on control size (eg. align right) + UpdateTextBlocks(); + } } } diff --git a/Source/Engine/UI/GUI/TextBlockStyle.cs b/Source/Engine/UI/GUI/TextBlockStyle.cs index a32042e0c..f6893b596 100644 --- a/Source/Engine/UI/GUI/TextBlockStyle.cs +++ b/Source/Engine/UI/GUI/TextBlockStyle.cs @@ -32,11 +32,32 @@ namespace FlaxEngine.GUI /// Bottom = 4, + /// + /// Block will be aligned to the left edge of the layout (horizontally). + /// + Left = 8, + + /// + /// Block will be aligned to center of the layout (horizontally). + /// + Center = 16, + + /// + /// Block will be aligned to the right edge of the layout (horizontally). + /// + Right = 32, + /// /// Mask with vertical alignment flags. /// [HideInEditor] VerticalMask = Top | Middle | Bottom, + + /// + /// Mask with horizontal alignment flags. + /// + [HideInEditor] + HorizontalMask = Left | Center | Right, } ///