diff --git a/src/OneWare.Essentials/EditorExtensions/ExtendedTextEditor.cs b/src/OneWare.Essentials/EditorExtensions/ExtendedTextEditor.cs index 8c59cc1..e0e1c18 100644 --- a/src/OneWare.Essentials/EditorExtensions/ExtendedTextEditor.cs +++ b/src/OneWare.Essentials/EditorExtensions/ExtendedTextEditor.cs @@ -25,7 +25,7 @@ public class ExtendedTextEditor : TextEditor // private ElementGenerator ElementGenerator { get; } public FoldingManager? FoldingManager { get; private set; } - public InlayHintRenderer InlayHintRenderer { get; } + public InlayHintGenerator InlayHintGenerator { get; } public ExtendedTextEditor() { @@ -51,7 +51,7 @@ public ExtendedTextEditor() WordRenderer = new WordHighlightRenderer(TextArea.TextView); MarkerService = new TextMarkerService(Document); ModificationService = new TextModificationService(TextArea.TextView); - InlayHintRenderer = new InlayHintRenderer(this); + InlayHintGenerator = new InlayHintGenerator(this); TextArea.TextView.BackgroundRenderers.Add(BracketRenderer); TextArea.TextView.BackgroundRenderers.Add(LineRenderer); @@ -61,7 +61,7 @@ public ExtendedTextEditor() TextArea.TextView.LineTransformers.Add(ModificationService); //TextArea.TextView.ElementGenerators.Add(ElementGenerator); - TextArea.TextView.ElementGenerators.Add(InlayHintRenderer); + TextArea.TextView.ElementGenerators.Add(InlayHintGenerator); } protected override void OnDocumentChanged(DocumentChangedEventArgs e) diff --git a/src/OneWare.Essentials/EditorExtensions/InlayHintRenderer.cs b/src/OneWare.Essentials/EditorExtensions/InlayHintGenerator.cs similarity index 50% rename from src/OneWare.Essentials/EditorExtensions/InlayHintRenderer.cs rename to src/OneWare.Essentials/EditorExtensions/InlayHintGenerator.cs index c6c2836..91b44eb 100644 --- a/src/OneWare.Essentials/EditorExtensions/InlayHintRenderer.cs +++ b/src/OneWare.Essentials/EditorExtensions/InlayHintGenerator.cs @@ -11,21 +11,24 @@ namespace OneWare.Essentials.EditorExtensions; public class InlayHint { - public TextLocation Location { get; init; } - - //Will be used internally public int Offset { get; set; } = -1; public string Text { get; init; } = string.Empty; } -public class InlayHintRenderer : VisualLineElementGenerator +internal class InlayHintWithAnchor +{ + public InlayHint Hint { get; init; } + public TextAnchor Anchor { get; set; } + public Control Control { get; set; } +} + +public class InlayHintGenerator : VisualLineElementGenerator { private readonly TextEditor _editor; - private readonly List _hints = []; - private readonly List _hintControls = []; + private readonly List _hints = []; - public InlayHintRenderer(TextEditor editor) + public InlayHintGenerator(TextEditor editor) { _editor = editor; } @@ -33,16 +36,15 @@ public InlayHintRenderer(TextEditor editor) public void SetInlineHints(IEnumerable hints) { _hints.Clear(); - _hintControls.Clear(); - _hints.AddRange(hints); - var foreground = Application.Current!.FindResource(Application.Current!.RequestedThemeVariant, "ThemeForegroundLowBrush") as IBrush; var background = Application.Current!.FindResource(Application.Current!.RequestedThemeVariant, "ThemeBackgroundBrush") as IBrush; - foreach (var hint in _hints) + _hints.AddRange(hints.Select(x => new InlayHintWithAnchor() { - _hintControls.Add(new Border() + Hint = x, + Anchor = _editor.Document.CreateAnchor(x.Offset), + Control = new Border() { Margin = new Thickness(1, 0, 5, 0), Background = background, @@ -50,13 +52,13 @@ public void SetInlineHints(IEnumerable hints) VerticalAlignment = VerticalAlignment.Center, Child = new TextBlock() { - Text = hint.Text, + Text = x.Text, Foreground = foreground, Margin = new Thickness(2,0), VerticalAlignment = VerticalAlignment.Center } - }); - } + } + })); _editor.TextArea.TextView.Redraw(); } @@ -66,53 +68,25 @@ public void ClearInlineHints() _hints.Clear(); _editor.TextArea.TextView.Redraw(); } - - private static InlayHint? FindNextPosition(List positions, TextLocation startPosition) - { - int left = 0; - int right = positions.Count - 1; - - while (left <= right) - { - int mid = left + (right - left) / 2; - int comparison = positions[mid].Location.CompareTo(startPosition); - - if (comparison >= 0) - { - if (mid == 0 || positions[mid - 1].Location.CompareTo(startPosition) < 0) - { - return positions[mid]; - } - right = mid - 1; - } - else - { - left = mid + 1; - } - } - - return null; - } public override int GetFirstInterestedOffset(int startOffset) { - var position = _editor.Document.GetLocation(startOffset); - var next = FindNextPosition(_hints, position); + var index = _hints.BinarySearch(startOffset, (a, b) => a.CompareTo(b.Anchor.Offset));; - if(next == null) - return -1; + if (index < 0) + index = ~index; + if (index < _hints.Count) + { + return _hints[index].Anchor.Offset; + } - next.Offset = _editor.Document.GetOffset(next.Location); - return next.Offset; + return -1; } public override VisualLineElement? ConstructElement(int offset) { - var index = _hints.FindIndex(hint => hint.Offset == offset); + var index = _hints.BinarySearch(offset, (a, b) => a.CompareTo(b.Anchor.Offset)); - if (index < 0) return null; - - var control = _hintControls[index]; - return new InlineObjectElement(0, control); + return index < 0 ? null : new InlineObjectElement(0, _hints[index].Control); } } \ No newline at end of file diff --git a/src/OneWare.Essentials/EditorExtensions/InlayHintLineText.cs b/src/OneWare.Essentials/EditorExtensions/InlayHintLineText.cs deleted file mode 100644 index 91211b0..0000000 --- a/src/OneWare.Essentials/EditorExtensions/InlayHintLineText.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System.Diagnostics; -using Avalonia.Media; -using Avalonia.Media.TextFormatting; -using AvaloniaEdit.Rendering; - -namespace OneWare.Essentials.EditorExtensions; - -public class InlayHintLineText : VisualLineText -{ - /// - /// Creates a visual line text element with the specified length. - /// It uses the and its - /// to find the actual text string. - /// - public InlayHintLineText(VisualLine parentVisualLine, int length) : base(parentVisualLine, length) - { - - } - - /// - public override TextRun CreateTextRun(int startVisualColumn, ITextRunConstructionContext context) - { - this.TextRunProperties.SetForegroundBrush(context.TextView.LinkTextForegroundBrush); - this.TextRunProperties.SetBackgroundBrush(context.TextView.LinkTextBackgroundBrush); - - if (context.TextView.LinkTextUnderline) - this.TextRunProperties.SetTextDecorations(TextDecorations.Underline); - return base.CreateTextRun(startVisualColumn, context); - } -} \ No newline at end of file diff --git a/src/OneWare.Essentials/LanguageService/TypeAssistanceLanguageService.cs b/src/OneWare.Essentials/LanguageService/TypeAssistanceLanguageService.cs index 620148f..c87ac58 100644 --- a/src/OneWare.Essentials/LanguageService/TypeAssistanceLanguageService.cs +++ b/src/OneWare.Essentials/LanguageService/TypeAssistanceLanguageService.cs @@ -155,7 +155,7 @@ protected override void OnAssistanceDeactivated() base.OnAssistanceDeactivated(); Editor.Editor.ModificationService.ClearModification("caretHighlight"); Editor.Editor.ModificationService.ClearModification("semanticTokens"); - Editor.Editor.InlayHintRenderer.ClearInlineHints(); + Editor.Editor.InlayHintGenerator.ClearInlineHints(); } protected virtual void DocumentChanged(object? sender, DocumentChangeEventArgs e) @@ -598,15 +598,15 @@ protected virtual async Task UpdateInlayHintsAsync() if (inlayHintContainer is not null) { - Editor.Editor.InlayHintRenderer.SetInlineHints(inlayHintContainer.Select(x => new InlayHint() + Editor.Editor.InlayHintGenerator.SetInlineHints(inlayHintContainer.Select(x => new InlayHint() { - Location = new TextLocation(x.Position.Line + 1, x.Position.Character + 1), + Offset = Editor.CurrentDocument.GetOffset(x.Position.Line+1, x.Position.Character+1), Text = x.Label.ToString() })); } else { - Editor.Editor.InlayHintRenderer.ClearInlineHints(); + Editor.Editor.InlayHintGenerator.ClearInlineHints(); } }