/Overthere/Overthere/ConsoleViewer.cs
C# | 334 lines | 277 code | 55 blank | 2 comment | 21 complexity | c82ca3061fca1505d1e554e134389802 MD5 | raw file
- using System;
- using System.Reflection;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Documents;
- using System.Windows.Input;
- using System.Windows.Media;
- using System.Windows.Threading;
- using Overthere.Interfaces;
- using System.IO;
- using System.Linq;
- using System.Text.RegularExpressions;
- using System.Collections.Generic;
- using System.Windows.Controls.Primitives;
-
- namespace Overthere
- {
- public partial class ConsoleViewer : FlowDocumentScrollViewer, IDisposable
- {
- Paragraph _output;
- Paragraph _input;
- Run _promptText;
- TextBox _commandPrompt;
- InlineUIContainer _promptContainer;
-
- OverthereShell _shell;
- Intellisense _intellisense;
-
- public ConsoleSession Session { get; private set; }
-
- public string PromptText
- {
- get
- {
- return _promptText.Text;
- }
- set
- {
- _promptText.Text = value + ">";
- }
- }
-
- public Intellisense Intellisense
- {
- get { return _intellisense; }
- }
-
- public string CurrentCommand
- {
- get
- {
- return _commandPrompt.Text;
- }
- set
- {
- _commandPrompt.Text = value;
- _commandPrompt.CaretIndex = _commandPrompt.Text.Length;
- _commandPrompt.Focus();
- }
- }
-
- public IConsole Console
- {
- get { return Session.Console; }
- }
-
- public TextBox CommandPrompt
- {
- get { return _commandPrompt; }
- }
-
- private ScrollViewer _scrollViewer;
- public ScrollViewer ScrollViewer
- {
- get
- {
- if (_scrollViewer == null)
- {
- PropertyInfo propertyInfo = typeof(FlowDocumentScrollViewer).GetProperty("ScrollViewer", BindingFlags.NonPublic | BindingFlags.Instance);
- _scrollViewer = propertyInfo.GetValue(this, new object[0]) as ScrollViewer;
- }
-
- return _scrollViewer;
- }
- }
-
- public ConsoleViewer()
- {
- _output = new Paragraph()
- {
- Margin = new Thickness(0.0),
- Padding = new Thickness(0.0),
- };
-
- _input = new Paragraph()
- {
- Margin = new Thickness(0.0),
- Padding = new Thickness(0.0),
- };
-
- _commandPrompt = new TextBox()
- {
- AcceptsReturn = false,
- AcceptsTab = false,
- Padding = new Thickness(0.0),
- Margin = new Thickness(0.0),
- BorderThickness = new Thickness(0.0),
- HorizontalAlignment = HorizontalAlignment.Left,
- VerticalScrollBarVisibility = ScrollBarVisibility.Hidden,
- TextWrapping = TextWrapping.Wrap,
- };
-
- _promptText = new Run();
- PromptText = string.Empty;
-
- _promptContainer = new InlineUIContainer(_commandPrompt)
- {
- BaselineAlignment = BaselineAlignment.Top
- };
-
- _intellisense = new Intellisense(this);
- }
-
- public void Dispose()
- {
- if (_intellisense != null)
- {
- _intellisense.Dispose();
- _intellisense = null;
- }
-
- GC.SuppressFinalize(this);
- }
-
- public override void EndInit()
- {
- base.EndInit();
-
- Document.Blocks.Add(_output);
- Document.Blocks.Add(_input);
- _input.Inlines.Add(_promptText);
- _input.Inlines.Add(_promptContainer);
-
- ResizePrompt(this.MaxWidth);
- _commandPrompt.Focus();
-
- BindingOperations.SetBinding(Document, FlowDocument.FontFamilyProperty, new Binding("FontFamily") { Source = this });
- BindingOperations.SetBinding(Document, FlowDocument.FontSizeProperty, new Binding("FontSize") { Source = this });
- BindingOperations.SetBinding(Document, FlowDocument.BackgroundProperty, new Binding("Background") { Source = this });
- BindingOperations.SetBinding(Document, FlowDocument.ForegroundProperty, new Binding("Foreground") { Source = this });
-
- BindingOperations.SetBinding(_commandPrompt, RichTextBox.FontFamilyProperty, new Binding("FontFamily") { Source = this });
- BindingOperations.SetBinding(_commandPrompt, RichTextBox.FontSizeProperty, new Binding("FontSize") { Source = this });
- BindingOperations.SetBinding(_commandPrompt, RichTextBox.BackgroundProperty, new Binding("Background") { Source = this });
- BindingOperations.SetBinding(_commandPrompt, RichTextBox.ForegroundProperty, new Binding("Foreground") { Source = this });
- }
-
- private void ResizePrompt(double totalWidth)
- {
- _commandPrompt.MaxWidth = Math.Max(0, totalWidth - PromptText.Length * 15);
- }
-
- protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
- {
- base.OnRenderSizeChanged(sizeInfo);
-
- ResizePrompt(sizeInfo.NewSize.Width);
- }
-
- protected override void OnPreviewKeyDown(System.Windows.Input.KeyEventArgs e)
- {
- base.OnPreviewKeyDown(e);
-
- _shell.KeyPreview(e);
-
- if (KeyboardEx.IsControlDown)
- {
- switch (e.Key)
- {
- case Key.C: // Copy
- return;
- case Key.D: // Ctrl+C
- Console.SendKey(Key.C, ModifierKeys.Control);
- break;
- case Key.Cancel: // Ctrl_Break
- Console.SendKey(Key.Cancel, ModifierKeys.Control);
- break;
- }
- }
-
- // Control/Shift/Alt
- if (e.Key.IsModifier())
- {
- return;
- }
-
- // Keyboard selection
- if (KeyboardEx.IsShiftDown && e.Key.IsArrowKey())
- {
- return;
- }
-
- if (KeyboardEx.IsControlDown && e.Key == Key.Tab)
- {
- return;
- }
-
- if (!_intellisense.IsOpen)
- {
- switch (e.Key)
- {
- case Key.Up:
- this.CurrentCommand = Session.BackHistory();
- break;
- case Key.Down:
- this.CurrentCommand = Session.ForwardHistory();
- break;
- }
- }
-
- this.CommandPrompt.Focus();
- }
-
- protected override void OnPreviewTextInput(System.Windows.Input.TextCompositionEventArgs e)
- {
- base.OnPreviewTextInput(e);
-
- _commandPrompt.Focus();
- }
-
- public void WriteOutput(string output)
- {
- this.WriteOutput(output, Brushes.White);
- }
-
- public void WriteError(string output)
- {
- this.WriteOutput(output, Brushes.Red);
- }
-
- void WriteOutput(string text, Brush brush)
- {
- _output.Dispatcher.Invoke(
- DispatcherPriority.Background,
- new Action<string, Brush>(AppendOutput),
- text,
- brush);
- }
-
- void AppendOutput(string text, Brush brush)
- {
- new Run(text, _output.ContentEnd) { Foreground = brush };
-
- ScrollViewer scrollViewer = this.ScrollViewer;
- if (scrollViewer.VerticalOffset == scrollViewer.ExtentHeight - scrollViewer.ViewportHeight
- || scrollViewer.ExtentHeight < scrollViewer.ViewportHeight)
- {
- scrollViewer.ScrollToBottom();
- }
- }
-
- #region Console Interaction
- public void Bind(OverthereShell shell, ConsoleSession session)
- {
- _shell = shell;
- this.Session = session;
- this.PromptText = session.Name;
-
- session.Console.Output += this.WriteOutput;
- session.Console.Error += this.WriteError;
-
- _commandPrompt.KeyDown += this.CommandPrompt_KeyDown;
- }
-
- public void Unbind()
- {
- if (this.Session == null)
- return;
-
- this.Session.Console.Output -= this.WriteOutput;
- this.Session.Console.Error -= this.WriteError;
-
- _commandPrompt.KeyDown -= this.CommandPrompt_KeyDown;
-
- this.PromptText = string.Empty;
- this.Session = null;
- _shell = null;
- }
-
- private void CommandPrompt_KeyDown(object sender, KeyEventArgs e)
- {
- _shell.KeyPressed(e);
-
- switch (e.Key)
- {
- case Key.Return:
- SubmitCommand();
- e.Handled = true;
- break;
- case Key.Escape:
- this.CurrentCommand = string.Empty;
- e.Handled = true;
- break;
- case Key.Tab:
- int newCaretIndex;
- this.CurrentCommand = this.Session.AutoComplete(this.CurrentCommand,
- this.CommandPrompt.CaretIndex,
- KeyboardEx.IsShiftDown,
- out newCaretIndex);
-
- this.CommandPrompt.CaretIndex = newCaretIndex;
- this.CommandPrompt.Focus();
- e.Handled = true;
- break;
- }
- }
-
- public void SubmitCommand()
- {
- string command = this.CurrentCommand;
- this.Session.AddHistory(command);
-
- if (_shell.HandleCommand(command))
- {
- this.Console.Input(command + Environment.NewLine);
- }
-
- this.CurrentCommand = string.Empty;
- }
-
- #endregion Console Interaction
- }
- }