123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321 |
- using Avalonia;
- using Avalonia.Controls;
- using Avalonia.Controls.ApplicationLifetimes;
- using Avalonia.Input;
- using Avalonia.Media;
- using Avalonia.Threading;
- using PicView.Avalonia.FileSystem;
- using PicView.Avalonia.ImageHandling;
- using PicView.Avalonia.Resizing;
- using PicView.Avalonia.UI;
- using PicView.Avalonia.ViewModels;
- using PicView.Core.ImageDecoding;
- using R3;
- namespace PicView.Avalonia.Views;
- public partial class SingleImageResizeView : UserControl
- {
- private double _aspectRatio;
- private readonly CompositeDisposable _imageUpdateSubscription = new();
- private bool _isKeepingAspectRatio = true;
- public SingleImageResizeView()
- {
- InitializeComponent();
- Loaded += OnLoaded;
- Unloaded += OnUnloaded;
- }
- private void OnLoaded(object? sender, EventArgs e)
- {
- if (DataContext is not MainViewModel vm)
- {
- return;
- }
-
- if (!Settings.Theme.Dark || Settings.Theme.GlassTheme)
- {
- BgPanel.Background = Brushes.Transparent;
- }
- _aspectRatio = (double)vm.PicViewer.PixelWidth.CurrentValue / vm.PicViewer.PixelHeight.CurrentValue;
- RegisterEventHandlers(vm);
- Observable.EveryValueChanged(vm.PicViewer, x => x.FileInfo.Value, UIHelper.GetFrameProvider)
- .Subscribe(_ =>
- {
- UpdateQualitySliderState();
- ShowCancelButton();
- }).AddTo(_imageUpdateSubscription);
- }
- private void OnUnloaded(object? sender, EventArgs e)
- {
- _imageUpdateSubscription?.Dispose();
- }
- private void RegisterEventHandlers(MainViewModel vm)
- {
- UpdateQualitySliderState();
- QualitySlider.ValueChanged += (_, _) => ShowResetButton();
- SaveButton.Click += async (_, _) => await SaveImage(vm).ConfigureAwait(false);
- SaveAsButton.Click += async (_, _) => await SaveImageAs(vm).ConfigureAwait(false);
- PixelWidthTextBox.KeyDown += async (_, e) => await SaveImageOnEnter(e, vm);
- PixelHeightTextBox.KeyDown += async (_, e) => await SaveImageOnEnter(e, vm);
- PixelWidthTextBox.KeyUp += (_, _) => AdjustAspectRatio(PixelWidthTextBox);
- PixelHeightTextBox.KeyUp += (_, _) => AdjustAspectRatio(PixelHeightTextBox);
- ConversionComboBox.SelectionChanged += (_, _) =>
- {
- UpdateQualitySliderState();
- ShowResetButton();
- };
- ResetButton.Click += (_, _) => ResetSettings(vm);
- CancelButton.Click += (_, _) => (VisualRoot as Window)?.Close();
- LinkChainButton.Click += (_, _) => ToggleAspectRatio();
- }
- private void ShowResetButton()
- {
- CancelButton.IsVisible = false;
- ResetButton.IsVisible = true;
- }
- private void ShowCancelButton()
- {
- CancelButton.IsVisible = true;
- ResetButton.IsVisible = false;
- }
- private void AdjustAspectRatio(TextBox sender)
- {
- if (!_isKeepingAspectRatio)
- {
- return;
- }
- AspectRatioHelper.SetAspectRatioForTextBox(
- PixelWidthTextBox, PixelHeightTextBox, sender == PixelWidthTextBox,
- _aspectRatio, DataContext as MainViewModel);
- ShowResetButton();
- }
- private void UpdateQualitySliderState()
- {
- if (DataContext is not MainViewModel vm)
- {
- return;
- }
- try
- {
- if (IsConversionToQualityFormat())
- {
- QualitySlider.IsEnabled = true;
- QualitySlider.Value = 75;
- }
- else if (IsOriginalFileQualityFormat(vm.PicViewer.FileInfo.CurrentValue.Extension))
- {
- QualitySlider.IsEnabled = true;
- QualitySlider.Value = ImageAnalyzer.GetCompressionQuality(vm.PicViewer.FileInfo.CurrentValue.FullName);
- }
- else
- {
- QualitySlider.IsEnabled = false;
- }
- }
- catch (Exception e)
- {
- #if DEBUG
- Console.WriteLine(e);
- #endif
- }
- }
- private bool IsConversionToQualityFormat()
- => JpgItem.IsSelected || PngItem.IsSelected;
- private static bool IsOriginalFileQualityFormat(string ext)
- => ext.Equals(".jpg", StringComparison.OrdinalIgnoreCase)
- || ext.Equals(".jpeg", StringComparison.OrdinalIgnoreCase)
- || ext.Equals(".png", StringComparison.OrdinalIgnoreCase);
- private async Task SaveImageOnEnter(KeyEventArgs e, MainViewModel vm)
- {
- if (e.Key == Key.Enter)
- {
- await SaveImage(vm).ConfigureAwait(false);
- }
- }
- private async Task SaveImageAs(MainViewModel vm)
- {
- if (Application.Current?.ApplicationLifetime is not IClassicDesktopStyleApplicationLifetime desktop
- || desktop.MainWindow?.StorageProvider is not { } provider)
- {
- return;
- }
- var fileInfoFullName = vm.PicViewer.FileInfo.CurrentValue.FullName;
- var ext = GetSelectedFileExtension(vm, ref fileInfoFullName);
- var file = await FilePicker.PickFileForSavingAsync(vm.PicViewer.FileInfo?.CurrentValue.FullName, ext);
- if (file is null)
- {
- return;
- }
- await DoSaveImage(vm, file).ConfigureAwait(false);
- }
- private async Task SaveImage(MainViewModel vm)
- {
- await DoSaveImage(vm, vm.PicViewer.FileInfo.CurrentValue.FullName).ConfigureAwait(false);
- }
- private async Task DoSaveImage(MainViewModel vm, string destination)
- {
- if (!uint.TryParse(PixelWidthTextBox.Text, out var width) ||
- !uint.TryParse(PixelHeightTextBox.Text, out var height))
- {
- return;
- }
- await Dispatcher.UIThread.InvokeAsync(() => SetLoadingState(true));
-
- var path = vm.PicViewer.FileInfo.CurrentValue.FullName;
- var ext = GetSelectedFileExtension(vm, ref destination);
- destination = Path.ChangeExtension(destination, ext);
- var sameFile = path.Equals(destination, StringComparison.OrdinalIgnoreCase);
- var quality = GetQualityValue(ext, destination);
- await SaveImageHandler.SaveImageWithPossibleNavigation(vm, path, destination, sameFile, ext, width, height,
- quality, null, _isKeepingAspectRatio);
- await Dispatcher.UIThread.InvokeAsync(() => SetLoadingState(false));
-
- }
- private void SetLoadingState(bool isLoading)
- {
- ParentContainer.Opacity = isLoading ? 0.1 : 1;
- ParentContainer.IsHitTestVisible = !isLoading;
- SpinWaiter.IsVisible = isLoading;
- }
- private string GetSelectedFileExtension(MainViewModel vm, ref string destination)
- {
- var ext = vm.PicViewer.FileInfo.CurrentValue.Extension;
- if (NoConversion.IsSelected)
- {
- return ext;
- }
- ext = GetExtensionFromSelectedItem() ?? ext;
- destination = Path.ChangeExtension(destination, ext);
- return ext;
- }
- private string? GetExtensionFromSelectedItem()
- {
- if (PngItem.IsSelected)
- {
- return ".png";
- }
- if (JpgItem.IsSelected)
- {
- return ".jpg";
- }
- if (WebpItem.IsSelected)
- {
- return ".webp";
- }
- if (AvifItem.IsSelected)
- {
- return ".avif";
- }
- if (HeicItem.IsSelected)
- {
- return ".heic";
- }
- if (JxlItem.IsSelected)
- {
- return ".jxl";
- }
- return null;
- }
- private uint? GetQualityValue(string ext, string destination)
- {
- if (QualitySlider.IsEnabled && (
- ext.Equals(".jpg", StringComparison.OrdinalIgnoreCase) ||
- Path.GetExtension(destination).Equals(".jpg", StringComparison.OrdinalIgnoreCase) ||
- Path.GetExtension(destination).Equals(".jpeg", StringComparison.OrdinalIgnoreCase)))
- {
- return (uint)QualitySlider.Value;
- }
- return null;
- }
- private void ResetSettings(MainViewModel vm)
- {
- PixelWidthTextBox.Text = vm.PicViewer.PixelWidth.ToString();
- PixelHeightTextBox.Text = vm.PicViewer.PixelHeight.ToString();
- if (IsOriginalFileQualityFormat(vm.PicViewer.FileInfo.CurrentValue.Extension))
- {
- QualitySlider.IsEnabled = true;
- QualitySlider.Value = ImageAnalyzer.GetCompressionQuality(vm.PicViewer.FileInfo.CurrentValue.FullName);
- }
- else
- {
- QualitySlider.IsEnabled = false;
- }
- ConversionComboBox.SelectedItem = NoConversion;
- _isKeepingAspectRatio = true;
- LinkChainImage.IsVisible = true;
- UnlinkChainImage.IsVisible = false;
- ShowCancelButton();
- }
- private void ToggleAspectRatio()
- {
- _isKeepingAspectRatio = !_isKeepingAspectRatio;
- LinkChainImage.IsVisible = _isKeepingAspectRatio;
- UnlinkChainImage.IsVisible = !_isKeepingAspectRatio;
- if (_isKeepingAspectRatio)
- {
- AdjustAspectRatio(PixelWidthTextBox);
- }
- if (!_isKeepingAspectRatio)
- {
- ShowResetButton();
- }
- }
- ~SingleImageResizeView()
- {
- _imageUpdateSubscription?.Dispose();
- }
- }
|