146 lines
4.2 KiB
C#
146 lines
4.2 KiB
C#
using System.Runtime.InteropServices;
|
|
|
|
namespace Hawkeye.VisionBuilder.Features.ToolEditor
|
|
{
|
|
public class CodeCompletionControl : ListBox
|
|
{
|
|
private TextBox textBox;
|
|
private readonly Form _form;
|
|
|
|
[DllImport("user32.dll")]
|
|
static extern bool GetCaretPos(out Point lpPoint);
|
|
|
|
public CodeCompletionControl(TextBox textBox)
|
|
{
|
|
this.textBox = textBox;
|
|
|
|
this.Visible = false;
|
|
this.Location = new Point(0, 0);
|
|
this.Width = 200;
|
|
_form = new Form();
|
|
_form.Width = this.Width;
|
|
_form.Height = 200;
|
|
|
|
_form.Controls.Add(this);
|
|
this.Dock = DockStyle.Fill;
|
|
_form.FormBorderStyle = FormBorderStyle.None;
|
|
_form.ShowInTaskbar = false;
|
|
_form.TopMost = true;
|
|
_form.StartPosition = FormStartPosition.Manual;
|
|
|
|
textBox.TextChanged += TextBox_TextChanged;
|
|
textBox.KeyDown += TextBox_KeyDown;
|
|
|
|
this.KeyDown += CodeCompletionControl_KeyDown;
|
|
}
|
|
|
|
private void CodeCompletionControl_KeyDown(object? sender, KeyEventArgs e)
|
|
{
|
|
if (e.KeyCode == Keys.Up)
|
|
{
|
|
if (this.SelectedIndex == 0)
|
|
{
|
|
textBox.Focus();
|
|
}
|
|
}
|
|
|
|
else if (e.KeyCode == Keys.Enter && this.Visible && this.SelectedIndex != -1)
|
|
{
|
|
Accept();
|
|
}else if (e.KeyCode == Keys.Escape)
|
|
{
|
|
this.Visible = false;
|
|
_form.Hide();
|
|
}
|
|
}
|
|
|
|
private void Cancel()
|
|
{
|
|
this.Visible = false;
|
|
_form.Hide();
|
|
}
|
|
|
|
private void Accept()
|
|
{
|
|
var start = textBox.Text.LastIndexOf(".");
|
|
if (start == -1)
|
|
{
|
|
textBox.Text = this.SelectedItem.ToString();
|
|
textBox.SelectionStart = textBox.Text.Length;
|
|
this.Visible = false;
|
|
_form.Hide();
|
|
return;
|
|
}
|
|
textBox.Text = textBox.Text.Substring(0,start+1);
|
|
textBox.Text += this.SelectedItem.ToString();
|
|
textBox.SelectionStart = textBox.Text.Length;
|
|
this.Visible = false;
|
|
_form.Hide();
|
|
}
|
|
|
|
private void TextBox_TextChanged(object sender, EventArgs e)
|
|
{
|
|
if(int.TryParse(textBox.Text,out _))return;
|
|
if (GetCaretPos(out Point point))
|
|
{
|
|
// Convert screen position to client position
|
|
|
|
|
|
// Set location of this control
|
|
_form.Location = textBox.PointToScreen(new Point(point.X, point.Y + textBox.Size.Height)); ; // Add offset to avoid overlap with text cursor
|
|
}
|
|
|
|
// Update suggestions
|
|
var suggestions = GetSuggestions(textBox.Text);
|
|
this.Items.Clear();
|
|
this.Items.AddRange(suggestions.ToArray());
|
|
if (this.Items.Count > 0)
|
|
{
|
|
_form.Show();
|
|
textBox.Focus();
|
|
}
|
|
else
|
|
{
|
|
_form.Hide();
|
|
}
|
|
this.Visible = this.Items.Count > 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void TextBox_KeyDown(object sender, KeyEventArgs e)
|
|
{
|
|
if (e.KeyCode == Keys.Down && this.Visible)
|
|
{
|
|
this.Focus();
|
|
this.SelectedIndex = 0;
|
|
}
|
|
else if (e.KeyCode == Keys.Escape)
|
|
{
|
|
Cancel();
|
|
}
|
|
else if (e.KeyCode == Keys.Enter && this.Visible && this.SelectedIndex != -1)
|
|
{
|
|
Accept();
|
|
}
|
|
}
|
|
|
|
public delegate void NeedSugestionsDelegate(string input, List<string> suggestions);
|
|
public event NeedSugestionsDelegate NeedSugestions =delegate{ };
|
|
|
|
private List<string> GetSuggestions(string input)
|
|
{
|
|
var source = new List<string>();
|
|
|
|
NeedSugestions(input, source);
|
|
if (source.Count == 0)
|
|
{
|
|
Visible = false;
|
|
_form.Hide();
|
|
}
|
|
return source.ToList();
|
|
}
|
|
}
|
|
}
|