using Avalonia;
using Avalonia.Media.Imaging;
using Avalonia.Threading;
using PicView.Avalonia.Functions;
using PicView.Avalonia.UI;
using PicView.Avalonia.ViewModels;
using PicView.Avalonia.Views.UC;
using PicView.Avalonia.WindowBehavior;
using PicView.Core.Gallery;
using PicView.Core.ImageDecoding;
using PicView.Core.Localization;
namespace PicView.Avalonia.Crop;
public static class CropFunctions
{
public static bool IsCropping { get; private set; }
///
/// Starts the cropping functionality by setting up the ImageCropperViewModel
/// and adding the CropControl to the main view.
///
/// The main view model instance containing image properties and state.
///
/// This method checks if cropping can be enabled and if the image source is valid.
/// If conditions are met, it configures the crop control with the appropriate dimensions
/// and updates the view model's title and tooltip to reflect the cropping state.
///
public static async Task StartCropControlAsync(MainViewModel vm)
{
if (!DetermineIfShouldBeEnabled(vm))
{
return;
}
if (vm?.PicViewer.ImageSource.CurrentValue is not Bitmap bitmap)
{
return;
}
var isBottomGalleryShown = Settings.Gallery.IsBottomGalleryShown;
// Hide bottom gallery when entering crop mode
if (isBottomGalleryShown)
{
vm.Gallery.GalleryMode.Value = GalleryMode.Closed;
// Reset setting before resizing
Settings.Gallery.IsBottomGalleryShown = false;
await WindowResizing.SetSizeAsync(vm);
}
var size = new Size(vm.PicViewer.ImageWidth.CurrentValue, vm.PicViewer.ImageHeight.CurrentValue);
await Dispatcher.UIThread.InvokeAsync(() =>
{
vm.Crop = new ImageCropperViewModel(bitmap);
vm.Crop.ImageWidth.Value = size.Width;
vm.Crop.ImageHeight.Value = size.Height;
vm.Crop.AspectRatio.Value = vm.PicViewer.AspectRatio.CurrentValue;
var cropControl = new CropControl
{
DataContext = vm,
Width = size.Width,
Height = size.Height,
Margin = new Thickness(0)
};
vm.MainWindow.CurrentView.Value = cropControl;
});
IsCropping = true;
vm.PicViewer.Title.Value = TranslationManager.Translation.CropMessage!;
vm.PicViewer.TitleTooltip.Value = TranslationManager.Translation.CropMessage!;
await FunctionsMapper.CloseMenus();
if (isBottomGalleryShown)
{
Settings.Gallery.IsBottomGalleryShown = true;
}
}
public static void CloseCropControl(MainViewModel vm)
{
if (Settings.Gallery.IsBottomGalleryShown)
{
if (vm.Gallery is {} gallery)
{
gallery.GalleryMode.Value = GalleryMode.ClosedToBottom;
}
WindowResizing.SetSize(vm);
}
vm.MainWindow.CurrentView.Value = vm.ImageViewer;
IsCropping = false;
TitleManager.SetTitle(vm);
// Reset image type to fix issue with animated images
switch (vm.PicViewer.ImageType.CurrentValue)
{
case ImageType.AnimatedWebp:
vm.PicViewer.ImageType.Value = ImageType.Bitmap;
vm.PicViewer.ImageType.Value = ImageType.AnimatedWebp;
break;
case ImageType.AnimatedGif:
vm.PicViewer.ImageType.Value = ImageType.Bitmap;
vm.PicViewer.ImageType.Value = ImageType.AnimatedGif;
break;
}
vm.Crop = null;
}
public static bool DetermineIfShouldBeEnabled(MainViewModel vm)
{
if (IsCropping)
{
return false;
}
if (vm?.PicViewer.ImageSource.CurrentValue is not Bitmap || Settings.ImageScaling.ShowImageSideBySide)
{
vm.PicViewer.ShouldCropBeEnabled.Value = false;
return false;
}
if (DialogManager.IsDialogOpen)
{
return false;
}
if (vm.MainWindow.IsEditableTitlebarOpen.CurrentValue)
{
return false;
}
if (vm.GlobalSettings.RotationAngle.CurrentValue is 0 && vm.PicViewer.ScaleX.CurrentValue is 1)
{
vm.PicViewer.ShouldCropBeEnabled.Value = true;
return true;
}
vm.PicViewer.ShouldCropBeEnabled.Value = false;
return false;
}
}