Add Avalonia MessageBox

This commit is contained in:
Michael Bucari-Tovo 2022-07-14 00:50:50 -06:00
parent 31d6fc8197
commit 7a8e910697
20 changed files with 570 additions and 35 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

View File

@ -0,0 +1,77 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Media;
using LibationWinForms.AvaloniaUI.Views.Dialogs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibationWinForms.AvaloniaUI.ViewModels.Dialogs
{
public class MessageBoxViewModel
{
private string _message;
public string Message { get { return _message; } set { _message = value; } }
public string Caption { get; } = "Message Box";
private MessageBoxButtons _button;
private MessageBoxIcon _icon;
private MessageBoxDefaultButton _defaultButton;
public MessageBoxButtons Buttons => _button;
public bool IsAsterisk => _icon == MessageBoxIcon.Asterisk;
public bool IsError => _icon == MessageBoxIcon.Error;
public bool IsQuestion => _icon == MessageBoxIcon.Question;
public bool IsExclamation => _icon == MessageBoxIcon.Exclamation;
public bool HasButton3 => !string.IsNullOrEmpty(Button3Text);
public bool HasButton2 => !string.IsNullOrEmpty(Button2Text);
public int WindowHeight { get;private set; }
public int WindowWidth { get;private set; }
public string Button1Text => _button switch
{
MessageBoxButtons.OK => "OK",
MessageBoxButtons.OKCancel => "OK",
MessageBoxButtons.AbortRetryIgnore => "Abort",
MessageBoxButtons.YesNoCancel => "Yes",
MessageBoxButtons.YesNo => "Yes",
MessageBoxButtons.RetryCancel => "Retry",
MessageBoxButtons.CancelTryContinue => "Cancel",
_ => string.Empty,
};
public string Button2Text => _button switch
{
MessageBoxButtons.OKCancel => "Cancel",
MessageBoxButtons.AbortRetryIgnore => "Retry",
MessageBoxButtons.YesNoCancel => "No",
MessageBoxButtons.YesNo => "No",
MessageBoxButtons.RetryCancel => "Cancel",
MessageBoxButtons.CancelTryContinue => "Try",
_ => string.Empty,
};
public string Button3Text => _button switch
{
MessageBoxButtons.AbortRetryIgnore => "Ignore",
MessageBoxButtons.YesNoCancel => "Cancel",
MessageBoxButtons.CancelTryContinue => "Continue",
_ => string.Empty,
};
public MessageBoxViewModel() { }
public MessageBoxViewModel(string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultBtn)
{
Message = message;
Caption = caption;
_button = buttons;
_icon = icon;
_defaultButton = defaultBtn;
}
}
}

View File

@ -0,0 +1,12 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace LibationWinForms.AvaloniaUI.ViewModels
{
public class MainWindowViewModel
{
}
}

View File

@ -9,6 +9,7 @@ using DataLayer;
using Dinah.Core;
using FileLiberator;
using LibationFileManager;
using LibationWinForms.AvaloniaUI.Views.Dialogs;
using ReactiveUI;
namespace LibationWinForms.AvaloniaUI.ViewModels
@ -152,7 +153,7 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
finally
{
if (Result == ProcessBookResult.None)
Result = showRetry(LibraryBook);
Result = await showRetry(LibraryBook);
Status = Result switch
{
@ -313,15 +314,15 @@ namespace LibationWinForms.AvaloniaUI.ViewModels
#region Failure Handler
private ProcessBookResult showRetry(LibraryBook libraryBook)
private async Task<ProcessBookResult> showRetry(LibraryBook libraryBook)
{
Logger.Error("ERROR. All books have not been processed. Most recent book: processing failed");
System.Windows.Forms.DialogResult? dialogResult = Configuration.Instance.BadBook switch
DialogResult? dialogResult = Configuration.Instance.BadBook switch
{
Configuration.BadBookAction.Abort => System.Windows.Forms.DialogResult.Abort,
Configuration.BadBookAction.Retry => System.Windows.Forms.DialogResult.Retry,
Configuration.BadBookAction.Ignore => System.Windows.Forms.DialogResult.Ignore,
Configuration.BadBookAction.Abort => DialogResult.Abort,
Configuration.BadBookAction.Retry => DialogResult.Retry,
Configuration.BadBookAction.Ignore => DialogResult.Ignore,
Configuration.BadBookAction.Ask => null,
_ => null
};
@ -346,9 +347,9 @@ $@" Title: {libraryBook.Book.Title}
}
// if null then ask user
dialogResult ??= System.Windows.Forms.MessageBox.Show(string.Format(SkipDialogText + "\r\n\r\nSee Settings to avoid this box in the future.", details), "Skip importing this book?", SkipDialogButtons, System.Windows.Forms.MessageBoxIcon.Question, SkipDialogDefaultButton);
dialogResult ??= await MessageBox.Show(string.Format(SkipDialogText + "\r\n\r\nSee Settings to avoid this box in the future.", details), "Skip importing this book?", SkipDialogButtons, MessageBoxIcon.Question, SkipDialogDefaultButton);
if (dialogResult == System.Windows.Forms.DialogResult.Abort)
if (dialogResult == DialogResult.Abort)
return ProcessBookResult.FailedAbort;
if (dialogResult == SkipResult)
@ -373,9 +374,9 @@ An error occurred while trying to process this book.
- IGNORE: Permanently ignore this book. Continue processing books. (Will not try this book again later.)
".Trim();
private System.Windows.Forms.MessageBoxButtons SkipDialogButtons => System.Windows.Forms.MessageBoxButtons.AbortRetryIgnore;
private System.Windows.Forms.MessageBoxDefaultButton SkipDialogDefaultButton => System.Windows.Forms.MessageBoxDefaultButton.Button1;
private System.Windows.Forms.DialogResult SkipResult => System.Windows.Forms.DialogResult.Ignore;
private MessageBoxButtons SkipDialogButtons => MessageBoxButtons.AbortRetryIgnore;
private MessageBoxDefaultButton SkipDialogDefaultButton => MessageBoxDefaultButton.Button1;
private DialogResult SkipResult => DialogResult.Ignore;
}
#endregion

View File

@ -0,0 +1,240 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using LibationWinForms.AvaloniaUI.ViewModels.Dialogs;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace LibationWinForms.AvaloniaUI.Views.Dialogs
{
public class MessageBox
{
/// <summary>Displays a message box with the specified text, caption, buttons, icon, and default button.</summary>
/// <param name="text">The text to display in the message box.</param>
/// <param name="caption">The text to display in the title bar of the message box.</param>
/// <param name="buttons">One of the <see cref="T:System.Windows.Forms.MessageBoxButtons" /> values that specifies which buttons to display in the message box.</param>
/// <param name="icon">One of the <see cref="T:System.Windows.Forms.MessageBoxIcon" /> values that specifies which icon to display in the message box.</param>
/// <param name="defaultButton">One of the <see cref="T:System.Windows.Forms.MessageBoxDefaultButton" /> values that specifies the default button for the message box.</param>
/// <returns>One of the <see cref="T:System.Windows.Forms.DialogResult" /> values.</returns>
/// <exception cref="T:System.ComponentModel.InvalidEnumArgumentException">
/// <paramref name="buttons" /> is not a member of <see cref="T:System.Windows.Forms.MessageBoxButtons" />.
/// -or-
/// <paramref name="icon" /> is not a member of <see cref="T:System.Windows.Forms.MessageBoxIcon" />.
/// -or-
/// <paramref name="defaultButton" /> is not a member of <see cref="T:System.Windows.Forms.MessageBoxDefaultButton" />.</exception>
/// <exception cref="T:System.InvalidOperationException">An attempt was made to display the <see cref="T:System.Windows.Forms.MessageBox" /> in a process that is not running in User Interactive mode. This is specified by the <see cref="P:System.Windows.Forms.SystemInformation.UserInteractive" /> property.</exception>
public static async Task<DialogResult> Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
{
return await ShowCore(null, text, caption, buttons, icon, defaultButton);
}
/// <summary>Displays a message box with specified text, caption, buttons, and icon.</summary>
/// <param name="text">The text to display in the message box.</param>
/// <param name="caption">The text to display in the title bar of the message box.</param>
/// <param name="buttons">One of the <see cref="T:System.Windows.Forms.MessageBoxButtons" /> values that specifies which buttons to display in the message box.</param>
/// <param name="icon">One of the <see cref="T:System.Windows.Forms.MessageBoxIcon" /> values that specifies which icon to display in the message box.</param>
/// <returns>One of the <see cref="T:System.Windows.Forms.DialogResult" /> values.</returns>
/// <exception cref="T:System.ComponentModel.InvalidEnumArgumentException">The <paramref name="buttons" /> parameter specified is not a member of <see cref="T:System.Windows.Forms.MessageBoxButtons" />.
/// -or-
/// The <paramref name="icon" /> parameter specified is not a member of <see cref="T:System.Windows.Forms.MessageBoxIcon" />.</exception>
/// <exception cref="T:System.InvalidOperationException">An attempt was made to display the <see cref="T:System.Windows.Forms.MessageBox" /> in a process that is not running in User Interactive mode. This is specified by the <see cref="P:System.Windows.Forms.SystemInformation.UserInteractive" /> property.</exception>
public static async Task<DialogResult> Show(string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon)
{
return await ShowCore(null, text, caption, buttons, icon, MessageBoxDefaultButton.Button1);
}
/// <summary>Displays a message box with specified text, caption, and buttons.</summary>
/// <param name="text">The text to display in the message box.</param>
/// <param name="caption">The text to display in the title bar of the message box.</param>
/// <param name="buttons">One of the <see cref="T:System.Windows.Forms.MessageBoxButtons" /> values that specifies which buttons to display in the message box.</param>
/// <returns>One of the <see cref="T:System.Windows.Forms.DialogResult" /> values.</returns>
/// <exception cref="T:System.ComponentModel.InvalidEnumArgumentException">The <paramref name="buttons" /> parameter specified is not a member of <see cref="T:System.Windows.Forms.MessageBoxButtons" />.</exception>
/// <exception cref="T:System.InvalidOperationException">An attempt was made to display the <see cref="T:System.Windows.Forms.MessageBox" /> in a process that is not running in User Interactive mode. This is specified by the <see cref="P:System.Windows.Forms.SystemInformation.UserInteractive" /> property.</exception>
public static async Task<DialogResult> Show(string text, string caption, MessageBoxButtons buttons)
{
return await ShowCore(null, text, caption, buttons, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
}
/// <summary>Displays a message box with specified text and caption.</summary>
/// <param name="text">The text to display in the message box.</param>
/// <param name="caption">The text to display in the title bar of the message box.</param>
/// <returns>One of the <see cref="T:System.Windows.Forms.DialogResult" /> values.</returns>
public static async Task<DialogResult> Show(string text, string caption)
{
return await ShowCore(null, text, caption, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
}
/// <summary>Displays a message box with specified text.</summary>
/// <param name="text">The text to display in the message box.</param>
/// <returns>One of the <see cref="T:System.Windows.Forms.DialogResult" /> values.</returns>
public static async Task<DialogResult> Show(string text)
{
return await ShowCore(null, text, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
}
/// <summary>Displays a message box in front of the specified object and with the specified text, caption, buttons, icon, default button, and options.</summary>
/// <param name="owner">An implementation of <see cref="T:System.Windows.Forms.IWin32Window" /> that will own the modal dialog box.</param>
/// <param name="text">The text to display in the message box.</param>
/// <param name="caption">The text to display in the title bar of the message box.</param>
/// <param name="buttons">One of the <see cref="T:System.Windows.Forms.MessageBoxButtons" /> values that specifies which buttons to display in the message box.</param>
/// <param name="icon">One of the <see cref="T:System.Windows.Forms.MessageBoxIcon" /> values that specifies which icon to display in the message box.</param>
/// <param name="defaultButton">One of the <see cref="T:System.Windows.Forms.MessageBoxDefaultButton" /> values the specifies the default button for the message box.</param>
/// <param name="options">One of the <see cref="T:System.Windows.Forms.MessageBoxOptions" /> values that specifies which display and association options will be used for the message box. You may pass in 0 if you wish to use the defaults.</param>
/// <returns>One of the <see cref="T:System.Windows.Forms.DialogResult" /> values.</returns>
/// <exception cref="T:System.ComponentModel.InvalidEnumArgumentException">
/// <paramref name="buttons" /> is not a member of <see cref="T:System.Windows.Forms.MessageBoxButtons" />.
/// -or-
/// <paramref name="icon" /> is not a member of <see cref="T:System.Windows.Forms.MessageBoxIcon" />.
/// -or-
/// <paramref name="defaultButton" /> is not a member of <see cref="T:System.Windows.Forms.MessageBoxDefaultButton" />.</exception>
/// <exception cref="T:System.InvalidOperationException">An attempt was made to display the <see cref="T:System.Windows.Forms.MessageBox" /> in a process that is not running in User Interactive mode. This is specified by the <see cref="P:System.Windows.Forms.SystemInformation.UserInteractive" /> property.</exception>
/// <exception cref="T:System.ArgumentException">
/// -or-
/// <paramref name="buttons" /> specified an invalid combination of <see cref="T:System.Windows.Forms.MessageBoxButtons" />.</exception>
public static async Task<DialogResult> Show(Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
{
return await ShowCore(owner, text, caption, buttons, icon, defaultButton);
}
/// <summary>Displays a message box in front of the specified object and with the specified text, caption, buttons, and icon.</summary>
/// <param name="owner">An implementation of <see cref="T:System.Windows.Forms.IWin32Window" /> that will own the modal dialog box.</param>
/// <param name="text">The text to display in the message box.</param>
/// <param name="caption">The text to display in the title bar of the message box.</param>
/// <param name="buttons">One of the <see cref="T:System.Windows.Forms.MessageBoxButtons" /> values that specifies which buttons to display in the message box.</param>
/// <param name="icon">One of the <see cref="T:System.Windows.Forms.MessageBoxIcon" /> values that specifies which icon to display in the message box.</param>
/// <returns>One of the <see cref="T:System.Windows.Forms.DialogResult" /> values.</returns>
/// <exception cref="T:System.ComponentModel.InvalidEnumArgumentException">
/// <paramref name="buttons" /> is not a member of <see cref="T:System.Windows.Forms.MessageBoxButtons" />.
/// -or-
/// <paramref name="icon" /> is not a member of <see cref="T:System.Windows.Forms.MessageBoxIcon" />.</exception>
/// <exception cref="T:System.InvalidOperationException">An attempt was made to display the <see cref="T:System.Windows.Forms.MessageBox" /> in a process that is not running in User Interactive mode. This is specified by the <see cref="P:System.Windows.Forms.SystemInformation.UserInteractive" /> property.</exception>
public static async Task<DialogResult> Show(Window owner, string text, string caption, MessageBoxButtons buttons, MessageBoxIcon icon)
{
return await ShowCore(owner, text, caption, buttons, icon, MessageBoxDefaultButton.Button1);
}
/// <summary>Displays a message box in front of the specified object and with the specified text, caption, and buttons.</summary>
/// <param name="owner">An implementation of <see cref="T:System.Windows.Forms.IWin32Window" /> that will own the modal dialog box.</param>
/// <param name="text">The text to display in the message box.</param>
/// <param name="caption">The text to display in the title bar of the message box.</param>
/// <param name="buttons">One of the <see cref="T:System.Windows.Forms.MessageBoxButtons" /> values that specifies which buttons to display in the message box.</param>
/// <returns>One of the <see cref="T:System.Windows.Forms.DialogResult" /> values.</returns>
/// <exception cref="T:System.ComponentModel.InvalidEnumArgumentException">
/// <paramref name="buttons" /> is not a member of <see cref="T:System.Windows.Forms.MessageBoxButtons" />.</exception>
/// <exception cref="T:System.InvalidOperationException">An attempt was made to display the <see cref="T:System.Windows.Forms.MessageBox" /> in a process that is not running in User Interactive mode. This is specified by the <see cref="P:System.Windows.Forms.SystemInformation.UserInteractive" /> property.</exception>
public static async Task<DialogResult> Show(Window owner, string text, string caption, MessageBoxButtons buttons)
{
return await ShowCore(owner, text, caption, buttons, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
}
/// <summary>Displays a message box in front of the specified object and with the specified text and caption.</summary>
/// <param name="owner">An implementation of <see cref="T:System.Windows.Forms.IWin32Window" /> that will own the modal dialog box.</param>
/// <param name="text">The text to display in the message box.</param>
/// <param name="caption">The text to display in the title bar of the message box.</param>
/// <returns>One of the <see cref="T:System.Windows.Forms.DialogResult" /> values.</returns>
public static async Task<DialogResult> Show(Window owner, string text, string caption)
{
return await ShowCore(owner, text, caption, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
}
/// <summary>Displays a message box in front of the specified object and with the specified text.</summary>
/// <param name="owner">An implementation of <see cref="T:System.Windows.Forms.IWin32Window" /> that will own the modal dialog box.</param>
/// <param name="text">The text to display in the message box.</param>
/// <returns>One of the <see cref="T:System.Windows.Forms.DialogResult" /> values.</returns>
public static async Task<DialogResult> Show(Window owner, string text)
{
return await ShowCore(owner, text, string.Empty, MessageBoxButtons.OK, MessageBoxIcon.None, MessageBoxDefaultButton.Button1);
}
private static async Task<DialogResult> ShowCore(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
{
if (Avalonia.Threading.Dispatcher.UIThread.CheckAccess())
return await ShowCore2(owner, message, caption, buttons, icon, defaultButton);
else
return await Avalonia.Threading.Dispatcher.UIThread.InvokeAsync(() => ShowCore2(owner, message, caption, buttons, icon, defaultButton));
}
private static async Task<DialogResult> ShowCore2(Window owner, string message, string caption, MessageBoxButtons buttons, MessageBoxIcon icon, MessageBoxDefaultButton defaultButton)
{
var dialog = new MessageBoxWindow();
var vm = new MessageBoxViewModel(message, caption, buttons, icon, defaultButton);
dialog.DataContext = vm;
dialog.CanResize = false;
var thisScreen = (owner ?? dialog).Screens.ScreenFromVisual(owner ?? dialog);
var tbx = dialog.FindControl<TextBlock>("messageTextBlock");
tbx.Text = message;
var maxSize = new Size(0.6 * thisScreen.Bounds.Width - 72, 0.9 * thisScreen.Bounds.Height);
var desiredMax = maxSize;
//Try to minimize the TextBlock area.
List<(double, Size)> areas = new();
for (int i = 0; i < 20; i++)
{
tbx.Measure(desiredMax);
var area = tbx.DesiredSize.Width * tbx.DesiredSize.Height;
areas.Add((area, new Size(tbx.DesiredSize.Width, tbx.DesiredSize.Height)));
if (tbx.DesiredSize.Height < maxSize.Height - 20)
{
if (desiredMax.Width / 2 < tbx.MinWidth)
desiredMax = new Size(desiredMax.Width * 1.5 + 1, desiredMax.Height);
else
desiredMax = new Size(desiredMax.Width / 2, desiredMax.Height);
}
}
var min = areas.Min(a => a.Item1);
var mindim = areas.First(a => a.Item1 == min);
var desiredSize = new Size(dialog.MinWidth - tbx.MinWidth + mindim.Item2.Width, dialog.MinHeight - tbx.MinHeight + mindim.Item2.Height);
dialog.Width = desiredSize.Width;
dialog.Height = desiredSize.Height;
tbx.Width = mindim.Item2.Width;
tbx.Height = mindim.Item2.Height;
if (owner is null)
{
if (Application.Current.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
return await dialog.ShowDialog<DialogResult>(desktop.MainWindow);
}
else
{
var window = new Window
{
IsVisible = false,
Height = 1,
Width = 1,
SystemDecorations = SystemDecorations.None,
ShowInTaskbar = false
};
window.Show();
var result = await dialog.ShowDialog<DialogResult>(window);
window.Close();
return result;
}
}
else
{
return await dialog.ShowDialog<DialogResult>(owner);
}
}
}
}

View File

@ -0,0 +1,41 @@
<Window xmlns="https://github.com/avaloniaui"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:vm="clr-namespace:LibationWinForms.AvaloniaUI.ViewModels"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
mc:Ignorable="d" d:DesignWidth="375" d:DesignHeight="130" MinWidth="385" MinHeight="150"
x:Class="LibationWinForms.AvaloniaUI.Views.Dialogs.MessageBoxWindow"
Title="{Binding Caption}" HasSystemDecorations="True" ShowInTaskbar="True">
<Grid ColumnDefinitions="*" RowDefinitions="*,Auto">
<StackPanel Orientation="Horizontal"
Grid.Row="0" Grid.Column="0"
Margin="10" VerticalAlignment="Top">
<Panel
Grid.Column="0"
Margin="10" VerticalAlignment="Top">
<Image IsVisible="{Binding IsAsterisk}" Stretch="None" Source="/AvaloniaUI/Assets/MBIcons/Asterisk.png"/>
<Image IsVisible="{Binding IsError}" Stretch="None" Source="/AvaloniaUI/Assets/MBIcons/error.png"/>
<Image IsVisible="{Binding IsQuestion}" Stretch="None" Source="/AvaloniaUI/Assets/MBIcons/Question.png"/>
<Image IsVisible="{Binding IsExclamation}" Stretch="None" Source="/AvaloniaUI/Assets/MBIcons/Exclamation.png"/>
</Panel>
<TextBlock Name="messageTextBlock" Background="Snow" MinHeight="80" MinWidth="300" TextWrapping="WrapWithOverflow" HorizontalAlignment="Left" VerticalAlignment="Top" FontSize="12" Text="{Binding Message}" />
</StackPanel>
<Grid Grid.Row="1" VerticalAlignment="Bottom" HorizontalAlignment="Right" Margin="0,0,15,10" ColumnDefinitions="Auto, Auto, Auto">
<Button Grid.Column="0" MinWidth="80" MinHeight="25" Name="Button1" Click="Button1_Click" Margin="5">
<TextBlock VerticalAlignment="Center" Text="{Binding Button1Text}"/>
</Button>
<Button Grid.Column="1" IsVisible="{Binding HasButton2}" MinWidth="80" MinHeight="25" Name="Button2" Click="Button2_Click" Margin="5">
<TextBlock VerticalAlignment="Center" Text="{Binding Button2Text}"/>
</Button>
<Button Grid.Column="2" IsVisible="{Binding HasButton3}" MinWidth="80" MinHeight="25" Name="Button3" Click="Button3_Click" Content="Cancel" Margin="5">
<TextBlock VerticalAlignment="Center" Text="{Binding Button3Text}"/>
</Button>
</Grid>
</Grid>
</Window>

View File

@ -0,0 +1,115 @@
using Avalonia;
using Avalonia.Controls;
using Avalonia.Markup.Xaml;
using Avalonia.ReactiveUI;
using LibationWinForms.AvaloniaUI.ViewModels.Dialogs;
namespace LibationWinForms.AvaloniaUI.Views.Dialogs
{
public enum DialogResult
{
None = 0,
OK = 1,
Cancel = 2,
Abort = 3,
Retry = 4,
Ignore = 5,
Yes = 6,
No = 7,
TryAgain = 10,
Continue = 11
}
public enum MessageBoxIcon
{
None = 0,
Error = 16,
Hand = 16,
Stop = 16,
Question = 32,
Exclamation = 48,
Warning = 48,
Asterisk = 64,
Information = 64
}
public enum MessageBoxButtons
{
OK,
OKCancel,
AbortRetryIgnore,
YesNoCancel,
YesNo,
RetryCancel,
CancelTryContinue
}
public enum MessageBoxDefaultButton
{
Button1,
Button2 = 256,
Button3 = 512,
}
public partial class MessageBoxWindow : ReactiveWindow<MessageBoxViewModel>
{
public MessageBoxWindow()
{
InitializeComponent();
#if DEBUG
this.AttachDevTools();
#endif
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
public DialogResult DialogResult { get; private set; }
public void Button1_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
{
var vm = DataContext as MessageBoxViewModel;
DialogResult = vm.Buttons switch
{
MessageBoxButtons.OK => DialogResult.OK,
MessageBoxButtons.OKCancel => DialogResult.OK,
MessageBoxButtons.AbortRetryIgnore => DialogResult.Abort,
MessageBoxButtons.YesNoCancel => DialogResult.Yes,
MessageBoxButtons.YesNo => DialogResult.Yes,
MessageBoxButtons.RetryCancel => DialogResult.Retry,
MessageBoxButtons.CancelTryContinue => DialogResult.Cancel,
_ => DialogResult.None
};
Close(DialogResult);
}
public void Button2_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
{
var vm = DataContext as MessageBoxViewModel;
DialogResult = vm.Buttons switch
{
MessageBoxButtons.OKCancel => DialogResult.Cancel,
MessageBoxButtons.AbortRetryIgnore => DialogResult.Retry,
MessageBoxButtons.YesNoCancel => DialogResult.No,
MessageBoxButtons.YesNo => DialogResult.No,
MessageBoxButtons.RetryCancel => DialogResult.Cancel,
MessageBoxButtons.CancelTryContinue => DialogResult.TryAgain,
_ => DialogResult.None
};
Close(DialogResult);
}
public void Button3_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
{
var vm = DataContext as MessageBoxViewModel;
DialogResult = vm.Buttons switch
{
MessageBoxButtons.AbortRetryIgnore => DialogResult.Ignore,
MessageBoxButtons.YesNoCancel => DialogResult.Cancel,
MessageBoxButtons.CancelTryContinue => DialogResult.Continue,
_ => DialogResult.None
};
Close(DialogResult);
}
}
}

View File

@ -1,4 +1,5 @@
using ApplicationServices;
using LibationWinForms.AvaloniaUI.Views.Dialogs;
using System;
using System.Linq;
@ -9,7 +10,7 @@ namespace LibationWinForms.AvaloniaUI.Views
{
private void Configure_Export() { }
public void exportLibraryToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
public async void exportLibraryToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
try
{
@ -37,7 +38,7 @@ namespace LibationWinForms.AvaloniaUI.Views
break;
}
System.Windows.Forms.MessageBox.Show("Library exported to:\r\n" + saveFileDialog.FileName);
await MessageBox.Show("Library exported to:\r\n" + saveFileDialog.FileName);
}
catch (Exception ex)
{

View File

@ -1,7 +1,9 @@
using Avalonia.Input;
using LibationWinForms.AvaloniaUI.Views.Dialogs;
using LibationWinForms.Dialogs;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace LibationWinForms.AvaloniaUI.Views
{
@ -13,22 +15,22 @@ namespace LibationWinForms.AvaloniaUI.Views
public void filterHelpBtn_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
=> new SearchSyntaxDialog().ShowDialog();
public void filterSearchTb_KeyPress(object sender, KeyEventArgs e)
public async void filterSearchTb_KeyPress(object sender, KeyEventArgs e)
{
if (e.Key == Key.Return)
{
performFilter(this.filterSearchTb.Text);
await performFilter(this.filterSearchTb.Text);
// silence the 'ding'
e.Handled = true;
}
}
public void filterBtn_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
=> performFilter(this.filterSearchTb.Text);
public async void filterBtn_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
=> await performFilter(this.filterSearchTb.Text);
private string lastGoodFilter = "";
private void performFilter(string filterString)
private async Task performFilter(string filterString)
{
this.filterSearchTb.Text = filterString;
@ -39,10 +41,10 @@ namespace LibationWinForms.AvaloniaUI.Views
}
catch (Exception ex)
{
System.Windows.Forms.MessageBox.Show($"Bad filter string:\r\n\r\n{ex.Message}", "Bad filter string", System.Windows.Forms.MessageBoxButtons.OK, System.Windows.Forms.MessageBoxIcon.Error);
await MessageBox.Show($"Bad filter string:\r\n\r\n{ex.Message}", "Bad filter string", MessageBoxButtons.OK, MessageBoxIcon.Error);
// re-apply last good filter
performFilter(lastGoodFilter);
await performFilter(lastGoodFilter);
}
}
}

View File

@ -1,4 +1,5 @@
using DataLayer;
using LibationWinForms.AvaloniaUI.Views.Dialogs;
using System;
using System.Linq;
using System.Threading.Tasks;
@ -40,15 +41,15 @@ namespace LibationWinForms.AvaloniaUI.Views
public async void convertAllM4bToMp3ToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs args)
{
var result = System.Windows.Forms.MessageBox.Show(
var result = await MessageBox.Show(
"This converts all m4b titles in your library to mp3 files. Original files are not deleted."
+ "\r\nFor large libraries this will take a long time and will take up more disk space."
+ "\r\n\r\nContinue?"
+ "\r\n\r\n(To always download titles as mp3 instead of m4b, go to Settings: Download my books as .MP3 files)",
"Convert all M4b => Mp3?",
System.Windows.Forms.MessageBoxButtons.YesNo,
System.Windows.Forms.MessageBoxIcon.Warning);
if (result == System.Windows.Forms.DialogResult.Yes)
MessageBoxButtons.YesNo,
MessageBoxIcon.Warning);
if (result == DialogResult.Yes)
{
SetQueueCollapseState(false);
await Task.Run(() => processBookQueue1.AddConvertMp3(ApplicationServices.DbContexts.GetLibrary_Flat_NoTracking()

View File

@ -1,6 +1,7 @@
using DataLayer;
using Dinah.Core;
using LibationFileManager;
using LibationWinForms.AvaloniaUI.Views.Dialogs;
using System;
using System.Linq;
@ -15,7 +16,7 @@ namespace LibationWinForms.AvaloniaUI.Views
SetQueueCollapseState(collapseState);
}
public void ProductsDisplay_LiberateClicked(object sender, LibraryBook libraryBook)
public async void ProductsDisplay_LiberateClicked(object sender, LibraryBook libraryBook)
{
try
{
@ -38,7 +39,7 @@ namespace LibationWinForms.AvaloniaUI.Views
if (!Go.To.File(filePath?.ShortPathName))
{
var suffix = string.IsNullOrWhiteSpace(filePath) ? "" : $":\r\n{filePath}";
System.Windows.Forms.MessageBox.Show($"File not found" + suffix);
await MessageBox.Show($"File not found" + suffix);
}
}
}

View File

@ -2,6 +2,7 @@
using AudibleUtilities;
using Avalonia.Controls;
using LibationFileManager;
using LibationWinForms.AvaloniaUI.Views.Dialogs;
using LibationWinForms.Dialogs;
using System;
using System.Collections.Generic;
@ -49,9 +50,9 @@ namespace LibationWinForms.AvaloniaUI.Views
}
}
public void noAccountsYetAddAccountToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
public async void noAccountsYetAddAccountToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
System.Windows.Forms.MessageBox.Show("To load your Audible library, come back here to the Import menu after adding your account");
await MessageBox.Show("To load your Audible library, come back here to the Import menu after adding your account");
new AccountsDialog().ShowDialog();
}
@ -91,7 +92,7 @@ namespace LibationWinForms.AvaloniaUI.Views
// this is here instead of ScanEnd so that the following is only possible when it's user-initiated, not automatic loop
if (Configuration.Instance.ShowImportedStats && newAdded > 0)
System.Windows.Forms.MessageBox.Show($"Total processed: {totalProcessed}\r\nNew: {newAdded}");
await MessageBox.Show($"Total processed: {totalProcessed}\r\nNew: {newAdded}");
}
catch (Exception ex)
{

View File

@ -1,4 +1,5 @@
using LibationWinForms.Dialogs;
using LibationWinForms.AvaloniaUI.Views.Dialogs;
using LibationWinForms.Dialogs;
using System;
using System.Linq;
@ -13,7 +14,7 @@ namespace LibationWinForms.AvaloniaUI.Views
public void basicSettingsToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e) => new SettingsDialog().ShowDialog();
public void aboutToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
=> System.Windows.Forms.MessageBox.Show($"Running Libation version {AppScaffolding.LibationScaffolding.BuildVersion}", $"Libation v{AppScaffolding.LibationScaffolding.BuildVersion}");
public async void aboutToolStripMenuItem_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
=> await MessageBox.Show($"Running Libation version {AppScaffolding.LibationScaffolding.BuildVersion}", $"Libation v{AppScaffolding.LibationScaffolding.BuildVersion}");
}
}

View File

@ -14,7 +14,7 @@
<Border BorderBrush="{DynamicResource DataGridGridLinesBrush}" BorderThickness="2" Padding="15">
<Grid RowDefinitions="Auto,Auto,*,Auto">
<Grid Grid.Row="0" ColumnDefinitions="1*, Auto">
<Grid Grid.Row="0" ColumnDefinitions="1*,Auto">
<!-- Menu Strip -->
<Menu Grid.Column="0" VerticalAlignment="Top">
@ -106,7 +106,9 @@
<MenuItem Click="aboutToolStripMenuItem_Click" Header="A_bout..." />
</MenuItem>
</Menu>
<Button Grid.Column="1" Content="Show Message Box" Click="ShowMessageBoxButton_Click" />
<StackPanel Name="scanningToolStripMenuItem" Grid.Column="1" Orientation="Horizontal" HorizontalAlignment="Right">
<Button Content="Show Message Box" Click="ShowMessageBoxButton_Click" />
<Image Width="16" Height="16" Source="/AvaloniaUI/Assets/import_16x16.png" />
<TextBlock Name="scanningToolStripMenuItem_Text" Margin="5,0,5,0" VerticalAlignment="Center" Text="Scanning..."/>
</StackPanel>

View File

@ -7,10 +7,18 @@ using System;
using System.Linq;
using Avalonia.Threading;
using LibationWinForms.AvaloniaUI.Views.ProductsGrid;
using Avalonia.ReactiveUI;
using LibationWinForms.AvaloniaUI.ViewModels;
using System.Threading.Tasks;
using ReactiveUI;
using LibationWinForms.AvaloniaUI.ViewModels.Dialogs;
using LibationWinForms.AvaloniaUI.Views.Dialogs;
using Avalonia.Media;
using System.Collections.Generic;
namespace LibationWinForms.AvaloniaUI.Views
{
public partial class MainWindow : Window
public partial class MainWindow : ReactiveWindow<MainWindowViewModel>
{
public MainWindow()
{
@ -46,6 +54,30 @@ namespace LibationWinForms.AvaloniaUI.Views
public void OnLoad() => Load?.Invoke(this, EventArgs.Empty);
public async void ShowMessageBoxButton_Click(object sender, Avalonia.Interactivity.RoutedEventArgs e)
{
await Task.Run(() => DoShowDialogAsync());
}
private async Task DoShowDialogAsync()
{
string caption = "this is a dialog message";
string message =
@"The Collatz conjecture is: This process will eventually reach the number 1, regardless of which positive integer is chosen initially.
If the conjecture is false, it can only be because there is some starting number which gives rise to a sequence that does not contain 1. Such a sequence would either enter a repeating cycle that excludes 1, or increase without bound. No such sequence has been found.
The smallest i such that ai < a0 is called the stopping time of n. Similarly, the smallest k such that ak = 1 is called the total stopping time of n.[3] If one of the indexes i or k doesn't exist, we say that the stopping time or the total stopping time, respectively, is infinite.
The Collatz conjecture asserts that the total stopping time of every n is finite. It is also equivalent to saying that every n >= 2 has a finite stopping time.
Since 3n + 1 is even whenever n is odd, one may instead use the shortcut form of the Collatz function:";
var result = await MessageBox.Show(message, caption);
}
private void FindAllControls()
{
{

View File

@ -99,7 +99,7 @@ namespace LibationWinForms.AvaloniaUI.Views.ProductsGrid
if (button.DataContext is LibraryBookEntry2 lbEntry)
{
var bookDetailsForm = new Dialogs.BookDetailsDialog(lbEntry.LibraryBook);
var bookDetailsForm = new LibationWinForms.Dialogs.BookDetailsDialog(lbEntry.LibraryBook);
if (bookDetailsForm.ShowDialog() == System.Windows.Forms.DialogResult.OK)
lbEntry.Commit(bookDetailsForm.NewTags, bookDetailsForm.BookLiberatedStatus, bookDetailsForm.PdfLiberatedStatus);
}

View File

@ -40,16 +40,24 @@
<ItemGroup>
<AvaloniaResource Include="AvaloniaUI\Assets\**" />
<None Remove=".gitignore" />
<None Remove="AvaloniaUI\Assets\Asterisk.png" />
<None Remove="AvaloniaUI\Assets\cancel.png" />
<None Remove="AvaloniaUI\Assets\completed.png" />
<None Remove="AvaloniaUI\Assets\down.png" />
<None Remove="AvaloniaUI\Assets\edit_25x25.png" />
<None Remove="AvaloniaUI\Assets\error.png" />
<None Remove="AvaloniaUI\Assets\errored.png" />
<None Remove="AvaloniaUI\Assets\Exclamation.png" />
<None Remove="AvaloniaUI\Assets\first.png" />
<None Remove="AvaloniaUI\Assets\glass-with-glow_16.png" />
<None Remove="AvaloniaUI\Assets\import_16x16.png" />
<None Remove="AvaloniaUI\Assets\last.png" />
<None Remove="AvaloniaUI\Assets\LibationStyles.xaml" />
<None Remove="AvaloniaUI\Assets\MBIcons\Asterisk.png" />
<None Remove="AvaloniaUI\Assets\MBIcons\error.png" />
<None Remove="AvaloniaUI\Assets\MBIcons\Exclamation.png" />
<None Remove="AvaloniaUI\Assets\MBIcons\Question.png" />
<None Remove="AvaloniaUI\Assets\Question.png" />
<None Remove="AvaloniaUI\Assets\queued.png" />
<None Remove="AvaloniaUI\Assets\up.png" />
</ItemGroup>