aboutsummaryrefslogtreecommitdiffstats
path: root/Software/Visual_Studio/Tango.Logging/ConsoleWindow.xaml.cs
blob: e95284cf86001c7bfeef49d0df4e0542099b6827 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100<
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
{
    /// <summary>
    /// Represents a debugging (write-only) console emulator.
    /// </summary>
    public partial class ConsoleWindow : Window
    {
        private bool _closing;
        private SolidColorBrush _currentBrush;

        /// <summary>
        /// Initializes a new instance of the <see cref="ConsoleWindow"/> class.
        /// </summary>
        public ConsoleWindow()
        {
            InitializeComponent();

            txtLog.Document.LineHeight = 15;
            txtLog.Document.PageWidth = 4000;
            _currentBrush = Brushes.Gainsboro;

            AppendLog("--------------------- Twine Console Emulator ---------------------" + Environment.NewLine + Environment.NewLine);

            Closing += ConsoleWindow_Closing;
        }

        /// <summary>
        /// Handles the Closing event of the ConsoleWindow control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.CancelEventArgs"/> instance containing the event data.</param>
        private void ConsoleWindow_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            _closing = true;
        }

        /// <summary>
        /// Appends the specified .
        /// </summary>
        /// <param name="obj">The object.</param>
        public void WriteLine(object obj)
        {
            AppendLog(obj.ToString() + Environment.NewLine);
        }

        /// <summary>
        /// Writes the specified object.
        /// </summary>
        /// <param name="obj">The object.</param>
        public void Write(object obj)
        {
            AppendLog(obj.ToString());
        }

        /// <summary>
        /// Sets the console foreground color.
        /// </summary>
        /// <param name="color">The color.</param>
        public void SetColor(ConsoleColor 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);
            });
        }

        /// <summary>
        /// Opens the console.
        /// </summary>
        public void Open()
        {
            Show();
        }

        /// <summary>
        /// Closes the console.
        /// </summary>
        public new void Close()
        {
            Close();
        }

        /// <summary>
        /// Waits until user closes the window.
        /// </summary>
        /// <returns></returns>
        public async Task WaitForUserClose()
        {
            WriteLine("");
            WriteLine("Close this window to exit...");

            await Task.Factory.StartNew(() =>
            {
                while (!_closing)
                {
                    Thread.Sleep(10);
                }
            });
        }

        /// <summary>
        /// Invokes the UI.
        /// </summary>
        /// <param name="action">The action.</param>
        private void InvokeUI(Action action)
        {
            Dispatcher.Invoke(action);
            DoEvents();
        }

        /// <summary>
        /// Forces the next rendering thread frame.
        /// </summary>
        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 { }));
        }
    }
}