/Overthere/Overthere/Intellisense.cs
C# | 320 lines | 298 code | 22 blank | 0 comment | 27 complexity | e467e742c83535b6b451e79cdca7f941 MD5 | raw file
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Windows.Controls.Primitives;
- using System.Windows.Controls;
- using System.Windows.Input;
- using System.IO;
- using System.Windows.Data;
- using System.Windows.Media;
- using System.Windows;
- using System.Threading;
- using System.Windows.Threading;
-
- namespace Overthere
- {
- public class Intellisense : IDisposable
- {
- Popup _popup;
- ListBox _list;
-
- string _currentDirectory;
- int _backslashLocation;
- PathQuery _lastQuery;
-
- Thread _fetchThread;
-
- ConsoleViewer _viewer;
-
- IEnumerable<DirectoryInfo> _directories;
- IEnumerable<FileInfo> _files;
-
- string[] _promptCommands = new string[]
- {
- "cd ",
- };
-
- public bool IsOpen
- {
- get { return _popup.IsOpen; }
- set { _popup.IsOpen = value; }
- }
-
- public Intellisense(ConsoleViewer viewer)
- {
- _viewer = viewer;
-
- _popup = new Popup()
- {
- Placement = PlacementMode.Right,
- StaysOpen = false,
- IsOpen = false,
- PlacementTarget = _viewer.CommandPrompt,
- AllowsTransparency = true,
- MinWidth = 50,
- MaxWidth = 500,
- MaxHeight = 500,
- };
-
- _list = new ListBox();
- _popup.Child = new Border()
- {
- Child = _list,
- Background = Brushes.LightGray,
- CornerRadius = new CornerRadius(8),
- Padding = new Thickness(3.0),
- };
-
- _viewer.CommandPrompt.PreviewKeyDown += Prompt_PreviewKeyDown;
- _viewer.CommandPrompt.KeyUp += Prompt_KeyUp;
-
- _fetchDataFlag = new AutoResetEvent(false);
-
- _fetchThread = new Thread(new ThreadStart(UpdateThreadLoop));
- _fetchThread.Start();
- }
-
- public void Dispose()
- {
- if (_fetchThread != null)
- {
- _fetchThread.Abort();
- _fetchThread = null;
- }
-
- GC.SuppressFinalize(this);
- }
-
- private void Prompt_PreviewKeyDown(object sender, KeyEventArgs e)
- {
- if (this.IsOpen)
- {
- switch (e.Key)
- {
- case Key.Space:
- if (KeyboardEx.IsControlDown)
- {
- e.Handled = true;
- }
- break;
- case Key.Tab:
- e.Handled = true;
- break;
- case Key.Escape:
- e.Handled = true;
- break;
- case Key.Oem5:
- e.Handled = true;
- break;
- case Key.Up:
- e.Handled = true;
- break;
- case Key.Down:
- e.Handled = true;
- break;
- }
- }
- }
-
- private void Prompt_KeyUp(object sender, KeyEventArgs e)
- {
- if (!this.IsOpen)
- {
- switch (e.Key)
- {
- case Key.Oem5:
- DisplayPopup();
- break;
- case Key.Space:
- if (KeyboardEx.IsControlDown
- || _promptCommands.Contains(_viewer.CurrentCommand))
- {
- DisplayPopup();
- }
- break;
- }
- }
- else
- {
- switch (e.Key)
- {
- case Key.Oem5:
- SubmitSelection(true);
- break;
- case Key.Back:
- PathQuery query = PathQuery.Parse(_viewer.CurrentCommand, _backslashLocation, _currentDirectory);
- if (string.IsNullOrEmpty(query.RelativePath) && string.IsNullOrEmpty(query.PartialPath))
- {
- _popup.IsOpen = false;
- }
- else if (query.RelativePath != _lastQuery.RelativePath)
- {
- DisplayPopup();
- }
- else
- {
- UpdateListBox(query);
- }
- break;
- case Key.Escape:
- _popup.IsOpen = false;
- e.Handled = true;
- break;
- case Key.Tab:
- SubmitSelection(false);
- e.Handled = true;
- break;
- case Key.Enter:
- _popup.IsOpen = false;
- e.Handled = true;
- break;
- case Key.Up:
- if (_list.SelectedIndex > 0)
- _list.SelectedIndex--;
- break;
- case Key.Down:
- if (_list.SelectedIndex + 1 < _list.Items.Count)
- _list.SelectedIndex++;
- break;
- default:
- query = PathQuery.Parse(_viewer.CurrentCommand, _backslashLocation, _currentDirectory);
- UpdateListBox(query);
- break;
- }
- }
- }
-
- private void SubmitSelection(bool slashSubmit)
- {
- PathQuery query = PathQuery.Parse(_viewer.CurrentCommand, _backslashLocation, _currentDirectory);
-
- if (_list.SelectedIndex == -1 && _list.Items.Count > 0)
- _list.SelectedIndex = 0;
-
- bool openAgain = false;
- if (_list.SelectedItem != null && !(slashSubmit && query.FullPath == "\\" && string.IsNullOrEmpty(query.PartialPath)))
- {
- Label label = (Label)((StackPanel)_list.SelectedItem).Children[1];
- query.Query.Value = Path.Combine(query.RelativePath, label.Content.ToString());
-
- if (slashSubmit && label.Content is DirectoryInfo)
- {
- query.Query.Value += "\\";
-
- openAgain = true;
- }
-
- _viewer.CurrentCommand = Token.Join(query.Tokens);
- }
- else if (slashSubmit)
- {
- query.Query.Value += "\\";
- openAgain = true;
- _viewer.CurrentCommand = Token.Join(query.Tokens);
- }
-
- _popup.IsOpen = false;
-
- if (openAgain)
- {
- DisplayPopup();
- }
- }
-
- private void DisplayPopup()
- {
- _popup.IsOpen = false;
- _backslashLocation = _viewer.CommandPrompt.CaretIndex;
- _currentDirectory = _viewer.Console.GetCurrentDirectory();
- if (string.IsNullOrEmpty(_currentDirectory))
- return;
-
- PathQuery query = PathQuery.Parse(_viewer.CurrentCommand, _backslashLocation, _currentDirectory);
-
- _lastQuery = query;
-
- lock (this)
- {
- _directories = new DirectoryInfo[0];
- _files = new FileInfo[0];
- }
-
- _fetchDataFlag.Set();
-
- UpdateListBox(query);
- _popup.IsOpen = true;
- _popup.VerticalOffset = _viewer.CommandPrompt.ViewportHeight;
- }
-
- private void UpdateListBox(PathQuery query)
- {
- string filter = query.PartialPath;
- _list.Items.Clear();
-
- lock (this)
- {
- foreach (DirectoryInfo dir in _directories.Where(d => d.Name.StartsWith(filter, StringComparison.OrdinalIgnoreCase)))
- {
- StackPanel panel = new StackPanel() { Orientation = Orientation.Horizontal, Margin = new Thickness(0.0) };
- panel.Children.Add(new Image() { Source = FolderIcon, Width = 16 });
- panel.Children.Add(new Label() { Content = dir, Padding = new Thickness(0.0) });
- _list.Items.Add(panel);
- }
-
- foreach (FileInfo file in _files.Where(f => f.Name.StartsWith(filter, StringComparison.OrdinalIgnoreCase)))
- {
- StackPanel panel = new StackPanel() { Orientation = Orientation.Horizontal, Margin = new Thickness(0.0) };
- panel.Children.Add(new Image() { Width = 16 });
- panel.Children.Add(new Label() { Content = file, Padding = new Thickness(0.0) });
- _list.Items.Add(panel);
- }
- }
- }
-
- AutoResetEvent _fetchDataFlag;
-
- private void UpdateThreadLoop()
- {
- try
- {
- while (true)
- {
- _fetchDataFlag.WaitOne();
-
- lock (this)
- {
- _directories = new DirectoryInfo[0];
- _files = new FileInfo[0];
- }
-
- IEnumerable<DirectoryInfo> directories = _viewer.Console.GetDirectories(_lastQuery.FullPath);
- IEnumerable<FileInfo> files = _viewer.Console.GetFiles(_lastQuery.FullPath);
-
- lock (this)
- {
- _directories = directories;
- _files = files;
- }
-
- _list.Dispatcher.BeginInvoke(DispatcherPriority.Render, (Action)delegate() { UpdateListBox(_lastQuery); });
- }
- }
- catch (ThreadAbortException) { }
- }
-
- private ImageSource _folderIcon;
- private ImageSource FolderIcon
- {
- get
- {
- if (_folderIcon == null)
- {
- _folderIcon = (ImageSource)_viewer.FindResource("folderIcon");
- }
-
- return _folderIcon;
- }
- }
- }
- }