完善窗口日志显示
This commit is contained in:
@@ -1,92 +1,53 @@
|
||||
//
|
||||
// Copyright (c) 2004-2011 Jaroslaw Kowalski <jaak@jkowalski.net>
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the name of Jaroslaw Kowalski nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
// THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
using NLog;
|
||||
using NLog.Conditions;
|
||||
using NLog.Config;
|
||||
using NLog;
|
||||
using System.ComponentModel;
|
||||
using NLog.Layouts;
|
||||
using System.Windows;
|
||||
|
||||
namespace NLog.Windows.Wpf
|
||||
{
|
||||
[NLogConfigurationItem]
|
||||
public class RichTextBoxRowColoringRule
|
||||
{
|
||||
static RichTextBoxRowColoringRule()
|
||||
{
|
||||
Default = new RichTextBoxRowColoringRule();
|
||||
}
|
||||
|
||||
public RichTextBoxRowColoringRule()
|
||||
: this(null, "Empty", "Empty", FontStyles.Normal, FontWeights.Normal)
|
||||
{
|
||||
}
|
||||
|
||||
public RichTextBoxRowColoringRule(string condition, string fontColor, string backColor, FontStyle fontStyle, FontWeight fontWeight)
|
||||
{
|
||||
Condition = condition;
|
||||
FontColor = fontColor;
|
||||
BackgroundColor = backColor;
|
||||
Style = fontStyle;
|
||||
Weight = fontWeight;
|
||||
}
|
||||
|
||||
public RichTextBoxRowColoringRule(string condition, string fontColor, string backColor)
|
||||
{
|
||||
Condition = condition;
|
||||
FontColor = fontColor;
|
||||
BackgroundColor = backColor;
|
||||
Style = FontStyles.Normal;
|
||||
Weight = FontWeights.Normal;
|
||||
}
|
||||
|
||||
public static RichTextBoxRowColoringRule Default { get; private set; }
|
||||
|
||||
[RequiredParameter]
|
||||
public ConditionExpression Condition { get; set; }
|
||||
|
||||
[DefaultValue("Empty")]
|
||||
public string FontColor { get; set; }
|
||||
public Layout FontColor { get; set; }
|
||||
public Layout BackgroundColor { get; set; }
|
||||
|
||||
[DefaultValue("Empty")]
|
||||
public string BackgroundColor { get; set; }
|
||||
public FontStyle FontStyle { get; set; }
|
||||
public FontWeight FontWeight { get; set; }
|
||||
|
||||
public FontStyle Style { get; set; }
|
||||
static RichTextBoxRowColoringRule()
|
||||
{
|
||||
RichTextBoxRowColoringRule.Default = new RichTextBoxRowColoringRule();
|
||||
}
|
||||
|
||||
public FontWeight Weight { get; set; }
|
||||
public RichTextBoxRowColoringRule() : this(null, "Empty", "Empty", FontStyles.Normal, FontWeights.Normal) { }
|
||||
|
||||
public RichTextBoxRowColoringRule(string condition, string fontColor, string backColor)
|
||||
{
|
||||
this.Condition = (ConditionExpression)condition;
|
||||
this.FontColor = Layout.FromString(fontColor);
|
||||
this.BackgroundColor = Layout.FromString(backColor);
|
||||
this.FontStyle = FontStyles.Normal;
|
||||
this.FontWeight = FontWeights.Normal;
|
||||
}
|
||||
|
||||
public RichTextBoxRowColoringRule(string condition, string fontColor, string backColor, FontStyle fontStyle, FontWeight fontWeight)
|
||||
{
|
||||
this.Condition = (ConditionExpression)condition;
|
||||
this.FontColor = Layout.FromString(fontColor);
|
||||
this.BackgroundColor = Layout.FromString(backColor);
|
||||
this.FontStyle = fontStyle;
|
||||
this.FontWeight = fontWeight;
|
||||
}
|
||||
|
||||
public bool CheckCondition(LogEventInfo logEvent)
|
||||
{
|
||||
return true.Equals(Condition.Evaluate(logEvent));
|
||||
return true.Equals(this.Condition.Evaluate(logEvent));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,27 @@
|
||||
using NLog.Config;
|
||||
using NLog.Layouts;
|
||||
using NLog;
|
||||
using NLog.Common;
|
||||
using NLog.Config;
|
||||
using NLog.Targets;
|
||||
using NLog;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.ComponentModel;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Media;
|
||||
using System.Windows;
|
||||
|
||||
namespace NLog.Windows.Wpf
|
||||
{
|
||||
// TODO: 完善日志实现
|
||||
[Target("RichTextBox")]
|
||||
public sealed class RichTextBoxTarget : TargetWithLayout
|
||||
{
|
||||
private int lineCount;
|
||||
private int _width = 500;
|
||||
private int _height = 500;
|
||||
private static readonly TypeConverter colorConverter = new ColorConverter();
|
||||
public static ReadOnlyCollection<RichTextBoxRowColoringRule> DefaultRowColoringRules { get; } = CreateDefaultColoringRules();
|
||||
|
||||
static RichTextBoxTarget()
|
||||
private static ReadOnlyCollection<RichTextBoxRowColoringRule> CreateDefaultColoringRules()
|
||||
{
|
||||
var rules = new List<RichTextBoxRowColoringRule>()
|
||||
return new List<RichTextBoxRowColoringRule>()
|
||||
{
|
||||
new RichTextBoxRowColoringRule("level == LogLevel.Fatal", "White", "Red", FontStyles.Normal, FontWeights.Bold),
|
||||
new RichTextBoxRowColoringRule("level == LogLevel.Error", "Red", "Empty", FontStyles.Italic, FontWeights.Bold),
|
||||
@@ -36,221 +29,253 @@ namespace NLog.Windows.Wpf
|
||||
new RichTextBoxRowColoringRule("level == LogLevel.Info", "Black", "Empty"),
|
||||
new RichTextBoxRowColoringRule("level == LogLevel.Debug", "Gray", "Empty"),
|
||||
new RichTextBoxRowColoringRule("level == LogLevel.Trace", "DarkGray", "Empty", FontStyles.Italic, FontWeights.Normal),
|
||||
};
|
||||
|
||||
DefaultRowColoringRules = rules.AsReadOnly();
|
||||
}.AsReadOnly();
|
||||
}
|
||||
|
||||
public RichTextBoxTarget()
|
||||
{
|
||||
WordColoringRules = new List<RichTextBoxWordColoringRule>();
|
||||
RowColoringRules = new List<RichTextBoxRowColoringRule>();
|
||||
ToolWindow = true;
|
||||
}
|
||||
|
||||
private delegate void DelSendTheMessageToRichTextBox(string logMessage, RichTextBoxRowColoringRule rule);
|
||||
|
||||
private delegate void FormCloseDelegate();
|
||||
|
||||
public static ReadOnlyCollection<RichTextBoxRowColoringRule> DefaultRowColoringRules { get; private set; }
|
||||
public RichTextBoxTarget() { }
|
||||
|
||||
public string ControlName { get; set; }
|
||||
|
||||
public string FormName { get; set; }
|
||||
public string WindowName { get; set; }
|
||||
|
||||
[DefaultValue(false)]
|
||||
public bool UseDefaultRowColoringRules { get; set; }
|
||||
|
||||
[ArrayParameter(typeof(RichTextBoxRowColoringRule), "row-coloring")]
|
||||
public IList<RichTextBoxRowColoringRule> RowColoringRules { get; private set; }
|
||||
|
||||
[ArrayParameter(typeof(RichTextBoxWordColoringRule), "word-coloring")]
|
||||
public IList<RichTextBoxWordColoringRule> WordColoringRules { get; private set; }
|
||||
|
||||
[DefaultValue(true)]
|
||||
public bool ToolWindow { get; set; }
|
||||
|
||||
public bool ShowMinimized { get; set; }
|
||||
|
||||
public int Width
|
||||
{
|
||||
get { return _width; }
|
||||
set { _width = value; }
|
||||
}
|
||||
|
||||
public int Height
|
||||
{
|
||||
get { return _height; }
|
||||
set { _height = value; }
|
||||
}
|
||||
|
||||
public bool AutoScroll { get; set; }
|
||||
|
||||
public int MaxLines { get; set; }
|
||||
|
||||
internal Window TargetForm { get; set; }
|
||||
[ArrayParameter(typeof(RichTextBoxRowColoringRule), "row-coloring")]
|
||||
public IList<RichTextBoxRowColoringRule> RowColoringRules { get; } = new List<RichTextBoxRowColoringRule>();
|
||||
|
||||
internal RichTextBox TargetRichTextBox { get; set; }
|
||||
[ArrayParameter(typeof(RichTextBoxWordColoringRule), "word-coloring")]
|
||||
public IList<RichTextBoxWordColoringRule> WordColoringRules { get; } = new List<RichTextBoxWordColoringRule>();
|
||||
|
||||
internal bool CreatedForm { get; set; }
|
||||
[NLogConfigurationIgnoreProperty]
|
||||
public Window TargetWindow { get; set; }
|
||||
|
||||
[NLogConfigurationIgnoreProperty]
|
||||
public RichTextBox TargetRichTextBox { get; set; }
|
||||
|
||||
protected override void InitializeTarget()
|
||||
{
|
||||
TargetRichTextBox = Application.Current.MainWindow.FindName(ControlName) as RichTextBox;
|
||||
base.InitializeTarget();
|
||||
if (TargetRichTextBox != null)
|
||||
return;
|
||||
|
||||
if (TargetRichTextBox != null) return;
|
||||
//this.TargetForm = FormHelper.CreateForm(this.FormName, this.Width, this.Height, false, this.ShowMinimized, this.ToolWindow);
|
||||
//this.CreatedForm = true;
|
||||
|
||||
var openFormByName = Application.Current.Windows.Cast<Window>().FirstOrDefault(x => x.GetType().Name == FormName);
|
||||
if (openFormByName != null)
|
||||
if (WindowName == null)
|
||||
{
|
||||
TargetForm = openFormByName;
|
||||
if (string.IsNullOrEmpty(ControlName))
|
||||
{
|
||||
// throw new NLogConfigurationException("Rich text box control name must be specified for " + GetType().Name + ".");
|
||||
Trace.WriteLine("Rich text box control name must be specified for " + GetType().Name + ".");
|
||||
}
|
||||
|
||||
CreatedForm = false;
|
||||
TargetRichTextBox = TargetForm.FindName(ControlName) as RichTextBox;
|
||||
|
||||
if (TargetRichTextBox == null)
|
||||
{
|
||||
// throw new NLogConfigurationException("Rich text box control '" + ControlName + "' cannot be found on form '" + FormName + "'.");
|
||||
Trace.WriteLine("Rich text box control '" + ControlName + "' cannot be found on form '" + FormName + "'.");
|
||||
}
|
||||
HandleError("WindowName should be specified for {0}.{1}", GetType().Name, Name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (TargetRichTextBox == null)
|
||||
if (string.IsNullOrEmpty(ControlName))
|
||||
{
|
||||
TargetForm = new Window
|
||||
{
|
||||
Name = FormName,
|
||||
Width = Width,
|
||||
Height = Height,
|
||||
WindowStyle = ToolWindow ? WindowStyle.ToolWindow : WindowStyle.None,
|
||||
WindowState = ShowMinimized ? WindowState.Minimized : WindowState.Normal,
|
||||
Title = "NLog Messages"
|
||||
};
|
||||
TargetForm.Show();
|
||||
|
||||
TargetRichTextBox = new RichTextBox { Name = ControlName };
|
||||
var style = new Style(typeof(Paragraph));
|
||||
TargetRichTextBox.VerticalScrollBarVisibility = ScrollBarVisibility.Auto;
|
||||
style.Setters.Add(new Setter(Block.MarginProperty, new Thickness(0, 0, 0, 0)));
|
||||
TargetRichTextBox.Resources.Add(typeof(Paragraph), style);
|
||||
TargetForm.Content = TargetRichTextBox;
|
||||
|
||||
CreatedForm = true;
|
||||
HandleError("Rich text box control name must be specified for {0}.{1}", GetType().Name, Name);
|
||||
return;
|
||||
}
|
||||
|
||||
var targetWindow = Application.Current.Windows.OfType<Window>().FirstOrDefault(w => w.Name == WindowName);
|
||||
if (targetWindow == null)
|
||||
{
|
||||
InternalLogger.Info("{0}: WindowName '{1}' not found", this, WindowName);
|
||||
return;
|
||||
}
|
||||
|
||||
var targetControl = targetWindow.FindName(ControlName) as RichTextBox;
|
||||
if (targetControl == null)
|
||||
{
|
||||
InternalLogger.Info("{0}: WIndowName '{1}' does not contain ControlName '{2}'", this, WindowName, ControlName);
|
||||
return;
|
||||
}
|
||||
|
||||
AttachToControl(targetWindow, targetControl);
|
||||
}
|
||||
|
||||
private static void HandleError(string message, params object[] args)
|
||||
{
|
||||
if (LogManager.ThrowExceptions)
|
||||
{
|
||||
throw new NLogConfigurationException(string.Format(message, args));
|
||||
}
|
||||
InternalLogger.Error(message, args);
|
||||
}
|
||||
|
||||
private void AttachToControl(Window window, RichTextBox textboxControl)
|
||||
{
|
||||
InternalLogger.Info("{0}: Attaching target to textbox {1}.{2}", this, window.Name, textboxControl.Name);
|
||||
DetachFromControl();
|
||||
TargetWindow = window;
|
||||
TargetRichTextBox = textboxControl;
|
||||
}
|
||||
|
||||
private void DetachFromControl()
|
||||
{
|
||||
TargetWindow = null;
|
||||
TargetRichTextBox = null;
|
||||
}
|
||||
|
||||
protected override void CloseTarget()
|
||||
{
|
||||
if (CreatedForm)
|
||||
{
|
||||
try
|
||||
{
|
||||
TargetForm.Dispatcher.Invoke(() =>
|
||||
{
|
||||
TargetForm.Close();
|
||||
TargetForm = null;
|
||||
});
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
DetachFromControl();
|
||||
}
|
||||
|
||||
protected override void Write(LogEventInfo logEvent)
|
||||
{
|
||||
RichTextBoxRowColoringRule matchingRule = RowColoringRules.FirstOrDefault(rr => rr.CheckCondition(logEvent));
|
||||
|
||||
if (UseDefaultRowColoringRules && matchingRule == null)
|
||||
RichTextBox textbox = TargetRichTextBox;
|
||||
if (textbox == null || textbox.Dispatcher.HasShutdownStarted || textbox.Dispatcher.HasShutdownFinished)
|
||||
{
|
||||
foreach (var rr in DefaultRowColoringRules.Where(rr => rr.CheckCondition(logEvent)))
|
||||
{
|
||||
matchingRule = rr;
|
||||
break;
|
||||
}
|
||||
//no last logged textbox
|
||||
InternalLogger.Trace("{0}: Attached Textbox is {1}, skipping logging", this, textbox == null ? "null" : "disposed");
|
||||
return;
|
||||
}
|
||||
|
||||
if (matchingRule == null)
|
||||
{
|
||||
matchingRule = RichTextBoxRowColoringRule.Default;
|
||||
}
|
||||
|
||||
var logMessage = Layout.Render(logEvent);
|
||||
|
||||
if (Application.Current == null) return;
|
||||
string logMessage = RenderLogEvent(Layout, logEvent);
|
||||
RichTextBoxRowColoringRule matchingRule = FindMatchingRule(logEvent);
|
||||
_ = DoSendMessageToTextbox(logMessage, matchingRule, logEvent);
|
||||
}
|
||||
|
||||
private bool DoSendMessageToTextbox(string logMessage, RichTextBoxRowColoringRule rule, LogEventInfo logEvent)
|
||||
{
|
||||
RichTextBox textbox = TargetRichTextBox;
|
||||
try
|
||||
{
|
||||
if (Application.Current.Dispatcher.CheckAccess() == false)
|
||||
if (textbox != null && !textbox.Dispatcher.HasShutdownStarted && !textbox.Dispatcher.HasShutdownFinished)
|
||||
{
|
||||
Application.Current.Dispatcher.Invoke(() => SendTheMessageToRichTextBox(logMessage, matchingRule));
|
||||
}
|
||||
else
|
||||
{
|
||||
SendTheMessageToRichTextBox(logMessage, matchingRule);
|
||||
if (!textbox.Dispatcher.CheckAccess())
|
||||
{
|
||||
textbox.Dispatcher.BeginInvoke(() => SendTheMessageToRichTextBox(textbox, logMessage, rule, logEvent));
|
||||
}
|
||||
else
|
||||
{
|
||||
SendTheMessageToRichTextBox(textbox, logMessage, rule, logEvent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine(ex);
|
||||
}
|
||||
InternalLogger.Warn(ex, "{0}: Failed to append RichTextBox", this);
|
||||
|
||||
}
|
||||
|
||||
|
||||
private static Color GetColorFromString(string color, Brush defaultColor)
|
||||
{
|
||||
|
||||
if (color == "Empty")
|
||||
{
|
||||
return defaultColor is SolidColorBrush solidBrush ? solidBrush.Color : Colors.White;
|
||||
}
|
||||
|
||||
return (Color)colorConverter.ConvertFromString(color);
|
||||
}
|
||||
|
||||
|
||||
private void SendTheMessageToRichTextBox(string logMessage, RichTextBoxRowColoringRule rule)
|
||||
{
|
||||
RichTextBox rtbx = TargetRichTextBox;
|
||||
|
||||
var tr = new TextRange(rtbx.Document.ContentEnd, rtbx.Document.ContentEnd);
|
||||
tr.Text = logMessage + "\n";
|
||||
tr.ApplyPropertyValue(TextElement.ForegroundProperty,
|
||||
new SolidColorBrush(GetColorFromString(rule.FontColor, (Brush)tr.GetPropertyValue(TextElement.ForegroundProperty)))
|
||||
);
|
||||
tr.ApplyPropertyValue(TextElement.BackgroundProperty,
|
||||
new SolidColorBrush(GetColorFromString(rule.BackgroundColor, (Brush)tr.GetPropertyValue(TextElement.BackgroundProperty)))
|
||||
);
|
||||
tr.ApplyPropertyValue(TextElement.FontStyleProperty, rule.Style);
|
||||
tr.ApplyPropertyValue(TextElement.FontWeightProperty, rule.Weight);
|
||||
|
||||
|
||||
if (MaxLines > 0)
|
||||
{
|
||||
lineCount++;
|
||||
if (lineCount > MaxLines)
|
||||
if (LogManager.ThrowExceptions)
|
||||
{
|
||||
tr = new TextRange(rtbx.Document.ContentStart, rtbx.Document.ContentEnd);
|
||||
tr.Text.Remove(0, tr.Text.IndexOf('\n'));
|
||||
lineCount--;
|
||||
throw;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private RichTextBoxRowColoringRule FindMatchingRule(LogEventInfo logEvent)
|
||||
{
|
||||
//custom rules first
|
||||
if (RowColoringRules.Count > 0)
|
||||
{
|
||||
foreach (RichTextBoxRowColoringRule coloringRule in RowColoringRules)
|
||||
{
|
||||
if (coloringRule.CheckCondition(logEvent))
|
||||
{
|
||||
return coloringRule;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (UseDefaultRowColoringRules && DefaultRowColoringRules != null)
|
||||
{
|
||||
foreach (RichTextBoxRowColoringRule coloringRule in DefaultRowColoringRules)
|
||||
{
|
||||
if (coloringRule.CheckCondition(logEvent))
|
||||
{
|
||||
return coloringRule;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return RichTextBoxRowColoringRule.Default;
|
||||
}
|
||||
|
||||
private void SendTheMessageToRichTextBox(RichTextBox textBox, string logMessage, RichTextBoxRowColoringRule rule, LogEventInfo logEvent)
|
||||
{
|
||||
if (textBox == null) return;
|
||||
|
||||
var document = textBox.Document;
|
||||
|
||||
// 插入文本(带换行)
|
||||
var tr = new TextRange(document.ContentEnd, document.ContentEnd)
|
||||
{
|
||||
Text = logMessage + Environment.NewLine
|
||||
};
|
||||
|
||||
// 设置行级样式
|
||||
var fgColor = rule.FontColor?.Render(logEvent);
|
||||
var bgColor = rule.BackgroundColor?.Render(logEvent);
|
||||
|
||||
tr.ApplyPropertyValue(TextElement.ForegroundProperty,
|
||||
string.IsNullOrEmpty(fgColor) || fgColor == "Empty"
|
||||
? textBox.Foreground
|
||||
: new SolidColorBrush((Color)ColorConverter.ConvertFromString(fgColor)));
|
||||
|
||||
tr.ApplyPropertyValue(TextElement.BackgroundProperty,
|
||||
string.IsNullOrEmpty(bgColor) || bgColor == "Empty"
|
||||
? Brushes.Transparent
|
||||
: new SolidColorBrush((Color)ColorConverter.ConvertFromString(bgColor)));
|
||||
|
||||
tr.ApplyPropertyValue(TextElement.FontStyleProperty, rule.FontStyle);
|
||||
tr.ApplyPropertyValue(TextElement.FontWeightProperty, rule.FontWeight);
|
||||
|
||||
// Word coloring(在刚插入的范围内做匹配)
|
||||
if (WordColoringRules.Count > 0)
|
||||
{
|
||||
foreach (var wordRule in WordColoringRules)
|
||||
{
|
||||
var pattern = wordRule.Regex?.Render(logEvent) ?? string.Empty;
|
||||
var text = wordRule.Text?.Render(logEvent) ?? string.Empty;
|
||||
var wholeWords = wordRule.WholeWords.RenderValue(logEvent);
|
||||
var ignoreCase = wordRule.IgnoreCase.RenderValue(logEvent);
|
||||
|
||||
var regex = wordRule.ResolveRegEx(pattern, text, wholeWords, ignoreCase);
|
||||
var matches = regex.Matches(tr.Text);
|
||||
|
||||
foreach (Match match in matches)
|
||||
{
|
||||
// 匹配到的部分范围
|
||||
var start = tr.Start.GetPositionAtOffset(match.Index, LogicalDirection.Forward);
|
||||
var endPos = tr.Start.GetPositionAtOffset(match.Index + match.Length, LogicalDirection.Backward);
|
||||
if (start == null || endPos == null) continue;
|
||||
|
||||
var wordRange = new TextRange(start, endPos);
|
||||
|
||||
var wordFg = wordRule.FontColor?.Render(logEvent);
|
||||
var wordBg = wordRule.BackgroundColor?.Render(logEvent);
|
||||
|
||||
wordRange.ApplyPropertyValue(TextElement.ForegroundProperty,
|
||||
string.IsNullOrEmpty(wordFg) || wordFg == "Empty"
|
||||
? tr.GetPropertyValue(TextElement.ForegroundProperty)
|
||||
: new SolidColorBrush((Color)ColorConverter.ConvertFromString(wordFg)));
|
||||
|
||||
wordRange.ApplyPropertyValue(TextElement.BackgroundProperty,
|
||||
string.IsNullOrEmpty(wordBg) || wordBg == "Empty"
|
||||
? tr.GetPropertyValue(TextElement.BackgroundProperty)
|
||||
: new SolidColorBrush((Color)ColorConverter.ConvertFromString(wordBg)));
|
||||
|
||||
wordRange.ApplyPropertyValue(TextElement.FontStyleProperty, wordRule.FontStyle);
|
||||
wordRange.ApplyPropertyValue(TextElement.FontWeightProperty, wordRule.FontWeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 限制最大行数
|
||||
if (MaxLines > 0)
|
||||
{
|
||||
while (document.Blocks.Count > MaxLines)
|
||||
{
|
||||
document.Blocks.Remove(document.Blocks.FirstBlock);
|
||||
}
|
||||
}
|
||||
|
||||
// 自动滚动到最后
|
||||
if (AutoScroll)
|
||||
{
|
||||
rtbx.ScrollToEnd();
|
||||
textBox.ScrollToEnd();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,119 +1,59 @@
|
||||
//
|
||||
// Copyright (c) 2004-2011 Jaroslaw Kowalski <jaak@jkowalski.net>
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions
|
||||
// are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the name of Jaroslaw Kowalski nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
// THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
|
||||
using NLog.Config;
|
||||
using NLog.Layouts;
|
||||
using System.ComponentModel;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Windows;
|
||||
using NLog.Config;
|
||||
|
||||
namespace NLog.Windows.Wpf
|
||||
{
|
||||
[NLogConfigurationItem]
|
||||
[NLogConfigurationItem]
|
||||
public class RichTextBoxWordColoringRule
|
||||
{
|
||||
private Regex compiledRegex;
|
||||
public Layout Regex { get; set; }
|
||||
public Layout Text { get; set; }
|
||||
public Layout<bool> WholeWords { get; set; }
|
||||
public Layout<bool> IgnoreCase { get; set; }
|
||||
|
||||
public RichTextBoxWordColoringRule()
|
||||
public Layout FontColor { get; set; }
|
||||
public Layout BackgroundColor { get; set; }
|
||||
|
||||
public FontStyle FontStyle { get; set; }
|
||||
public FontWeight FontWeight { get; set; }
|
||||
|
||||
internal Regex ResolveRegEx(string pattern, string text, bool wholeWords, bool ignoreCase)
|
||||
{
|
||||
FontColor = "Empty";
|
||||
BackgroundColor = "Empty";
|
||||
if (string.IsNullOrEmpty(pattern) && text != null)
|
||||
{
|
||||
pattern = System.Text.RegularExpressions.Regex.Escape(text);
|
||||
if (wholeWords)
|
||||
pattern = "\b" + pattern + "\b";
|
||||
}
|
||||
|
||||
RegexOptions options = RegexOptions.None;
|
||||
if (ignoreCase)
|
||||
options |= RegexOptions.IgnoreCase;
|
||||
|
||||
return new Regex(pattern, options); // RegEx-Cache
|
||||
}
|
||||
|
||||
public RichTextBoxWordColoringRule() : this(null, "Empty", "Empty", FontStyles.Normal, FontWeights.Normal) { }
|
||||
|
||||
public RichTextBoxWordColoringRule(string text, string fontColor, string backgroundColor)
|
||||
{
|
||||
Text = text;
|
||||
FontColor = fontColor;
|
||||
BackgroundColor = backgroundColor;
|
||||
Style = FontStyles.Normal;
|
||||
Weight = FontWeights.Normal;
|
||||
this.Text = text;
|
||||
this.FontColor = Layout.FromString(fontColor);
|
||||
this.BackgroundColor = Layout.FromString(backgroundColor);
|
||||
this.FontStyle = FontStyles.Normal;
|
||||
this.FontWeight = FontWeights.Normal;
|
||||
}
|
||||
|
||||
public RichTextBoxWordColoringRule(string text, string textColor, string backgroundColor, FontStyle fontStyle, FontWeight fontWeight)
|
||||
{
|
||||
Text = text;
|
||||
FontColor = textColor;
|
||||
BackgroundColor = backgroundColor;
|
||||
Style = fontStyle;
|
||||
Weight = fontWeight;
|
||||
this.Text = text;
|
||||
this.FontColor = Layout.FromString(textColor);
|
||||
this.BackgroundColor = Layout.FromString(backgroundColor);
|
||||
this.FontStyle = fontStyle;
|
||||
this.FontWeight = fontWeight;
|
||||
}
|
||||
|
||||
public string Regex { get; set; }
|
||||
|
||||
public string Text { get; set; }
|
||||
|
||||
[DefaultValue(false)]
|
||||
public bool WholeWords { get; set; }
|
||||
|
||||
[DefaultValue(false)]
|
||||
public bool IgnoreCase { get; set; }
|
||||
|
||||
public FontStyle Style { get; set; }
|
||||
|
||||
public FontWeight Weight { get; set; }
|
||||
|
||||
public Regex CompiledRegex
|
||||
{
|
||||
get
|
||||
{
|
||||
if (compiledRegex == null)
|
||||
{
|
||||
string regexpression = Regex;
|
||||
if (regexpression == null && Text != null)
|
||||
{
|
||||
regexpression = System.Text.RegularExpressions.Regex.Escape(Text);
|
||||
if (WholeWords)
|
||||
{
|
||||
regexpression = "\b" + regexpression + "\b";
|
||||
}
|
||||
}
|
||||
|
||||
RegexOptions regexOptions = RegexOptions.Compiled;
|
||||
if (IgnoreCase)
|
||||
{
|
||||
regexOptions |= RegexOptions.IgnoreCase;
|
||||
}
|
||||
|
||||
compiledRegex = new Regex(regexpression, regexOptions);
|
||||
}
|
||||
|
||||
return compiledRegex;
|
||||
}
|
||||
}
|
||||
|
||||
[DefaultValue("Empty")]
|
||||
public string FontColor { get; set; }
|
||||
|
||||
[DefaultValue("Empty")]
|
||||
public string BackgroundColor { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
xmlns:utils="clr-namespace:SpineViewer.Utils"
|
||||
xmlns:SFMLRenderer="clr-namespace:SFMLRenderer;assembly=SFMLRenderer"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_mainWindow"
|
||||
Title="{Binding Title}"
|
||||
Width="1500"
|
||||
Height="800"
|
||||
|
||||
@@ -111,14 +111,13 @@ public partial class MainWindow : Window
|
||||
var rtbTarget = new NLog.Windows.Wpf.RichTextBoxTarget
|
||||
{
|
||||
Name = "rtbTarget",
|
||||
FormName = GetType().Name,
|
||||
WindowName = _mainWindow.Name,
|
||||
ControlName = _loggerRichTextBox.Name,
|
||||
AutoScroll = true,
|
||||
MaxLines = 3000,
|
||||
Layout = "[${level:format=OneLetter}]${date:format=yyyy-MM-dd HH\\:mm\\:ss} - ${message}"
|
||||
Layout = "[${level:format=OneLetter}]${date:format=yyyy-MM-dd HH\\:mm\\:ss} - ${message}",
|
||||
};
|
||||
|
||||
// TODO: 完善日志实现
|
||||
rtbTarget.WordColoringRules.Add(new("[D]", "Gray", "Empty"));
|
||||
rtbTarget.WordColoringRules.Add(new("[I]", "DimGray", "Empty"));
|
||||
rtbTarget.WordColoringRules.Add(new("[W]", "DarkOrange", "Empty"));
|
||||
|
||||
Reference in New Issue
Block a user