using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; namespace codelanguage { /// /// Interactive code completion dropdown UI with filtering, selection, and documentation preview. /// Displays completion items with icons, types, and inline documentation. /// public partial class CodeCompletionDropdown : UserControl { public ObservableCollection Items { get; } = new(); public event EventHandler ItemSelected; public event EventHandler CompletionCancelled; private CompletionItemUI _selectedItem; private int _selectedIndex = -1; public CodeCompletionDropdown() { InitializeComponent(); CompletionListBox.ItemsSource = Items; CompletionListBox.SelectionChanged += CompletionListBox_SelectionChanged; FilterTextBox.TextChanged += FilterTextBox_TextChanged; PreviewKeyDown += CodeCompletionDropdown_PreviewKeyDown; FilterTextBox.PreviewKeyDown += FilterTextBox_PreviewKeyDown; FilterTextBox.Focus(); } private void CodeCompletionDropdown_PreviewKeyDown(object sender, KeyEventArgs e) { HandlePreviewKey(e); } private void FilterTextBox_PreviewKeyDown(object sender, KeyEventArgs e) { HandlePreviewKey(e); } private void HandlePreviewKey(KeyEventArgs e) { switch (e.Key) { case Key.Up: SelectItem(_selectedIndex - 1); e.Handled = true; break; case Key.Down: SelectItem(_selectedIndex + 1); e.Handled = true; break; case Key.Enter: case Key.Tab: if (_selectedItem != null) { ItemSelected?.Invoke(this, _selectedItem); Hide(); } e.Handled = true; break; case Key.Escape: Hide(); e.Handled = true; break; } } public void SelectNext() => SelectItem(_selectedIndex + 1); public void SelectPrevious() => SelectItem(_selectedIndex - 1); public void ShowCompletions(List items, int x, int y) { Items.Clear(); _selectedIndex = -1; foreach (var item in items) { Items.Add(new CompletionItemUI(item)); } // Position dropdown if (Parent is Canvas canvas) { Canvas.SetLeft(this, x); Canvas.SetTop(this, y); } Visibility = Visibility.Visible; FilterTextBox.Clear(); FilterTextBox.Focus(); if (Items.Count > 0) SelectItem(0); } public void Hide() { Visibility = Visibility.Collapsed; CompletionCancelled?.Invoke(this, EventArgs.Empty); } private void SelectItem(int index) { if (index < 0 || index >= Items.Count) return; _selectedIndex = index; CompletionListBox.SelectedIndex = index; CompletionListBox.ScrollIntoView(Items[index]); _selectedItem = Items[index]; UpdateDocumentation(_selectedItem); } private void UpdateDocumentation(CompletionItemUI item) { Documentation.Text = !string.IsNullOrEmpty(item.Documentation) ? item.Documentation : $"Kind: {item.Kind}\nNo additional documentation available."; } private void CompletionListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { if (CompletionListBox.SelectedItem is CompletionItemUI item) { _selectedItem = item; UpdateDocumentation(item); } } private void CompletionListBox_KeyDown(object sender, KeyEventArgs e) { switch (e.Key) { case Key.Up: SelectItem(_selectedIndex - 1); e.Handled = true; break; case Key.Down: SelectItem(_selectedIndex + 1); e.Handled = true; break; case Key.Enter: case Key.Tab: if (_selectedItem != null) { ItemSelected?.Invoke(this, _selectedItem); Hide(); } e.Handled = true; break; case Key.Escape: Hide(); e.Handled = true; break; } } private void FilterTextBox_TextChanged(object sender, TextChangedEventArgs e) { string filter = FilterTextBox.Text.ToLower(); // Filter items if (string.IsNullOrEmpty(filter)) { foreach (var item in Items) item.IsVisible = true; } else { foreach (var item in Items) { item.IsVisible = item.Label.ToLower().Contains(filter) || item.Documentation?.ToLower().Contains(filter) == true; } } // Re-select first visible for (int i = 0; i < Items.Count; i++) { if (Items[i].IsVisible) { SelectItem(i); return; } } } private void CompletionItem_MouseDoubleClick(object sender, MouseButtonEventArgs e) { if (sender is FrameworkElement elem && elem.DataContext is CompletionItemUI item) { ItemSelected?.Invoke(this, item); Hide(); e.Handled = true; } } public CompletionItemUI GetSelectedItem() => _selectedItem; } /// UI wrapper for CompletionItem with visual styling and filtering support public class CompletionItemUI : CompletionItem { private bool _isVisible = true; public CompletionItemUI(CompletionItem item) : base(item.Label, item.InsertText, item.Documentation, item.Kind, item.SortOrder) { } public bool IsVisible { get => _isVisible; set => _isVisible = value; } public string IconChar => Kind switch { CompletionItemKind.Variable => "🔤", CompletionItemKind.Procedure => "⚙", CompletionItemKind.Type => "📦", CompletionItemKind.Keyword => "🔑", CompletionItemKind.BuiltinProc => "⭐", CompletionItemKind.Field => "📝", CompletionItemKind.Parameter => "📥", CompletionItemKind.Snippet => "📋", _ => "•" }; public Brush ItemBackground { get { return Kind switch { CompletionItemKind.Keyword => VisualThemeManager.GetBrush("Keyword"), CompletionItemKind.BuiltinProc => VisualThemeManager.GetBrush("BuiltinProc"), CompletionItemKind.Type => VisualThemeManager.GetBrush("Type"), _ => VisualThemeManager.GetBrush("SurfaceLight") }; } } } }