using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; 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.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; using System.Windows.Threading; namespace Tango.Logging { /// /// Represents a debugging (write-only) console emulator. /// public partial class ConsoleWindow : Window { private bool _closing; private SolidColorBrush _currentBrush; private ConsoleColor _current_color; /// /// Initializes a new instance of the class. /// public ConsoleWindow() { InitializeComponent(); txtLog.Document.LineHeight = 12; txtLog.Document.PageWidth = 4000; _currentBrush = Brushes.Gainsboro; AppendLog("--------------------- Twine Console Emulator ---------------------" + Environment.NewLine + Environment.NewLine); Closing += ConsoleWindow_Closing; } /// /// Handles the Closing event of the ConsoleWindow control. /// /// The source of the event. /// The instance containing the event data. private void ConsoleWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e) { _closing = true; } /// /// Appends the specified . /// /// The object. public void WriteLine(object obj) { AppendLog(obj.ToString() + Environment.NewLine); } /// /// Writes the specified object. /// /// The object. public void Write(object obj) { AppendLog(obj.ToString()); } /// /// Sets the console foreground color. /// /// The color. public void SetColor(ConsoleColor color) { if (_current_color != color) { _current_color = color; InvokeUI(() => _currentBrush = new SolidColorBrush((Color)ColorConverter.ConvertFromString(color.ToString()))); } } private void AppendLog(String log) { InvokeUI(() => { TextRange tr = new TextRange(txtLog.Document.ContentEnd, txtLog.Document.ContentEnd); tr.Text = log; tr.ApplyPropertyValue(TextElement.ForegroundProperty, _currentBrush); Rect r = txtLog.Document.ContentEnd.GetCharacterRect(LogicalDirection.Forward); txtLog.ScrollToVerticalOffset(r.Y); }); } /// /// Opens the console. /// public void Open() { Show(); } /// /// Closes the console. /// public new void Close() { Close(); } /// /// Waits until user closes the window. /// /// public async Task WaitForUserClose() { WriteLine(""); WriteLine("Close this window to exit..."); await Task.Factory.StartNew(() => { while (!_closing) { Thread.Sleep(10); } }); } /// /// Invokes the UI. /// /// The action. private void InvokeUI(Action action) { Dispatcher.Invoke(action); DoEvents(); } /// /// Forces the next rendering thread frame. /// private void DoEvents() { if (Application.Current == null) //Using this to enable processing outside a WPF application. { new Application { ShutdownMode = ShutdownMode.OnExplicitShutdown }; } Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate { })); } } }