AvaloniaUI / AvaloniaEdit

Avalonia-based text editor (port of AvalonEdit)
MIT License
764 stars 148 forks source link

Tab Column Misalignment #412

Open ajkfds opened 6 months ago

ajkfds commented 6 months ago

When inserting characters before a tab, the tab’s column position does not align as expected.

image

The expected behavior was as shown in the image below.

image

AvaloniaEdit 11.0.6 + .net 6.0 + Windows 11 Home

mgarstenauer commented 6 months ago

This seems to be a bug in Avalonia. You can reproduce this bug using a simple TextBox.

<TextBox Text="&#x09;a&#x09;a&#x0D;a&#x09;a&#x09;a"/>

Avalonia: image

WPF: image

I am going to file an Avalonia issue.

ajkfds commented 6 months ago

I have found a temporary workaround for the bug until it is fixed.

  1. Set indentation size =1 and ShowTabs = true
            _textEditor.Options.IndentationSize = 1;
            _textEditor.Options.ShowTabs = true;
  2. Fix Rendering/SingleCharacterElementGenerator.cs to accept TabGlyphRun Size cahnge.

Change TabTextElement class from private to internal. Add TabSize variable.

internal sealed class TabTextElement : VisualLineElemen
    {
        public int TabSize = 0;
        ...
    }

Fix Size override of TabGlyphRun.

private sealed class TabGlyphRun : DrawableTextRun
{
    ...
    //public override Size Size => default;

   public override Size Size
    {
        get
        {
            return new Size(_element.Text.WidthIncludingTrailingWhitespace* (_element.TabSize-1), 0);
        }
    }
    ...
}
  1. Fix Rendering/VisualLine.cs to Set TabSize parameter of TabTextElement
        private void CalculateOffsets()
        {
            var visualOffset = 0;
            var textOffset = 0;
            int tabOffset= 0;
            foreach (var element in _elements)
            {
                element.VisualColumn = visualOffset;
                element.RelativeTextOffset = textOffset;
                visualOffset += element.VisualLength;
                textOffset += element.DocumentLength;
                if(element is SingleCharacterElementGenerator.TabTextElement)
                {
                    (element as SingleCharacterElementGenerator.TabTextElement).TabSize = 4-(tabOffset%4);
                    tabOffset = 0;
                }
                else
                {
                    tabOffset = tabOffset + element.DocumentLength;
                }
            }
            VisualLength = visualOffset;
            Debug.Assert(textOffset == LastDocumentLine.EndOffset - FirstDocumentLine.Offset);
        }