using System;
using System.Linq;
using System.Threading.Tasks;
using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.VisualTree;
using AvaloniaEdit;
using MarkdownEditor.Constants;
using MarkdownEditor.ViewModels;
namespace MarkdownEditor.Views;
///
/// Main application window.
/// Handles initialization and coordination between the view and view model.
///
public partial class MainWindow : Window
{
private bool _isClosingConfirmed = false;
///
/// Initializes a new instance of the class.
///
public MainWindow()
{
InitializeComponent();
// Subscribe to pointer pressed to capture selection before command executes
this.AddHandler(Button.PointerPressedEvent, OnButtonPointerPressed, Avalonia.Interactivity.RoutingStrategies.Tunnel);
}
///
protected override void OnOpened(EventArgs e)
{
base.OnOpened(e);
if (DataContext is MainWindowViewModel viewModel)
{
viewModel.StorageProvider = StorageProvider;
// Restore session after StorageProvider is set
_ = viewModel.RestoreSessionAsync();
}
}
///
protected override async void OnClosing(WindowClosingEventArgs e)
{
if (DataContext is not MainWindowViewModel viewModel)
{
base.OnClosing(e);
return;
}
// If we've already confirmed the close (from a previous call), just save session and close
if (_isClosingConfirmed)
{
await viewModel.SaveSessionAsync();
base.OnClosing(e);
return;
}
// Check for unsaved changes
if (viewModel.HasUnsavedChanges())
{
// Cancel the close event to prevent immediate closing
e.Cancel = true;
// Show save confirmation dialog
var unsavedCount = viewModel.GetUnsavedChangesCount();
var message = unsavedCount == 1
? AppConstants.Messages.SaveChangesBeforeClose
: string.Format(AppConstants.Messages.SaveChangesBeforeCloseMultiple, unsavedCount);
var dialog = new SaveConfirmationDialog(message);
await dialog.ShowDialog(this);
var result = dialog.Result;
switch (result)
{
case SaveConfirmationResult.Save:
// User wants to save - save all unsaved changes
var saved = await viewModel.SaveAllUnsavedChangesAsync();
if (saved)
{
// All files saved successfully - mark as confirmed and close
_isClosingConfirmed = true;
await viewModel.SaveSessionAsync();
Close();
}
// If save was cancelled, keep the window open (e.Cancel is already true)
// Don't call base.OnClosing since we're cancelling
return;
case SaveConfirmationResult.DontSave:
// User doesn't want to save - mark as confirmed and close
_isClosingConfirmed = true;
await viewModel.SaveSessionAsync();
Close();
// Don't call base.OnClosing here - Close() will trigger OnClosing again
return;
case SaveConfirmationResult.Cancel:
default:
// User cancelled - keep the window open (e.Cancel is already true)
// Don't call base.OnClosing since we're cancelling
return;
}
}
else
{
// No unsaved changes - just save session and close normally
await viewModel.SaveSessionAsync();
}
base.OnClosing(e);
}
///
/// Handles pointer pressed events to capture text selection before formatting commands execute.
/// This is necessary because toolbar buttons take focus, losing the text selection.
///
private void OnButtonPointerPressed(object? sender, Avalonia.Input.PointerPressedEventArgs e)
{
// Walk up the visual tree to find the Button
Button? button = null;
if (e.Source is Control sourceControl)
{
button = sourceControl.GetVisualAncestors().OfType