using CommunityToolkit.Mvvm.ComponentModel;
|
using OpenTap;
|
using OpenTap.Diagnostic;
|
using OpenTapEditor.Util;
|
using System.Collections.ObjectModel;
|
using System.Windows.Controls;
|
using System.Windows.Data;
|
using System.Windows.Media;
|
using System.Windows.Threading;
|
using UtilLib;
|
|
namespace OpenTapEditor
|
{
|
public enum LevelType
|
{
|
/// <summary>
|
/// Recoverable error.
|
/// </summary>
|
Error = 10,
|
/// <summary>
|
/// Noncritical problem.
|
/// </summary>
|
Warning = 20,
|
/// <summary>
|
/// Informational message.
|
/// </summary>
|
Info = 30,
|
/// <summary>
|
/// Debugging trace.
|
/// </summary>
|
Debug = 40
|
}
|
|
public class LogItem
|
{
|
|
public Event e { get; internal set; }
|
|
public int Type => e.EventType;
|
|
public override string ToString()
|
{
|
return $"{(LevelType)e.EventType} {new DateTime(e.Timestamp).ToString("HH:mm:ss.fff")} : {e.Source} : {e.Message}";
|
}
|
|
}
|
/// <summary>
|
/// LogControl.xaml 的交互逻辑
|
/// </summary>
|
[ObservableObject]
|
public partial class LogControl : UserControl, ILogListener
|
{
|
|
[ObservableProperty]
|
private ObservableCollection<LogItem> datasource = new ObservableCollection<LogItem>();
|
|
[ObservableProperty]
|
private string searchText = string.Empty;
|
|
[ObservableProperty]
|
private bool showError = true;
|
|
[ObservableProperty]
|
private bool showWarn = true;
|
|
[ObservableProperty]
|
private bool showInfo = true;
|
|
[ObservableProperty]
|
private bool showDebug = true;
|
|
[ObservableProperty]
|
private bool showAll = false;
|
|
[ObservableProperty]
|
private CollectionViewSource viewSource;
|
|
private readonly SolidColorBrush _debugBrush;
|
private readonly SolidColorBrush _successBrush;
|
private readonly SolidColorBrush _warnBrush;
|
private readonly SolidColorBrush _errorBrush;
|
|
public LogControl()
|
{
|
|
_debugBrush = new SolidColorBrush(Color.FromArgb(0xaa, 0x71, 0x80, 0x8A)); // 灰色
|
_successBrush = new SolidColorBrush(Color.FromArgb(0xaa, 0x30, 0xC5, 0x30));
|
_warnBrush = new SolidColorBrush(Color.FromArgb(0xaa, 0xD6, 0x9E, 0x2E)); // 橙黄色
|
_errorBrush = new SolidColorBrush(Color.FromArgb(0xaa, 0xC5, 0x30, 0x30)); // 红色
|
|
DataContext = this;
|
ViewSource = new CollectionViewSource();
|
ViewSource.Filter += CollectionViewSource_Filter;
|
BindingOperations.SetBinding(viewSource, CollectionViewSource.SourceProperty,
|
new Binding(nameof(Datasource))
|
{
|
Source = this,
|
Mode = BindingMode.TwoWay,
|
NotifyOnSourceUpdated = true,
|
});
|
InitializeComponent();
|
InitFromSetting();
|
}
|
|
private void InitFromSetting()
|
{
|
ShowError = bool.Parse(IniHelper.ReadIniData("Log", nameof(ShowError), "True", PathHelper.SettingIniPath));
|
ShowWarn = bool.Parse(IniHelper.ReadIniData("Log", nameof(ShowWarn), "True", PathHelper.SettingIniPath));
|
ShowInfo = bool.Parse(IniHelper.ReadIniData("Log", nameof(ShowInfo), "True", PathHelper.SettingIniPath));
|
ShowDebug = bool.Parse(IniHelper.ReadIniData("Log", nameof(ShowDebug), "True", PathHelper.SettingIniPath));
|
ShowAll = bool.Parse(IniHelper.ReadIniData("Log", nameof(ShowAll), "False", PathHelper.SettingIniPath));
|
}
|
|
private void WriteSetting(string name, object value)
|
{
|
IniHelper.WriteIniData("Log", name, value.ToString(), PathHelper.SettingIniPath);
|
}
|
|
partial void OnShowErrorChanged(bool value)
|
{
|
WriteSetting(nameof(ShowError), value);
|
ViewSource.View.Refresh();
|
}
|
|
partial void OnShowWarnChanged(bool value)
|
{
|
WriteSetting(nameof(ShowWarn), value);
|
ViewSource.View.Refresh();
|
}
|
|
partial void OnShowInfoChanged(bool value)
|
{
|
WriteSetting(nameof(ShowInfo), value);
|
ViewSource.View.Refresh();
|
}
|
|
partial void OnShowDebugChanged(bool value)
|
{
|
WriteSetting(nameof(ShowDebug), value);
|
ViewSource.View.Refresh();
|
}
|
|
partial void OnShowAllChanged(bool value)
|
{
|
WriteSetting(nameof(ShowAll), value);
|
ViewSource.View.Refresh();
|
}
|
|
partial void OnSearchTextChanged(string value)
|
{
|
ViewSource.View.Refresh();
|
}
|
|
public void EventsLogged(IEnumerable<Event> Events)
|
{
|
foreach (var e in Events)
|
{
|
HandleLog(e);
|
}
|
}
|
|
private void HandleLog(Event e)
|
{
|
Dispatcher.BeginInvoke(() =>
|
{
|
lock (this)
|
{
|
var item = new LogItem()
|
{
|
e = e
|
};
|
while (Datasource.Count >= 1000)
|
{
|
Datasource.RemoveAt(0);
|
}
|
Datasource.Add(item);
|
log.ScrollIntoView(item);
|
}
|
}, DispatcherPriority.Background);
|
}
|
|
public void Flush()
|
{
|
Log.Flush();
|
}
|
|
private void CollectionViewSource_Filter(object sender, System.Windows.Data.FilterEventArgs e)
|
{
|
if (e.Item is LogItem item)
|
{
|
bool res = true;
|
switch (item.Type)
|
{
|
case 10:
|
res = ShowError || ShowAll;
|
break;
|
case 20:
|
res = ShowWarn || ShowAll;
|
break;
|
case 30:
|
res = ShowInfo || ShowAll;
|
break;
|
case 40:
|
res = ShowDebug || ShowAll;
|
break;
|
default:
|
res = true;
|
break;
|
}
|
if (!string.IsNullOrEmpty(SearchText))
|
{
|
res &= item.ToString().Contains(SearchText);
|
}
|
e.Accepted = res;
|
}
|
}
|
|
private void Button_Click(object sender, System.Windows.RoutedEventArgs e)
|
{
|
Datasource.Clear();
|
}
|
|
private volatile bool showingResult = false;
|
public void ShowResult(Verdict verdict)
|
{
|
if (showingResult)
|
{
|
return;
|
}
|
showingResult = true;
|
Task.Run(() =>
|
{
|
Dispatcher.BeginInvoke(() =>
|
{
|
string title = "PASS";
|
resultShow.Background = _successBrush;
|
if (verdict == Verdict.Aborted)
|
{
|
resultShow.Background = _warnBrush;
|
title = "Aborted";
|
}
|
else if (verdict == Verdict.NotSet)
|
{
|
resultShow.Background = _debugBrush;
|
title = "NotSet";
|
}
|
else if (verdict == Verdict.Fail)
|
{
|
resultShow.Background = _errorBrush;
|
title = "FAIL";
|
}
|
else if (verdict == Verdict.Error)
|
{
|
resultShow.Background = _errorBrush;
|
title = "Error";
|
}
|
resultLabel.Content = title;
|
resultShow.Visibility = System.Windows.Visibility.Visible;
|
});
|
Thread.Sleep(3000);
|
Dispatcher.BeginInvoke(() =>
|
{
|
resultShow.Visibility = System.Windows.Visibility.Collapsed;
|
});
|
showingResult = false;
|
});
|
}
|
}
|
}
|