2014-11-13 09:43:39 +00:00
|
|
|
|
#region ================== Namespaces
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Drawing;
|
2015-08-16 23:42:57 +00:00
|
|
|
|
using System.Globalization;
|
2014-11-13 09:43:39 +00:00
|
|
|
|
using System.Windows.Forms;
|
|
|
|
|
|
2015-09-16 12:10:43 +00:00
|
|
|
|
#if PROFILE
|
|
|
|
|
using JetBrains.Profiler.Core.Api;
|
|
|
|
|
#endif
|
|
|
|
|
|
2014-11-13 09:43:39 +00:00
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
namespace CodeImp.DoomBuilder
|
|
|
|
|
{
|
|
|
|
|
#region ================== Enums
|
|
|
|
|
|
|
|
|
|
[Flags]
|
|
|
|
|
public enum DebugMessageType
|
|
|
|
|
{
|
2014-12-03 23:15:26 +00:00
|
|
|
|
LOG = 1,
|
|
|
|
|
INFO = 2,
|
|
|
|
|
WARNING = 4,
|
|
|
|
|
ERROR = 8,
|
|
|
|
|
SPECIAL = 16,
|
2014-11-13 09:43:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
public partial class DebugConsole : UserControl
|
|
|
|
|
{
|
|
|
|
|
#region ================== Variables
|
|
|
|
|
|
2014-11-25 11:52:01 +00:00
|
|
|
|
private const int MAX_MESSAGES = 1024;
|
|
|
|
|
private static readonly List<KeyValuePair<DebugMessageType, string>> messages = new List<KeyValuePair<DebugMessageType, string>>(MAX_MESSAGES);
|
2014-11-13 09:43:39 +00:00
|
|
|
|
|
|
|
|
|
//Colors
|
|
|
|
|
private readonly Dictionary<DebugMessageType, Color> textcolors;
|
|
|
|
|
private readonly Dictionary<DebugMessageType, string> textheaders;
|
|
|
|
|
|
2014-11-25 11:52:01 +00:00
|
|
|
|
private DebugMessageType filters;
|
2014-11-13 09:43:39 +00:00
|
|
|
|
private static long starttime = -1;
|
|
|
|
|
private static DebugConsole me;
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Properties
|
|
|
|
|
|
|
|
|
|
public bool AlwaysOnTop { get { return alwaysontop.Checked; } }
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Constructor
|
|
|
|
|
|
|
|
|
|
public DebugConsole()
|
|
|
|
|
{
|
|
|
|
|
InitializeComponent();
|
|
|
|
|
me = this;
|
|
|
|
|
|
|
|
|
|
// Setup filters
|
|
|
|
|
foreach (ToolStripMenuItem item in filterselector.DropDownItems)
|
|
|
|
|
{
|
|
|
|
|
UpdateFilters(item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Setup colors
|
|
|
|
|
textcolors = new Dictionary<DebugMessageType, Color> {
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{ DebugMessageType.LOG, SystemColors.WindowText },
|
|
|
|
|
{ DebugMessageType.INFO, Color.DarkGreen },
|
|
|
|
|
{ DebugMessageType.WARNING, Color.DarkOrange },
|
|
|
|
|
{ DebugMessageType.ERROR, Color.DarkRed },
|
|
|
|
|
{ DebugMessageType.SPECIAL, Color.DarkMagenta }
|
2014-11-13 09:43:39 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Setup headers
|
|
|
|
|
textheaders = new Dictionary<DebugMessageType, string> {
|
2014-12-03 23:15:26 +00:00
|
|
|
|
{ DebugMessageType.LOG, string.Empty},
|
|
|
|
|
{ DebugMessageType.INFO, string.Empty},
|
|
|
|
|
{ DebugMessageType.WARNING, "Warning: "},
|
|
|
|
|
{ DebugMessageType.ERROR, "ERROR: "},
|
|
|
|
|
{ DebugMessageType.SPECIAL, string.Empty}
|
2014-11-13 09:43:39 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Word wrap?
|
|
|
|
|
wordwrap.Checked = console.WordWrap;
|
|
|
|
|
|
|
|
|
|
// Pending messages?
|
|
|
|
|
if (messages.Count > 0) UpdateMessages();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Methods
|
|
|
|
|
|
|
|
|
|
public static void Write(string text)
|
|
|
|
|
{
|
2014-12-03 23:15:26 +00:00
|
|
|
|
Write(DebugMessageType.INFO, text);
|
2014-11-13 09:43:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void WriteLine(string text)
|
|
|
|
|
{
|
2014-12-03 23:15:26 +00:00
|
|
|
|
Write(DebugMessageType.INFO, text + Environment.NewLine);
|
2014-11-13 09:43:39 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Write(DebugMessageType type, string text)
|
|
|
|
|
{
|
|
|
|
|
if(me != null && me.InvokeRequired)
|
|
|
|
|
{
|
|
|
|
|
me.Invoke(new Action<DebugMessageType, string>(Write), new object[] { type, text });
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2014-11-25 11:52:01 +00:00
|
|
|
|
if (messages.Count + 1 > MAX_MESSAGES) lock (messages) { messages.RemoveAt(0); }
|
2014-11-13 09:43:39 +00:00
|
|
|
|
messages.Add(new KeyValuePair<DebugMessageType, string>(type, text));
|
|
|
|
|
if(me != null && (me.filters & type) == type)
|
|
|
|
|
{
|
|
|
|
|
me.AddMessage(type, text, true);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void WriteLine(DebugMessageType type, string text)
|
|
|
|
|
{
|
|
|
|
|
Write(type, text + Environment.NewLine);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void Clear()
|
|
|
|
|
{
|
|
|
|
|
if (me != null && me.InvokeRequired)
|
|
|
|
|
{
|
|
|
|
|
me.Invoke(new Action(Clear));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
if (me != null) me.console.Clear();
|
|
|
|
|
messages.Clear();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void StartTimer()
|
|
|
|
|
{
|
|
|
|
|
starttime = SlimDX.Configuration.Timer.ElapsedMilliseconds;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void StopTimer(string message)
|
|
|
|
|
{
|
2015-08-16 23:42:57 +00:00
|
|
|
|
if(starttime == -1) throw new InvalidOperationException("DebugConsole.StartTimer() must be called before DebugConsole.StopTimer()!");
|
|
|
|
|
|
|
|
|
|
long duration = SlimDX.Configuration.Timer.ElapsedMilliseconds - starttime;
|
|
|
|
|
|
|
|
|
|
if (message.Contains("%"))
|
|
|
|
|
message = message.Replace("%", duration.ToString(CultureInfo.InvariantCulture));
|
|
|
|
|
else
|
|
|
|
|
message = message.TrimEnd() + " " + duration + " ms.";
|
|
|
|
|
|
|
|
|
|
WriteLine(DebugMessageType.SPECIAL, message);
|
2014-11-13 09:43:39 +00:00
|
|
|
|
|
|
|
|
|
starttime = -1;
|
|
|
|
|
}
|
|
|
|
|
|
2015-09-16 12:10:43 +00:00
|
|
|
|
public static void StartProfiler()
|
|
|
|
|
{
|
|
|
|
|
#if PROFILE
|
|
|
|
|
if(PerformanceProfiler.IsActive)
|
|
|
|
|
{
|
|
|
|
|
WriteLine(DebugMessageType.SPECIAL, "Starting the Profiler...");
|
|
|
|
|
PerformanceProfiler.Begin();
|
|
|
|
|
PerformanceProfiler.Start();
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
WriteLine(DebugMessageType.SPECIAL, "Unable to start the Profiler...");
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
WriteLine(DebugMessageType.SPECIAL, "Unable to start the Profiler: incorrect build configuration selected!");
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static void StopProfiler() { StopProfiler(true); }
|
|
|
|
|
public static void StopProfiler(bool savesnapshot)
|
|
|
|
|
{
|
|
|
|
|
#if PROFILE
|
|
|
|
|
if(PerformanceProfiler.IsActive)
|
|
|
|
|
{
|
|
|
|
|
PerformanceProfiler.Stop();
|
|
|
|
|
if(savesnapshot) PerformanceProfiler.EndSave();
|
|
|
|
|
else PerformanceProfiler.EndDrop();
|
|
|
|
|
|
|
|
|
|
WriteLine(DebugMessageType.SPECIAL, "Profiler Stopped...");
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
WriteLine(DebugMessageType.SPECIAL, "Unable to stop the Profiler...");
|
|
|
|
|
}
|
|
|
|
|
#else
|
|
|
|
|
WriteLine(DebugMessageType.SPECIAL, "Unable to stop the Profiler: incorrect build configuration selected!");
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-13 09:43:39 +00:00
|
|
|
|
private void AddMessage(DebugMessageType type, string text, bool scroll)
|
|
|
|
|
{
|
|
|
|
|
text = textheaders[type] + text;
|
|
|
|
|
console.SelectionStart = console.TextLength;
|
|
|
|
|
console.SelectionColor = textcolors[type];
|
|
|
|
|
console.AppendText(text);
|
|
|
|
|
if(scroll && autoscroll.Checked) console.ScrollToCaret();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateFilters(ToolStripMenuItem item)
|
|
|
|
|
{
|
|
|
|
|
DebugMessageType flag = (DebugMessageType)(int)item.Tag;
|
|
|
|
|
if(item.Checked)
|
|
|
|
|
{
|
|
|
|
|
filters |= flag;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
filters &= ~flag;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void UpdateMessages()
|
|
|
|
|
{
|
|
|
|
|
console.Clear();
|
|
|
|
|
|
|
|
|
|
console.SuspendLayout();
|
|
|
|
|
foreach (KeyValuePair<DebugMessageType, string> pair in messages)
|
|
|
|
|
{
|
|
|
|
|
if((filters & pair.Key) == pair.Key && CheckTextFilter(pair.Value, searchbox.Text))
|
|
|
|
|
{
|
|
|
|
|
AddMessage(pair.Key, pair.Value, false);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
console.ResumeLayout();
|
|
|
|
|
console.ScrollToCaret();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Should we display this message?
|
2014-12-03 23:15:26 +00:00
|
|
|
|
private static bool CheckTextFilter(string text, string filter)
|
2014-11-13 09:43:39 +00:00
|
|
|
|
{
|
|
|
|
|
if (string.IsNullOrEmpty(filter) || filter.Length < 3) return true;
|
|
|
|
|
return text.ToUpperInvariant().Contains(filter.ToUpperInvariant());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Events
|
|
|
|
|
|
|
|
|
|
private void clearall_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void filters_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
UpdateFilters(sender as ToolStripMenuItem);
|
|
|
|
|
UpdateMessages();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void wordwrap_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
console.WordWrap = wordwrap.Checked;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
#region ================== Search events
|
|
|
|
|
|
|
|
|
|
private void searchclear_Click(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
searchbox.Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void searchbox_TextChanged(object sender, EventArgs e)
|
|
|
|
|
{
|
|
|
|
|
if(string.IsNullOrEmpty(searchbox.Text) || searchbox.Text.Length > 2) UpdateMessages();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|