diff --git a/Source/Editor/Windows/DebugLogWindow.cs b/Source/Editor/Windows/DebugLogWindow.cs
index 64cb29f88..5183b7454 100644
--- a/Source/Editor/Windows/DebugLogWindow.cs
+++ b/Source/Editor/Windows/DebugLogWindow.cs
@@ -13,7 +13,6 @@ using FlaxEditor.Options;
using FlaxEngine;
using FlaxEngine.Assertions;
using FlaxEngine.GUI;
-using FlaxEngine.Utilities;
using Object = FlaxEngine.Object;
namespace FlaxEditor.Windows
@@ -70,67 +69,6 @@ namespace FlaxEditor.Windows
private class LogEntry : Control
{
- ///
- /// Text block with only color available, no other styling.
- ///
- private struct TextColorBlock
- {
- ///
- /// Color of this block.
- ///
- public Color TextColor;
-
- ///
- /// Range of the text.
- ///
- public TextRange Range;
-
- ///
- /// The text location and size.
- ///
- public Rectangle Bounds;
- }
-
- ///
- /// Rich text parsing context.
- ///
- private struct ColorParseContext
- {
- ///
- /// LogEntry control.
- ///
- public LogEntry Control;
-
- ///
- /// Caret location for the next text block.
- ///
- public Float2 Caret;
-
- ///
- /// Current parsed color.
- ///
- public Color CurrentColor;
-
- ///
- /// Default color, for reverting color on closing tags.
- ///
- public Color DefaultColor;
-
- ///
- /// Current text font for text processing.
- ///
- public Font TextFont;
-
- ///
- /// Add text block to the control.
- ///
- /// The text block to add.
- public void AddBlock(ref TextColorBlock block)
- {
- Control._textBlocks.Add(block);
- }
- }
-
private bool _isRightMouseDown;
///
@@ -139,12 +77,13 @@ namespace FlaxEditor.Windows
public const float DefaultHeight = 32.0f;
private DebugLogWindow _window;
+ private RichTextBox _richTextBox;
public LogGroup Group;
public LogEntryDescription Desc;
public SpriteHandle Icon;
public int LogCount = 1;
- private readonly List _textBlocks = new List();
+ private Color Color => Group == LogGroup.Error ? _window._colorError : (Group == LogGroup.Warning ? _window._colorWarning : _window._colorInfo);
public LogEntry(DebugLogWindow window, ref LogEntryDescription desc)
: base(0, 0, 120, DefaultHeight)
@@ -171,123 +110,21 @@ namespace FlaxEditor.Windows
break;
}
- // Color parsing
- var style = Style.Current;
- var color = Group == LogGroup.Error ? _window._colorError : (Group == LogGroup.Warning ? _window._colorWarning : _window._colorInfo);
-
- HtmlParser parser = new();
-
- parser.Reset(Desc.Title);
-
- var context = new ColorParseContext
+ // Use Rich Text Box to display title if it contains any HTML tags
+ if (desc.Title.Contains('<') && desc.Title.Contains('>'))
{
- Control = this,
- Caret = Float2.Zero,
- CurrentColor = color,
- DefaultColor = color,
- TextFont = style.FontMedium,
- };
-
- int pointerPos = 0;
-
- while (parser.ParseNext(out var tag))
- {
- if (tag.Name.ToLower() == "color")
+ _richTextBox = new RichTextBox
{
- ProcessTextBlock(ref context, pointerPos, tag.StartPosition);
-
- pointerPos = tag.EndPosition;
-
- ProcessColorTag(ref context, ref tag);
- }
- }
-
- // Processing leftover text
- ProcessTextBlock(ref context, pointerPos, Desc.Title.Length);
- }
-
- ///
- /// Processing the text block within given range and adding it to the list.
- ///
- /// The parsing context.
- /// Start of the range.(Character index)
- /// End of the range.(Character index)
- private void ProcessTextBlock(ref ColorParseContext context, int startPos, int endPos)
- {
- // Text block preset
- var textBlock = new TextColorBlock()
- {
- TextColor = context.CurrentColor,
- Range = new TextRange(startPos, endPos),
- Bounds = new Rectangle(context.Caret, Float2.Zero)
- };
-
- // Processing the text with selected font. (Handle newlines, text offsets)
- var lines = context.TextFont.ProcessText(Desc.Title, ref textBlock.Range);
-
- if (lines == null || lines.Length == 0)
- {
- return;
- }
- for (int i = 0; i < lines.Length; i++)
- {
- ref var line = ref lines[i];
- textBlock.Range = new TextRange
- {
- StartIndex = startPos + line.FirstCharIndex,
- EndIndex = startPos + line.LastCharIndex + 1
+ ClipText = false,
+ HasBorder = false,
+ BackgroundColor = Color.Transparent,
+ Text = desc.Title,
};
-
- // Move to the next line
- if (i != 0)
+ if (_window._colorDebugLogText)
{
- context.Caret.Y += line.Size.Y;
- textBlock.Bounds.X = 0;
- textBlock.Bounds.Y += line.Size.Y;
- }
-
- textBlock.Bounds.X += line.Location.X;
- textBlock.Bounds.Size = line.Size;
- context.AddBlock(ref textBlock);
- }
-
- // Caret location for the next text block
- var lastLine = lines[lines.Length - 1];
- if (lines.Length == 1)
- {
- context.Caret.X += lastLine.Size.X;
- }
- else
- {
- context.Caret.X = lastLine.Size.X;
- }
- }
-
- ///
- /// Parse color info from the tag and handle closing tags.
- ///
- /// The parsing context.
- /// Tag to process.
- private static void ProcessColorTag(ref ColorParseContext context, ref HtmlTag tag)
- {
- // Closing tag
- if (tag.IsSlash)
- {
- context.CurrentColor = context.DefaultColor;
- }
- else
- {
- // Parse color
- if (tag.Attributes.TryGetValue(string.Empty, out string colorText))
- {
- if (Color.TryParse(colorText, out Color colorVal))
- {
- context.CurrentColor = colorVal;
- }
- }
- else
- {
- context.CurrentColor = context.DefaultColor;
+ var style = _richTextBox.TextStyle;
+ style.Color = Color;
+ _richTextBox.TextStyle = style;
}
}
}
@@ -300,12 +137,10 @@ namespace FlaxEditor.Windows
///
public override void Draw()
{
- base.Draw();
-
- // Cache data
var style = Style.Current;
var index = IndexInParent;
var clientRect = new Rectangle(Float2.Zero, Size);
+ var color = Color;
// Background
if (_window._selected == this)
@@ -320,37 +155,44 @@ namespace FlaxEditor.Windows
else if (index % 2 == 0)
Render2D.FillRectangle(clientRect, style.Background * 0.9f);
- var color = Group == LogGroup.Error ? _window._colorError : (Group == LogGroup.Warning ? _window._colorWarning : _window._colorInfo);
-
// Icon
Render2D.DrawSprite(Icon, new Rectangle(8, 0, 32, 32), color);
// Title
- var textLocation = new Float2(43, 2);
+ var textRect = new Rectangle(43, 2, clientRect.Width - 40, clientRect.Height - 10);
Render2D.PushClip(ref clientRect);
bool coloredText = _window._colorDebugLogText;
-
- // Render text blocks with their colors
- for (int i = 0; i < _textBlocks.Count; i++)
+ if (_richTextBox != null)
{
- TextColorBlock block = _textBlocks[i];
- Render2D.DrawText(style.FontMedium, Desc.Title, ref block.Range,
- coloredText ? block.TextColor : style.Foreground, textLocation + block.Bounds.Location);
+ Render2D.PushTransform(Matrix3x3.Translation2D(textRect.Location));
+ _richTextBox.DrawSelf();
+ Render2D.PopTransform();
+ }
+ else
+ {
+ Render2D.DrawText(style.FontMedium, Desc.Title, textRect, coloredText ? color : style.Foreground);
}
// Adding log counter for collapsed logs
if (LogCount > 1)
{
- Float2 numberLocation = textLocation;
- if (_textBlocks.Count > 0)
+ Float2 logCountPos = Float2.Zero;
+ if (_richTextBox != null)
{
- TextColorBlock block = _textBlocks[_textBlocks.Count - 1];
- numberLocation += block.Bounds.Location;
- numberLocation.X += block.Bounds.Size.X;
+ var blocks = _richTextBox.TextBlocks;
+ if (blocks.Count != 0)
+ {
+ var block = blocks[^1];
+ logCountPos = new Float2(block.Bounds.Right, block.Bounds.Top);
+ }
}
-
- Render2D.DrawText(style.FontMedium, $" ({LogCount})", color, numberLocation);
+ else
+ {
+ logCountPos.X = style.FontMedium.MeasureText(Desc.Title).X;
+ }
+ Render2D.DrawText(style.FontMedium, $" ({LogCount})", color, textRect.Location + logCountPos);
}
+
Render2D.PopClip();
}
@@ -489,6 +331,18 @@ namespace FlaxEditor.Windows
base.OnMouseLeave();
}
+
+ ///
+ public override void OnDestroy()
+ {
+ if (_richTextBox != null)
+ {
+ _richTextBox.OnDestroy();
+ _richTextBox = null;
+ }
+
+ base.OnDestroy();
+ }
}
private readonly SplitPanel _split;
diff --git a/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs b/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
index 97e1d88a5..b83a89943 100644
--- a/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
+++ b/Source/Engine/UI/GUI/Common/RichTextBoxBase.cs
@@ -29,6 +29,11 @@ namespace FlaxEngine.GUI
[HideInEditor]
public ParseTextBlocksDelegate ParseTextBlocks;
+ ///
+ /// Gets the list of parsed text blocks.
+ ///
+ public List TextBlocks => _textBlocks;
+
///
/// Initializes a new instance of the class.
///