Skip to content

Commit 7d8009f

Browse files
Fr33danJTignor
andauthored
Add ToolStripItemTarget. (#87)
* Add ToolStripItemTarget. * Switch to using layout instead of strings Also move logic directly to write method rather than add a billion arguments to FindItemAndSendTheMessage * Add unit tests for ToolStripMenuItemTarget. * Do events so invoke can apply. Dispose form. * Add whitespace for clarity. Test dumb theory. * Add second DoEvents to make test pass because ??? * Run form on STA thread. * Read item only from form thread. * Add ability to track pending invocations for tests * Bring back the form threading. * Fix unit testing Use collections so tests don't run simultaneously as well as remove tricky code that didn't work and is just clutter if unneeded. * Simplify test further. Co-authored-by: JTignor <[email protected]>
1 parent 2772d79 commit 7d8009f

File tree

4 files changed

+241
-0
lines changed

4 files changed

+241
-0
lines changed

NLog.Windows.Forms.Tests/RichTextBoxTargetTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212

1313
namespace NLog.Windows.Forms.Tests
1414
{
15+
[Collection("NLog.Windows.Forms Tests")]
1516
public class RichTextBoxTargetTests
1617
{
1718
private Logger logger = LogManager.GetLogger("NLog.UnitTests.Targets.RichTextBoxTargetTests");
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
using NLog.Config;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Linq;
5+
using System.Text;
6+
using System.Threading.Tasks;
7+
using System.Windows.Forms;
8+
using Xunit;
9+
10+
namespace NLog.Windows.Forms.Tests
11+
{
12+
[Collection("NLog.Windows.Forms Tests")]
13+
public class ToolStripItemTargetTests
14+
{
15+
private Logger logger = LogManager.GetLogger("NLog.UnitTests.Targets.ToolStripItemTargetTests");
16+
17+
[Fact]
18+
public void SimpleToolStripItemTargetTest()
19+
{
20+
Form testForm = null;
21+
try
22+
{
23+
testForm = new Form();
24+
testForm.Name = "Form1";
25+
26+
ToolStrip testMenuStrip = new ToolStrip();
27+
testMenuStrip.Name = "ToolStrip1";
28+
testForm.Controls.Add(testMenuStrip);
29+
30+
ToolStripMenuItem testItem = new ToolStripMenuItem();
31+
testItem.Name = "Item1";
32+
testMenuStrip.Items.Add(testItem);
33+
34+
testForm.Show();
35+
36+
Application.DoEvents();
37+
38+
ToolStripItemTarget target = new ToolStripItemTarget()
39+
{
40+
ItemName = "Item1",
41+
FormName = "Form1",
42+
ToolStripName = "ToolStrip1",
43+
Layout = "${level} ${logger} ${message}"
44+
};
45+
SimpleConfigurator.ConfigureForTargetLogging(target, LogLevel.Trace);
46+
47+
logger.Fatal("Test"); // Send log
48+
Application.DoEvents(); // Do events to allow the invoked method is completed.
49+
Assert.Equal("Fatal NLog.UnitTests.Targets.ToolStripItemTargetTests Test", testItem.Text); // Test if method worked.
50+
51+
logger.Error("Foo");
52+
Application.DoEvents();
53+
Assert.Equal("Error NLog.UnitTests.Targets.ToolStripItemTargetTests Foo", testItem.Text);
54+
55+
logger.Warn("Bar");
56+
Application.DoEvents();
57+
Assert.Equal("Warn NLog.UnitTests.Targets.ToolStripItemTargetTests Bar", testItem.Text);
58+
59+
logger.Info("Test");
60+
Application.DoEvents();
61+
Assert.Equal("Info NLog.UnitTests.Targets.ToolStripItemTargetTests Test", testItem.Text);
62+
63+
logger.Debug("Foo");
64+
Application.DoEvents();
65+
Assert.Equal("Debug NLog.UnitTests.Targets.ToolStripItemTargetTests Foo", testItem.Text);
66+
67+
logger.Trace("Bar");
68+
Application.DoEvents();
69+
Assert.Equal("Trace NLog.UnitTests.Targets.ToolStripItemTargetTests Bar", testItem.Text);
70+
71+
}
72+
finally
73+
{
74+
if (testForm != null)
75+
{
76+
testForm.Dispose();
77+
}
78+
LogManager.Configuration = null;
79+
}
80+
}
81+
}
82+
}

NLog.Windows.Forms/FormHelper.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,34 @@ internal static Control FindControl(string name, Control searchControl)
5555
return null;
5656
}
5757

58+
/// <summary>
59+
/// Finds item within searchCollection it's contents drop down items.
60+
/// </summary>
61+
/// <param name="name">Name of the ToolStripItem</param>
62+
/// <param name="searchCollection">Collection of ToolStripItem we are looking for the item in.</param>
63+
/// <returns>A value of null of no item has been found.</returns>
64+
internal static ToolStripItem FindToolStripItem(string name, ToolStripItemCollection searchCollection)
65+
{
66+
foreach (ToolStripItem childItem in searchCollection)
67+
{
68+
if(childItem.Name == name)
69+
{
70+
return childItem;
71+
}
72+
if(childItem is ToolStripDropDownItem)
73+
{
74+
ToolStripDropDownItem childDropDown = childItem as ToolStripDropDownItem;
75+
ToolStripItem foundItem = FindToolStripItem(name, childDropDown.DropDownItems);
76+
77+
if (foundItem != null)
78+
{
79+
return foundItem;
80+
}
81+
}
82+
}
83+
return null;
84+
}
85+
5886
/// <summary>
5987
/// Finds control of specified type embended on searchControl.
6088
/// </summary>
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
using System;
2+
using System.ComponentModel;
3+
using System.Windows.Forms;
4+
using NLog.Common;
5+
using NLog.Config;
6+
using NLog.Layouts;
7+
using NLog.Targets;
8+
9+
namespace NLog.Windows.Forms
10+
{
11+
/// <summary>
12+
/// Logs text to Windows.Forms.ToolStripItem.Text property control of specified Name.
13+
/// </summary>
14+
/// <example>
15+
/// <p>
16+
/// To set up the target in the <a href="config.html">configuration file</a>,
17+
/// use the following syntax:
18+
/// </p>
19+
/// <code lang="XML" source="examples/targets/Configuration File/ToolStripItem/NLog.config" />
20+
/// <p>
21+
/// The result is:
22+
/// </p>
23+
/// <img src="examples/targets/Screenshots/ToolStripItem/ToolStripItem.gif" />
24+
/// <p>
25+
/// To set up the log target programmatically similar to above use code like this:
26+
/// </p>
27+
/// <code lang="C#" source="examples/targets/Configuration API/ToolStripItem/Form1.cs" />,
28+
/// </example>
29+
[Target("ToolStripItem")]
30+
public sealed class ToolStripItemTarget : TargetWithLayout
31+
{
32+
/// <summary>
33+
/// Initializes a new instance of the <see cref="ToolStripItemTarget" /> class.
34+
/// </summary>
35+
/// <remarks>
36+
/// The default value of the layout is: <code>${longdate}|${level:uppercase=true}|${logger}|${message}</code>
37+
/// </remarks>
38+
public ToolStripItemTarget()
39+
{
40+
}
41+
42+
private delegate void DelSendTheMessageToFormControl(ToolStripItem control, string logMessage);
43+
44+
/// <summary>
45+
/// Gets or sets the name of the ToolStripItem to which NLog will log write log text.
46+
/// </summary>
47+
/// <docgen category='Form Options' order='10' />
48+
[RequiredParameter]
49+
public Layout ItemName { get; set; }
50+
51+
/// <summary>
52+
/// Gets or sets the name of ToolStrip that contains the ToolStripItem to which NLog will log write log text.
53+
/// </summary>
54+
/// <docgen category='Form Options' order='10' />
55+
[RequiredParameter]
56+
public Layout ToolStripName { get; set; }
57+
58+
/// <summary>
59+
/// Gets or sets the name of the Form on which the ToolStrip is located.
60+
/// </summary>
61+
/// <docgen category='Form Options' order='10' />
62+
public Layout FormName { get; set; }
63+
64+
/// <summary>
65+
/// Log message to item.
66+
/// </summary>
67+
/// <param name="logEvent">
68+
/// The logging event.
69+
/// </param>
70+
protected override void Write(LogEventInfo logEvent)
71+
{
72+
string logMessage = Layout.Render(logEvent);
73+
74+
Form form = null;
75+
76+
if (Form.ActiveForm != null)
77+
{
78+
form = Form.ActiveForm;
79+
}
80+
81+
if (Application.OpenForms[FormName.Render(logEvent)] != null)
82+
{
83+
form = Application.OpenForms[FormName.Render(logEvent)];
84+
}
85+
86+
if (form == null)
87+
{
88+
InternalLogger.Info("Form {0} not found", FormName);
89+
return;
90+
}
91+
92+
Control control = FormHelper.FindControl(ToolStripName.Render(logEvent), form);
93+
94+
if (control == null || !(control is ToolStrip))
95+
{
96+
InternalLogger.Info("ToolStrip {0} on Form {1} not found", ToolStripName, FormName);
97+
return;
98+
}
99+
100+
ToolStrip toolStrip = control as ToolStrip;
101+
102+
ToolStripItem item = FormHelper.FindToolStripItem(ItemName.Render(logEvent), toolStrip.Items);
103+
104+
if (item == null)
105+
{
106+
InternalLogger.Info("ToolStripItem {0} on ToolStrip {1} not found", ItemName, ToolStripName);
107+
return;
108+
}
109+
110+
try
111+
{
112+
control.BeginInvoke(new DelSendTheMessageToFormControl(SendTheMessageToFormControl), item, logMessage);
113+
114+
}
115+
catch (Exception ex)
116+
{
117+
InternalLogger.Warn(ex.ToString());
118+
119+
if (LogManager.ThrowExceptions)
120+
{
121+
throw;
122+
}
123+
}
124+
}
125+
private void SendTheMessageToFormControl(ToolStripItem item, string logMessage)
126+
{
127+
item.Text = logMessage;
128+
}
129+
}
130+
}

0 commit comments

Comments
 (0)