How to show a pop-up when hovering a word? #379
-
|
Hello, I would like to show a pop-up when hovering certain words. Consider that my TextEditor has the following content: When hovering "banana" with my mouse, I would like to show some text in a pop-up. How can I do this? |
Beta Was this translation helpful? Give feedback.
Answered by
alexandrehtrb
Aug 6, 2025
Replies: 1 comment
-
|
Found a solution and came back here :-) Based on this Stack Overflow answer for AvalonEdit. 1) Add a Flyout in your TextEditor (View, XAML)<AvaloniaEdit:TextEditor
x:Name="myTextEditor"
Grid.Column="0"
Grid.Row="1"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Margin="12,12,12,0"
IsReadOnly="False"
Document="{Binding MyTextDocument, Mode=TwoWay}">
<FlyoutBase.AttachedFlyout>
<Flyout ShowMode="TransientWithDismissOnPointerMoveAway">
<SelectableTextBlock x:Name="stbPopupText"/>
</Flyout>
</FlyoutBase.AttachedFlyout>
</AvaloniaEdit:TextEditor>2) Add code-behind for text editor (View, C#)var textEditor = this.FindControl<TextEditor>("myTextEditor")!;
textEditor.PointerHover += OnTextEditorPointerHover(sender, e);
textEditor.PointerHoverStopped += OnTextEditorPointerHoverStopped;
/* ... */
private static void OnTextEditorPointerHover(object? sender, PointerEventArgs e)
{
var te = ((TextEditor)sender!);
var pos = te.GetPositionFromPoint(e.GetPosition(te));
if (pos != null && pos.HasValue)
{
var line = te.Document.GetLineByNumber(pos.Value.Line);
string lineText = te.Document.GetText(line.Offset, line.Length);
int pointerIndex = pos.Value.Column - 1;
string? hoveringWord = GetPointerHoverWord(lineText, pointerIndex);
if (hoveringWord != null)
{
var flyout = (Flyout)(FlyoutBase.GetAttachedFlyout(te)!);
var flyoutStb = te.FindControl<SelectableTextBlock>("stbPopupText")!;
flyoutStb.Text = hoveringWord;
flyout.ShowAt(te, showAtPointer: true);
e.Handled = true;
}
}
}
private static void OnTextEditorPointerHoverStopped(object? sender, PointerEventArgs e)
{
var flyout = FlyoutBase.GetAttachedFlyout((TextEditor)sender!)!;
if (flyout.IsOpen)
{
flyout!.Hide();
}
}3) Get hovered word logic (C#)The logic below gets a hovered word delimited by whitespace, start or end of line. Logicpublic static string? GetPointerHoverWord(string? lineText, int pointerIndex)
{
int startIndex = -1, endIndex = -1;
if (string.IsNullOrWhiteSpace(lineText))
{
return null;
}
if (pointerIndex >= lineText.Length)
{
return null; // pointer over end-of-line ('\n')
}
if (lineText[pointerIndex] == ' ')
{
return null;
}
if (pointerIndex == 0)
{
startIndex = 0;
}
if (pointerIndex == (lineText.Length - 1))
{
endIndex = lineText.Length - 1;
}
for (int i = pointerIndex; i >= 0; i--)
{
if (lineText[i] == ' ')
{
startIndex = i + 1;
break;
}
if (i == 0)
{
startIndex = 0;
break;
}
}
if (startIndex == -1)
{
return null;
}
for (int i = pointerIndex; i <= lineText.Length - 1; i++)
{
if (lineText[i] == ' ')
{
endIndex = i - 1;
break;
}
if (i == lineText.Length - 1)
{
endIndex = lineText.Length - 1;
break;
}
}
if (endIndex == -1)
{
return null;
}
if (startIndex == endIndex)
{
return null;
}
string hoveringVar = lineText[startIndex..(endIndex + 1)];
return hoveringVar;
}Unit tests[Theory]
[InlineData("banana", "banana", 0)]
[InlineData("banana", "banana", 1)]
[InlineData("banana", "banana", 2)]
[InlineData("banana", "banana", 3)]
[InlineData("banana", "banana", 4)]
[InlineData("banana", "banana", 5)]
[InlineData(null, "banana", 6)]
[InlineData(null, " banana", 0)]
[InlineData("banana", " banana", 1)]
[InlineData("banana", " banana", 2)]
[InlineData("banana", " banana", 3)]
[InlineData("banana", " banana", 4)]
[InlineData("banana", " banana", 5)]
[InlineData("banana", " banana", 6)]
[InlineData(null, " banana", 7)]
[InlineData("banana", "banana ", 0)]
[InlineData("banana", "banana ", 1)]
[InlineData("banana", "banana ", 2)]
[InlineData("banana", "banana ", 3)]
[InlineData("banana", "banana ", 4)]
[InlineData("banana", "banana ", 5)]
[InlineData(null, "banana ", 6)]
[InlineData(null, "banana ", 7)]
[InlineData(null, " papaya banana ", 0)]
[InlineData("papaya", " papaya banana ", 1)]
[InlineData("papaya", " papaya banana ", 2)]
[InlineData("papaya", " papaya banana ", 3)]
[InlineData("papaya", " papaya banana ", 4)]
[InlineData("papaya", " papaya banana ", 5)]
[InlineData("papaya", " papaya banana ", 6)]
[InlineData(null, " papaya banana ", 7)]
[InlineData(null, " papaya banana ", 8)]
[InlineData(null, " papaya banana ", 9)]
[InlineData("banana", " papaya banana ", 10)]
[InlineData("banana", " papaya banana ", 11)]
[InlineData("banana", " papaya banana ", 12)]
[InlineData("banana", " papaya banana ", 13)]
[InlineData("banana", " papaya banana ", 14)]
[InlineData("banana", " papaya banana ", 15)]
[InlineData(null, " papaya banana ", 16)]
[InlineData(null, " papaya banana ", 17)]
public static void Should_detect_hovered_word_correctly(string? expectedVariable, string lineText, int pointerIndex) =>
Assert.Equal(expectedVariable, GetPointerHoverWord(lineText, pointerIndex)); |
Beta Was this translation helpful? Give feedback.
0 replies
Answer selected by
alexandrehtrb
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Found a solution and came back here :-)
Based on this Stack Overflow answer for AvalonEdit.
1) Add a Flyout in your TextEditor (View, XAML)
2) Add code-behind for text editor (View, C#)