using InABox.Clients; using InABox.Core; using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Runtime.CompilerServices; using System.Windows; using System.Windows.Controls; using System.IO; namespace InABox.Wpf; public enum MessageWindowButtonPosition { Left, Right } public enum MessageWindowResult { None, OK, Cancel, Other } public class MessageWindowButton : INotifyPropertyChanged { public delegate void MessageWindowButtonDelegate(MessageWindow window, MessageWindowButton button); public MessageWindowButtonPosition Position { get; set; } private string _content; public string Content { get => _content; [MemberNotNull(nameof(_content))] set { _content = value; OnPropertyChanged(); } } public MessageWindowButtonDelegate Action { get; set; } public MessageWindowButton(string content, MessageWindowButtonDelegate action, MessageWindowButtonPosition position) { Content = content; Action = action; Position = position; } public event PropertyChangedEventHandler? PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } } /// /// Interaction logic for MessageWindow.xaml /// public partial class MessageWindow : Window, INotifyPropertyChanged { public ObservableCollection Buttons { get; private set; } = new(); public IEnumerable LeftButtons => Buttons.Where(x => x.Position == MessageWindowButtonPosition.Left); public IEnumerable RightButtons => Buttons.Where(x => x.Position == MessageWindowButtonPosition.Right); private string _message = ""; public string Message { get => _message; set { _message = value; OnPropertyChanged(); } } private string _details = ""; public string Details { get => _details; set { _details = value; OnPropertyChanged(); } } public static readonly DependencyProperty ShowDetailsProperty = DependencyProperty.Register(nameof(ShowDetails), typeof(bool), typeof(MessageWindow)); public bool ShowDetails { get => (bool)GetValue(ShowDetailsProperty); set => SetValue(ShowDetailsProperty, value); } public MessageWindowResult Result { get; set; } = MessageWindowResult.None; public object? OtherResult { get; set; } public MessageWindow() { InitializeComponent(); Buttons.CollectionChanged += Buttons_CollectionChanged; } private void Button_Click(object sender, RoutedEventArgs e) { if (sender is not Button button || button.Tag is not MessageWindowButton winButton) return; winButton.Action(this, winButton); } private void Buttons_CollectionChanged(object? sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e) { OnPropertyChanged(nameof(LeftButtons)); OnPropertyChanged(nameof(RightButtons)); } public void AddButton(MessageWindowButton button) { Buttons.Add(button); } public void AddOKButton(string content = "OK") { Buttons.Add(new MessageWindowButton(content, OKButton_Click, MessageWindowButtonPosition.Right)); } public void AddCancelButton(string content = "Cancel") { Buttons.Add(new MessageWindowButton(content, CancelButton_Click, MessageWindowButtonPosition.Right)); } private void CancelButton_Click(MessageWindow window, MessageWindowButton button) { Result = MessageWindowResult.Cancel; Close(); } private void OKButton_Click(MessageWindow window, MessageWindowButton button) { Result = MessageWindowResult.OK; Close(); } public event PropertyChangedEventHandler? PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = "") { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } #region Static Constructors public static void ShowMessage(string message, string title) { var window = new MessageWindow { Message = message, Title = title }; window.AddOKButton(); window.ShowDialog(); } public static bool ShowOKCancel(string message, string title) { var window = new MessageWindow { Message = message, Title = title }; window.AddOKButton(); window.AddCancelButton(); window.ShowDialog(); return window.Result == MessageWindowResult.OK; } public static bool ShowYesNo(string message, string title) { var window = new MessageWindow { Message = message, Title = title }; window.AddOKButton("Yes"); window.AddCancelButton("No"); window.ShowDialog(); return window.Result == MessageWindowResult.OK; } /// /// Display a message box for an exception, giving options to view the logs. /// /// The message to display. Set to to default to the exception message. /// /// /// If , also logs the exception. public static void ShowError(string? message, Exception exception, string title = "Error", bool shouldLog = true) { if (shouldLog) { CoreUtils.LogException(ClientFactory.UserID, exception); } var window = new MessageWindow { Message = message ?? exception.Message, Title = title, Details = CoreUtils.FormatException(exception) }; window.AddButton(new MessageWindowButton("Show Logs", ShowLogs_Click, MessageWindowButtonPosition.Left)); var showDetailsButton = new MessageWindowButton("Show Details", (win, button) => { win.ShowDetails = !win.ShowDetails; button.Content = win.ShowDetails ? "Hide Details" : "Show Details"; }, MessageWindowButtonPosition.Left); window.AddButton(showDetailsButton); window.AddOKButton(); window.ShowDialog(); } private static void ShowLogs_Click(MessageWindow window, MessageWindowButton button) { var console = new MessageWindowConsole("Logs", Path.Combine(CoreUtils.GetPath(), string.Format("{0:yyyy-MM-dd}.log", DateTime.Today))); console.ShowDialog(); } #endregion } public class MessageWindowConsole : Console.Console { public string FileName { get; set; } public MessageWindowConsole(string description, string file) : base(description) { FileName = file; ConsoleControl.AllowLoadLogButton = false; } protected override void OnLoaded() { base.OnLoaded(); if (File.Exists(FileName)) { var lines = File.ReadLines(FileName); ConsoleControl.LoadLogEntries(lines); } } protected override string GetLogDirectory() { return CoreUtils.GetPath(); } }