using AnotherReplayReader.Utils; using Microsoft.Win32; using System; using System.Collections.Generic; using System.ComponentModel; using System.IO; using System.Windows; namespace AnotherReplayReader { public sealed class DebugMessageWrapper { public readonly struct Proxy { public readonly string Payload; public Proxy(string text) { Payload = text; } public static Proxy operator +(Proxy p, string text) { return string.IsNullOrEmpty(p.Payload) ? new Proxy(text) : new Proxy(p.Payload + text); } } private readonly object _lock = new(); private readonly List _list = new(); public event Action? NewText; public Proxy DebugMessage { get => new(); set { var text = value.Payload; using var locker = new Lock(_lock); if (NewText is null || _list.Count > 0) { _list.Add(text); if (NewText is not null) { text = string.Join(string.Empty, _list); _list.Clear(); _list.Capacity = 0; } else { return; } } NewText(text); } } public event Action? RequestedSave; public void RequestSave() => RequestedSave?.Invoke(); } /// /// Debug.xaml 的交互逻辑 /// public sealed partial class Debug : Window { public static readonly DebugMessageWrapper Instance = new(); private static readonly object _lock = new(); private static Debug? _window = null; public static void Initialize() { using var locker = new Lock(_lock); if (_window is not null) { return; } var window = new Debug(); window.InitializeComponent(); _window = window; Instance.NewText += _window.AppendText; Instance.RequestedSave += _window.ExportInMainWindow; } public static new void ShowDialog() => Lock.Run(_lock, () => (_window as Window)?.ShowDialog()); protected override void OnClosing(CancelEventArgs e) { e.Cancel = true; Hide(); } private Debug() { } private void OnExportButtonClick(object sender, RoutedEventArgs e) => Export(this); private void OnClearButtonClick(object sender, RoutedEventArgs e) => _textBox.Clear(); private void AppendText(string s) => Dispatcher.InvokeAsync(() => _textBox.AppendText(s)); private void ExportInMainWindow() => Export(Application.Current.MainWindow); private void Export(Window owner) { Dispatcher.Invoke(() => { var saveFileDialog = new SaveFileDialog { Filter = "文本文档 (*.txt)|*.txt|所有文件 (*.*)|*.*", OverwritePrompt = true, }; var result = saveFileDialog.ShowDialog(owner); if (result == true) { using var file = saveFileDialog.OpenFile(); using var writer = new StreamWriter(file); writer.Write(_textBox.Text); } }); } } }