mirror of
https://github.com/ajisaacs/OpenNest.git
synced 2026-11-14 02:15:07 -05:00
File > Save (Ctrl+S), Save As and Export .nest, with Save and Save As on the toolbar. Save writes to the file saved to this session, else asks for one in the nest's folder; a failed save says why, keeps the nest unsaved and points to Save As. One save or export runs at a time, a nest cannot be closed while one is under way, and the nest Auto Nest is working on is not written, checked again after the file picker. Closing a nest with unsaved changes asks Save / Don't Save / Cancel, as the WinForms nest window does; Exit asks about each unsaved nest in turn, showing it, and reads the list again after each answer, since Auto Nest can finish while a question is open. Cancel, or a save that does not happen, keeps the app open; an unsaved nest still being nested stops Exit with how to stop Auto Nest. Nest load warnings are shown after opening, one dialog at a time and scrolling when long; for nests opened from the command line they appear once the window opens, and --snapshot only notes them in the status. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
73 lines
2.9 KiB
C#
73 lines
2.9 KiB
C#
using System.Threading.Tasks;
|
|
using Avalonia;
|
|
using Avalonia.Controls;
|
|
using Avalonia.Layout;
|
|
using Avalonia.Media;
|
|
|
|
namespace OpenNest.Avalonia
|
|
{
|
|
/// <summary>
|
|
/// A message with a row of buttons ending in Cancel (OK for a plain message). That last
|
|
/// button is the default and Esc, so a stray Enter never discards work, and closing the
|
|
/// dialog counts as it.
|
|
/// </summary>
|
|
internal sealed class ConfirmDialog : Window
|
|
{
|
|
private ConfirmDialog(string title, string message, string[] choices, string cancelText)
|
|
{
|
|
Title = title;
|
|
Width = 460;
|
|
SizeToContent = SizeToContent.Height;
|
|
CanResize = false;
|
|
WindowStartupLocation = WindowStartupLocation.CenterOwner;
|
|
|
|
var buttons = new StackPanel
|
|
{
|
|
Orientation = Orientation.Horizontal,
|
|
HorizontalAlignment = HorizontalAlignment.Right,
|
|
Spacing = 8,
|
|
};
|
|
for (var i = 0; i < choices.Length; i++)
|
|
{
|
|
var index = i;
|
|
var choice = new Button { Content = choices[i] };
|
|
choice.Click += (_, _) => Close(index);
|
|
buttons.Children.Add(choice);
|
|
}
|
|
var cancel = new Button { Content = cancelText, IsDefault = true, IsCancel = true };
|
|
cancel.Click += (_, _) => Close(null);
|
|
buttons.Children.Add(cancel);
|
|
|
|
var panel = new StackPanel { Margin = new Thickness(18), Spacing = 18 };
|
|
// A long message (many load warnings) scrolls rather than pushing the buttons away.
|
|
panel.Children.Add(new ScrollViewer
|
|
{
|
|
MaxHeight = 420,
|
|
Content = new TextBlock { Text = message, TextWrapping = TextWrapping.Wrap },
|
|
});
|
|
panel.Children.Add(buttons);
|
|
Content = panel;
|
|
Opened += (_, _) => cancel.Focus();
|
|
}
|
|
|
|
/// <summary>True when the user chose <paramref name="confirmText"/>.</summary>
|
|
public static async Task<bool> AskAsync(
|
|
Window owner, string title, string message, string confirmText) =>
|
|
await ChooseAsync(owner, title, message, confirmText) == 0;
|
|
|
|
/// <summary>
|
|
/// The index of the choice the user clicked, or -1 for Cancel (also Esc, Enter and
|
|
/// closing the dialog).
|
|
/// </summary>
|
|
public static async Task<int> ChooseAsync(
|
|
Window owner, string title, string message, params string[] choices) =>
|
|
await new ConfirmDialog(title, message, choices, "Cancel")
|
|
.ShowDialog<int?>(owner) ?? -1;
|
|
|
|
/// <summary>A message with only an OK button.</summary>
|
|
public static Task ShowAsync(Window owner, string title, string message) =>
|
|
new ConfirmDialog(title, message, System.Array.Empty<string>(), "OK")
|
|
.ShowDialog<int?>(owner);
|
|
}
|
|
}
|