Files
SharpIDE/src/SharpIDE.Godot/Features/CodeEditor/SharpIdeCodeEdit_Completions_InputHandling.cs
2026-01-31 15:41:51 +10:00

120 lines
4.7 KiB
C#

using Godot;
using Microsoft.CodeAnalysis.Completion;
using Microsoft.CodeAnalysis.Text;
using SharpIDE.Godot.Features.Problems;
namespace SharpIDE.Godot.Features.CodeEditor;
public partial class SharpIdeCodeEdit
{
private bool CompletionsPopupTryConsumeGuiInput(InputEvent @event)
{
var isCodeCompletionPopupOpen = _codeCompletionOptions.Length is not 0;
if (isCodeCompletionPopupOpen is false)
{
if (@event.IsActionPressed(InputStringNames.CodeEditorRequestCompletions))
{
completionTrigger = new CompletionTrigger(CompletionTriggerKind.InvokeAndCommitIfUnique);
CustomCodeCompletionRequested.InvokeParallelFireAndForget(completionTrigger!.Value, Text, GetCaretPosition());
return true;
}
}
if (isCodeCompletionPopupOpen)
{
if (@event is InputEventMouseButton { Pressed: true, ButtonIndex: MouseButton.Left or MouseButton.Right } mouseEvent)
{
var codeCompletionIndex = GetCompletionOptionAtPoint((Vector2I)mouseEvent.Position);
if (codeCompletionIndex is null)
{
// if the index is null, it means we clicked outside the completion popup, so close it
ResetCompletionPopupState();
return false;
}
// If no item is currently centered
if (_codeCompletionForceItemCenter is -1)
{
// center the current central item, as an anchor, before we update the selection
_codeCompletionForceItemCenter = _codeCompletionCurrentSelected;
}
_codeCompletionCurrentSelected = codeCompletionIndex.Value;
if (mouseEvent is { DoubleClick: true })
{
ApplySelectedCodeCompletion();
return true;
}
GD.Print($"Code completion option clicked: {codeCompletionIndex.Value}");
QueueRedraw();
return true;
}
if (@event is InputEventMouseButton { Pressed: true, ButtonIndex: MouseButton.WheelDown or MouseButton.WheelUp } scrollEvent)
{
if (_codeCompletionRect.HasPoint((Vector2I)scrollEvent.Position))
{
int scrollAmount = scrollEvent.ButtonIndex is MouseButton.WheelDown ? 1 : -1;
_codeCompletionCurrentSelected = Mathf.Clamp(
_codeCompletionCurrentSelected + scrollAmount,
0,
_codeCompletionOptions.Length - 1
);
_codeCompletionForceItemCenter = -1;
QueueRedraw();
return true;
}
}
else if (@event.IsActionPressed(InputStringNames.Backspace))
{
pendingCompletionFilterReason = CompletionFilterReason.Deletion;
return false;
}
if (@event is InputEventKey { Pressed: true, Keycode: Key.Up or Key.Down } inputEventKey)
{
var delta = inputEventKey.Keycode is Key.Up ? -1 : 1;
_codeCompletionCurrentSelected = Mathf.Clamp(
_codeCompletionCurrentSelected + delta,
0,
_codeCompletionOptions.Length - 1
);
_codeCompletionForceItemCenter = -1;
QueueRedraw();
return true;
}
if (@event is InputEventKey { Pressed: true, Keycode: Key.Escape })
{
ResetCompletionPopupState();
QueueRedraw();
return true;
}
if (@event is InputEventKey { Pressed: true, Keycode: Key.Enter or Key.Tab })
{
ApplySelectedCodeCompletion();
return true;
}
}
if (@event is InputEventKey { Pressed: true, Unicode: not 0 } keyEvent)
{
var unicodeString = char.ConvertFromUtf32((int)keyEvent.Unicode);
if (isCodeCompletionPopupOpen && keyEvent.Unicode >= 32)
{
pendingCompletionFilterReason = CompletionFilterReason.Insertion;
return false; // Let the text update happen
}
if (isCodeCompletionPopupOpen is false && _codeCompletionTriggers.Contains(unicodeString, StringComparer.OrdinalIgnoreCase))
{
_pendingCompletionTrigger = CompletionTrigger.CreateInsertionTrigger(unicodeString[0]);
return false;
}
}
return false;
}
}