Index: Core/Common/src/Core.Common.Gui/Forms/MessageWindow/IMessageWindow.cs
===================================================================
diff -u -rfbb37872d09f1ded75ce2209e8e48a6b64d8a78f -r07138211a0efc377b1c9ef29a8e86178e8d90ab3
--- Core/Common/src/Core.Common.Gui/Forms/MessageWindow/IMessageWindow.cs (.../IMessageWindow.cs) (revision fbb37872d09f1ded75ce2209e8e48a6b64d8a78f)
+++ Core/Common/src/Core.Common.Gui/Forms/MessageWindow/IMessageWindow.cs (.../IMessageWindow.cs) (revision 07138211a0efc377b1c9ef29a8e86178e8d90ab3)
@@ -25,27 +25,29 @@
namespace Core.Common.Gui.Forms.MessageWindow
{
+ ///
+ /// Interface declaring the members for a view that can show log messages.
+ ///
public interface IMessageWindow : IView
{
///
- /// Adds logging event as a log4net event to the window.
- /// Only some columns are added.
+ /// Adds a logging message to the view.
///
- ///
- ///
- ///
+ /// Type of logging message.
+ /// Time when the message was logged.
+ /// The message text.
void AddMessage(Level level, DateTime time, string message);
///
- /// Clears all messages in the window.
+ /// Clears all messages in the view.
///
void Clear();
///
- /// Returns true if message level is enabled in the window (can be shown).
+ /// Indicates if a given logging-level is enabled or not.
///
- ///
- ///
+ /// The type of logging message to check.
+ /// true is the particular logging-level is enabled; false otherwise.
bool IsMessageLevelEnabled(Level level);
}
}
\ No newline at end of file
Index: Core/Common/src/Core.Common.Gui/Forms/MessageWindow/MessageWindow.cs
===================================================================
diff -u -rfbb37872d09f1ded75ce2209e8e48a6b64d8a78f -r07138211a0efc377b1c9ef29a8e86178e8d90ab3
--- Core/Common/src/Core.Common.Gui/Forms/MessageWindow/MessageWindow.cs (.../MessageWindow.cs) (revision fbb37872d09f1ded75ce2209e8e48a6b64d8a78f)
+++ Core/Common/src/Core.Common.Gui/Forms/MessageWindow/MessageWindow.cs (.../MessageWindow.cs) (revision 07138211a0efc377b1c9ef29a8e86178e8d90ab3)
@@ -29,42 +29,58 @@
namespace Core.Common.Gui.Forms.MessageWindow
{
+ ///
+ /// Class that receives messages from to be displayed
+ /// in a thread-safe way. This view supports filtering particular logging levels.
+ ///
public partial class MessageWindow : UserControl, IMessageWindow
{
- public event EventHandler OnError;
- private readonly IWin32Window owner;
+ #region Constants referring to the item-names of the ImageList
+
+ private const string errorLevelImageName = "exclamation.png";
+ private const string warningLevelImageName = "error.png";
+ private const string informationLevelImageName = "information.png";
+ private const string debugLevelImageName = "debug.png";
+
+ #endregion
+
+ private readonly IWin32Window dialogParent;
private readonly Dictionary levelImageName;
private readonly ConcurrentQueue newMessages = new ConcurrentQueue();
private bool filtering;
- public MessageWindow(IWin32Window owner)
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The dialog parent for which dialogs should be shown on top.
+ public MessageWindow(IWin32Window dialogParent)
{
- this.owner = owner;
+ this.dialogParent = dialogParent;
Text = Resources.MessageWindow_MessageWindow_Messages;
- MessageWindowLogAppender.MessageWindow = this;
+ MessageWindowLogAppender.Instance.MessageWindow = this;
InitializeComponent();
levelImageName = new Dictionary();
// order is the same as in log4j Level (check sources of log4net)
- levelImageName[Level.Off.ToString()] = "exclamation.png";
- levelImageName[Level.Emergency.ToString()] = "exclamation.png";
- levelImageName[Level.Fatal.ToString()] = "exclamation.png";
- levelImageName[Level.Alert.ToString()] = "exclamation.png";
- levelImageName[Level.Critical.ToString()] = "exclamation.png";
- levelImageName[Level.Severe.ToString()] = "exclamation.png";
- levelImageName[Level.Error.ToString()] = "exclamation.png";
- levelImageName[Level.Warn.ToString()] = "error.png";
- levelImageName[Level.Notice.ToString()] = "error.png";
- levelImageName[Level.Info.ToString()] = "information.png";
- levelImageName[Level.Debug.ToString()] = "debug.png";
- levelImageName[Level.Fine.ToString()] = "debug.png";
- levelImageName[Level.Trace.ToString()] = "debug.png";
- levelImageName[Level.Finer.ToString()] = "debug.png";
- levelImageName[Level.Verbose.ToString()] = "debug.png";
- levelImageName[Level.Finest.ToString()] = "debug.png";
- levelImageName[Level.All.ToString()] = "debug.png";
+ levelImageName[Level.Off.ToString()] = errorLevelImageName;
+ levelImageName[Level.Emergency.ToString()] = errorLevelImageName;
+ levelImageName[Level.Fatal.ToString()] = errorLevelImageName;
+ levelImageName[Level.Alert.ToString()] = errorLevelImageName;
+ levelImageName[Level.Critical.ToString()] = errorLevelImageName;
+ levelImageName[Level.Severe.ToString()] = errorLevelImageName;
+ levelImageName[Level.Error.ToString()] = errorLevelImageName;
+ levelImageName[Level.Warn.ToString()] = warningLevelImageName;
+ levelImageName[Level.Notice.ToString()] = warningLevelImageName;
+ levelImageName[Level.Info.ToString()] = informationLevelImageName;
+ levelImageName[Level.Debug.ToString()] = debugLevelImageName;
+ levelImageName[Level.Fine.ToString()] = debugLevelImageName;
+ levelImageName[Level.Trace.ToString()] = debugLevelImageName;
+ levelImageName[Level.Finer.ToString()] = debugLevelImageName;
+ levelImageName[Level.Verbose.ToString()] = debugLevelImageName;
+ levelImageName[Level.Finest.ToString()] = debugLevelImageName;
+ levelImageName[Level.All.ToString()] = debugLevelImageName;
messagesDataGridView.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText;
messagesDataGridView.MouseUp += MessagesDataGridViewMouseUp;
@@ -76,7 +92,7 @@
// fixes DPI problem
messagesDataGridView.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.AutoSize;
- messagesDataGridView.RowsAdded += messagesDataGridView_RowsAdded;
+ messagesDataGridView.RowsAdded += MessagesDataGridViewRowsAdded;
}
#region IView Members
@@ -92,10 +108,6 @@
#endregion
- ///
- /// Raises the event.
- ///
- /// A that contains the event data.
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
@@ -109,34 +121,27 @@
return;
}
- var hasError = false;
messageWindowData.Messages.BeginLoadData();
try
{
MessageData msg;
while (newMessages.TryDequeue(out msg))
{
messageWindowData.Messages.AddMessagesRow(msg.ImageName, msg.Time, msg.Message);
- hasError = hasError || (msg.ImageName == "ERROR" && OnError != null);
}
}
finally
{
messageWindowData.Messages.EndLoadData();
}
- if (hasError)
- {
- OnError(this, null);
- }
-
if (messagesDataGridView.Rows.Count > 0)
{
messagesDataGridView.CurrentCell = messagesDataGridView.Rows[0].Cells[0];
}
}
- private void messagesDataGridView_RowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
+ private void MessagesDataGridViewRowsAdded(object sender, DataGridViewRowsAddedEventArgs e)
{
if (filtering)
{
@@ -180,36 +185,40 @@
Clear();
}
- ///
- /// Copies selected range to the clipboard
- ///
- ///
- ///
private void ButtonCopyClick(object sender, EventArgs e)
{
Clipboard.SetDataObject(messagesDataGridView.GetClipboardContent());
}
- ///
- /// since the dataset stores the image name and not the actual image, we have to put
- /// the corresponding image in the datagridviewcell of the first column.
- ///
- ///
- ///
private void MessagesDataGridViewCellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
{
if (e.ColumnIndex != 0 || e.Value == null)
{
return;
}
+ // Dataset stores image-name instead of actual image, therefore we map to
+ // actual image during formatting.
var level = (string) e.Value;
e.Value = levelImages.Images[levelImageName[level]];
}
private void ApplyFilter()
{
filtering = true;
+
+ messagesBindingSource.Filter = CreateLoggingLevelDataGridViewFilter();
+
+ filtering = false;
+
+ foreach (DataGridViewRow row in messagesDataGridView.Rows)
+ {
+ AutoSizeRow(row);
+ }
+ }
+
+ private string CreateLoggingLevelDataGridViewFilter()
+ {
var filterlines = new List();
if (buttonShowInfo.Checked)
{
@@ -224,27 +233,9 @@
filterlines.Add(string.Format("Image = '{0}'", Level.Error));
filterlines.Add(string.Format("Image = '{0}'", Level.Fatal));
}
-
- if (filterlines.Count == 0)
- {
- messagesBindingSource.Filter = "Image = 'NOTHING SHOWN'";
- }
- else
- {
- string filter = filterlines[0];
- for (var i = 1; i < filterlines.Count; i++)
- {
- filter += " OR " + filterlines[i];
- }
- messagesBindingSource.Filter = filter;
- }
-
- filtering = false;
-
- foreach (DataGridViewRow row in messagesDataGridView.Rows)
- {
- AutoSizeRow(row);
- }
+ return filterlines.Count == 0 ?
+ "Image = 'NOTHING SHOWN'" :
+ string.Join(" OR ", filterlines);
}
private void ButtonShowInfoClick(object sender, EventArgs e)
@@ -272,7 +263,7 @@
return;
}
- var messageWindowDialog = new MessageWindowDialog(owner, (string) messagesDataGridView.CurrentRow.Cells[messageDataGridViewTextBoxColumn.Index].Value);
+ var messageWindowDialog = new MessageWindowDialog(dialogParent, (string) messagesDataGridView.CurrentRow.Cells[messageDataGridViewTextBoxColumn.Index].Value);
messageWindowDialog.ShowDialog();
}
@@ -286,12 +277,6 @@
#region IMessageWindow Members
- ///
- /// Appends message to the Top of the messagewindow
- ///
- ///
- ///
- ///
public void AddMessage(Level level, DateTime time, string message)
{
newMessages.Enqueue(new MessageData
@@ -301,9 +286,6 @@
Invalidate();
}
- ///
- /// Clears all messages from the view
- ///
public void Clear()
{
messageWindowData.Clear();
Index: Core/Common/src/Core.Common.Gui/Forms/MessageWindow/MessageWindowLogAppender.cs
===================================================================
diff -u -r98de4c5be2622a4476aa47e6d5084e88d57b80bd -r07138211a0efc377b1c9ef29a8e86178e8d90ab3
--- Core/Common/src/Core.Common.Gui/Forms/MessageWindow/MessageWindowLogAppender.cs (.../MessageWindowLogAppender.cs) (revision 98de4c5be2622a4476aa47e6d5084e88d57b80bd)
+++ Core/Common/src/Core.Common.Gui/Forms/MessageWindow/MessageWindowLogAppender.cs (.../MessageWindowLogAppender.cs) (revision 07138211a0efc377b1c9ef29a8e86178e8d90ab3)
@@ -22,38 +22,68 @@
using System;
using System.Collections.Generic;
using System.Linq;
-using System.Reflection;
-using System.Resources;
+
using Core.Common.Gui.Properties;
+using Core.Common.Utils.Reflection;
+
using log4net.Appender;
using log4net.Core;
+using log4net.Util;
namespace Core.Common.Gui.Forms.MessageWindow
{
+ ///
+ /// A log-appender for Log4Net that is able to forward received messages to a
+ /// instance.
+ ///
public class MessageWindowLogAppender : AppenderSkeleton
{
///
- /// This list contains any messages that could not yet be delivered to the MessageWindow (typically because it doesn't exist
- /// yet at startup). They are kept in the backlog and send to the MessageWindow upon the first message arriving while there
- /// is a MessageWindow.
+ /// This list contains any messages that could not yet be delivered to the
+ /// (typically because it doesn't exist yet at startup). They are kept in the backlog
+ /// and send to upon the first message arriving while there is a MessageWindow
+ /// has been set.
///
- protected static IList messageBackLog = new List();
+ private readonly IList messageBackLog = new List();
- private static bool enabled;
+ private bool enabled;
+ private IMessageWindow messageWindow;
- public static IMessageWindow MessageWindow { get; set; }
+ ///
+ /// Initializes a new instance of the class and
+ /// the singleton instance.
+ ///
+ public MessageWindowLogAppender()
+ {
+ Instance = this;
+ }
///
- /// Resource manager for looking up culture/language depended messages
+ /// Gets the singleton instance.
///
- public static ResourceManager ResourceManager { get; set; }
+ public static MessageWindowLogAppender Instance { get; set; }
///
- /// Resource writer makes a catalogue for not found messages at the resources
+ /// Gets or sets the message window to which log-messages should be forwarded.
///
- public static ResourceWriter ResourceWriter { get; set; }
+ public IMessageWindow MessageWindow
+ {
+ get
+ {
+ return messageWindow;
+ }
+ set
+ {
+ messageWindow = value;
+ FlushMessagesToMessageWindow();
+ }
+ }
- public static bool Enabled
+ ///
+ /// Indicating whether this appender should forward it's messages to
+ /// (set to true) or should cache them when it's enabled at a later time (set to false).
+ ///
+ public bool Enabled
{
get
{
@@ -68,7 +98,7 @@
protected override void Append(LoggingEvent loggingEvent)
{
- if (MessageWindow == null || !Enabled)
+ if (MessageWindow == null || !enabled)
{
messageBackLog.Add(loggingEvent);
}
@@ -79,39 +109,21 @@
}
}
- protected static void AppendToMessageWindow(LoggingEvent loggingEvent)
+ private void AppendToMessageWindow(LoggingEvent loggingEvent)
{
- if (MessageWindow == null)
- {
- return;
- }
-
string message = null;
- if (loggingEvent.MessageObject != null)
+ var stringFormat = loggingEvent.MessageObject as SystemStringFormat;
+ if (stringFormat != null)
{
- Type t = loggingEvent.MessageObject.GetType();
-
- if (t.FullName == "log4net.Util.SystemStringFormat")
- {
- string format =
- (string)
- t.InvokeMember("m_format",
- BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance, null,
- loggingEvent.MessageObject, null);
- object[] args =
- (object[])
- t.InvokeMember("m_args",
- BindingFlags.GetField | BindingFlags.NonPublic | BindingFlags.Instance, null,
- loggingEvent.MessageObject, null);
-
- message = GetLocalizedMessage(format, args);
- }
+ string format = TypeUtils.GetField(stringFormat, "m_format");
+ object[] args = TypeUtils.GetField