mirror of
https://github.com/icsharpcode/ILSpy.git
synced 2026-10-12 02:15:58 +00:00
Fix live line number margin toggle
AvaloniaEdit inserts the line number margin before ILSpy's bookmark gutter and can render it before its cached font size is initialized. Keep the gutter order stable after live toggles and prepare the margin before the first render. Assisted-by: OpenCode:openai/gpt-5.5:OpenCode
This commit is contained in:
@@ -17,9 +17,11 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Headless;
|
||||
using Avalonia.Headless.NUnit;
|
||||
|
||||
using AvaloniaEdit.Editing;
|
||||
@@ -75,4 +77,37 @@ public class MarginCursorTests
|
||||
$"the {margin.GetType().Name} is a click target, so it must show the arrow rather than the text I-beam");
|
||||
}
|
||||
}
|
||||
|
||||
[AvaloniaTest]
|
||||
public async Task Toggling_Line_Numbers_On_Live_Keeps_Gutter_Order_And_Positive_Font_Size()
|
||||
{
|
||||
var (window, vm) = await TestHarness.BootAsync(1);
|
||||
var settings = AppComposition.Current.GetExport<SettingsService>().DisplaySettings;
|
||||
settings.ShowLineNumbers = false;
|
||||
|
||||
var coreLibName = typeof(object).Assembly.GetName().Name!;
|
||||
var objectNode = vm.AssemblyTreeModel.FindNode<TypeTreeNode>(coreLibName, "System", "System.Object");
|
||||
vm.AssemblyTreeModel.SelectNode(objectNode);
|
||||
await vm.DockWorkspace.WaitForDecompiledTextAsync();
|
||||
var view = await window.WaitForComponent<DecompilerTextView>();
|
||||
|
||||
settings.ShowLineNumbers = true;
|
||||
var margins = view.Editor.TextArea.LeftMargins;
|
||||
var lineNumberMargin = margins.OfType<LineNumberMargin>()
|
||||
.Should().ContainSingle("line numbers should render after being toggled on live").Which;
|
||||
margins.IndexOf(margins.OfType<BookmarkMargin>().Single())
|
||||
.Should().Be(margins.IndexOf(lineNumberMargin) - 1,
|
||||
"the bookmark gutter must stay left of line numbers when line numbers are toggled on live");
|
||||
GetLineNumberMarginEmSize(lineNumberMargin).Should().BeGreaterThan(0);
|
||||
|
||||
window.UpdateLayout();
|
||||
AvaloniaHeadlessPlatform.ForceRenderTimerTick();
|
||||
}
|
||||
|
||||
static double GetLineNumberMarginEmSize(LineNumberMargin margin)
|
||||
{
|
||||
return (double)typeof(LineNumberMargin)
|
||||
.GetProperty("EmSize", BindingFlags.Instance | BindingFlags.NonPublic)!
|
||||
.GetValue(margin)!;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
@@ -100,6 +101,17 @@ namespace ICSharpCode.ILSpy.TextView
|
||||
FontFamily = new FontFamily(displaySettings.SelectedFont);
|
||||
if (displaySettings.SelectedFontSize > 0)
|
||||
FontSize = EditorZoom.EffectiveFontSize(displaySettings);
|
||||
PrepareLineNumberMarginsForRender();
|
||||
}
|
||||
|
||||
internal void PrepareLineNumberMarginsForRender()
|
||||
{
|
||||
foreach (var margin in TextArea.LeftMargins.OfType<LineNumberMargin>())
|
||||
{
|
||||
margin.SetValue(TextBlock.FontFamilyProperty, FontFamily);
|
||||
margin.SetValue(TextBlock.FontSizeProperty, FontSize);
|
||||
margin.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
|
||||
}
|
||||
}
|
||||
|
||||
static DisplaySettings? TryGetDisplaySettings()
|
||||
|
||||
@@ -34,6 +34,7 @@ using Avalonia.Threading;
|
||||
using Avalonia.VisualTree;
|
||||
|
||||
using AvaloniaEdit.Document;
|
||||
using AvaloniaEdit.Editing;
|
||||
using AvaloniaEdit.Folding;
|
||||
using AvaloniaEdit.Highlighting;
|
||||
|
||||
@@ -179,6 +180,41 @@ namespace ICSharpCode.ILSpy.TextView
|
||||
margin.Cursor = ArrowCursor;
|
||||
}
|
||||
|
||||
void KeepBookmarkMarginBeforeLineNumbers()
|
||||
{
|
||||
if (bookmarkMargin == null)
|
||||
return;
|
||||
|
||||
var margins = Editor.TextArea.LeftMargins;
|
||||
var lineNumberIndex = -1;
|
||||
for (var i = 0; i < margins.Count; i++)
|
||||
{
|
||||
if (margins[i] is LineNumberMargin)
|
||||
{
|
||||
lineNumberIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
var bookmarkIndex = margins.IndexOf(bookmarkMargin);
|
||||
if (lineNumberIndex < 0 || bookmarkIndex < 0 || bookmarkIndex < lineNumberIndex)
|
||||
return;
|
||||
|
||||
var lineNumberMargin = margins[lineNumberIndex];
|
||||
Control? separator = null;
|
||||
if (lineNumberIndex + 1 < margins.Count
|
||||
&& margins[lineNumberIndex + 1] is global::Avalonia.Controls.Shapes.Line)
|
||||
separator = margins[lineNumberIndex + 1];
|
||||
|
||||
if (separator != null)
|
||||
margins.Remove(separator);
|
||||
margins.Remove(lineNumberMargin);
|
||||
|
||||
bookmarkIndex = margins.IndexOf(bookmarkMargin);
|
||||
margins.Insert(bookmarkIndex + 1, lineNumberMargin);
|
||||
if (separator != null)
|
||||
margins.Insert(bookmarkIndex + 2, separator);
|
||||
}
|
||||
|
||||
void OnPreviewKeyDownForOmnibar(object? sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key == Key.L && e.KeyModifiers == KeyModifiers.Control && Omnibar.IsVisible)
|
||||
@@ -649,6 +685,11 @@ namespace ICSharpCode.ILSpy.TextView
|
||||
{
|
||||
case nameof(DisplaySettings.ShowLineNumbers):
|
||||
Editor.ShowLineNumbers = s.ShowLineNumbers;
|
||||
if (Editor.ShowLineNumbers)
|
||||
{
|
||||
KeepBookmarkMarginBeforeLineNumbers();
|
||||
Editor.PrepareLineNumberMarginsForRender();
|
||||
}
|
||||
break;
|
||||
case nameof(DisplaySettings.EnableWordWrap):
|
||||
Editor.WordWrap = s.EnableWordWrap;
|
||||
|
||||
Reference in New Issue
Block a user