2020-04-08 01:19:14 +08:00
// Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
2020-03-31 20:32:22 +08:00
2020-08-19 04:43:58 +08:00
using System ;
2020-04-27 08:34:03 +08:00
using System.Collections.ObjectModel ;
using System.ComponentModel ;
2020-10-22 03:32:53 +08:00
using System.Diagnostics.CodeAnalysis ;
using System.IO ;
2020-04-27 08:34:03 +08:00
using System.Linq ;
2020-10-23 00:45:48 +08:00
using Microsoft.PowerToys.Settings.UI.Library.Helpers ;
using Microsoft.PowerToys.Settings.UI.Library.Interfaces ;
using Microsoft.PowerToys.Settings.UI.Library.Utilities ;
2020-03-31 20:32:22 +08:00
2020-10-23 00:45:48 +08:00
namespace Microsoft.PowerToys.Settings.UI.Library.ViewModels
2020-03-31 20:32:22 +08:00
{
public class ImageResizerViewModel : Observable
{
2020-09-24 04:20:32 +08:00
private GeneralSettings GeneralSettingsConfig { get ; set ; }
2020-09-22 01:14:44 +08:00
private readonly ISettingsUtils _settingsUtils ;
2020-04-27 08:34:03 +08:00
private ImageResizerSettings Settings { get ; set ; }
2020-10-09 07:34:19 +08:00
private const string ModuleName = ImageResizerSettings . ModuleName ;
2020-04-27 08:34:03 +08:00
2020-08-19 04:43:58 +08:00
private Func < string , int > SendConfigMSG { get ; }
2020-10-22 03:32:53 +08:00
[SuppressMessage("Design", "CA1031:Do not catch general exception types", Justification = "Exceptions should not crash the program but will be logged until we can understand common exception scenarios")]
2021-01-14 20:14:29 +08:00
public ImageResizerViewModel ( ISettingsUtils settingsUtils , ISettingsRepository < GeneralSettings > settingsRepository , Func < string , int > ipcMSGCallBackFunc , Func < string , string > resourceLoader )
2020-03-31 20:32:22 +08:00
{
2020-09-22 01:14:44 +08:00
_settingsUtils = settingsUtils ? ? throw new ArgumentNullException ( nameof ( settingsUtils ) ) ;
2020-09-24 04:20:32 +08:00
// To obtain the general settings configurations of PowerToys.
2020-10-20 04:32:05 +08:00
if ( settingsRepository = = null )
{
throw new ArgumentNullException ( nameof ( settingsRepository ) ) ;
}
2020-09-24 04:20:32 +08:00
GeneralSettingsConfig = settingsRepository . SettingsConfig ;
2020-04-27 08:34:03 +08:00
try
{
2020-09-22 01:14:44 +08:00
Settings = _settingsUtils . GetSettings < ImageResizerSettings > ( ModuleName ) ;
2020-04-27 08:34:03 +08:00
}
2020-10-22 03:32:53 +08:00
catch ( Exception e )
2020-04-27 08:34:03 +08:00
{
2020-10-22 03:32:53 +08:00
Logger . LogError ( $"Exception encountered while reading {ModuleName} settings." , e ) ;
#if DEBUG
if ( e is ArgumentException | | e is ArgumentNullException | | e is PathTooLongException )
{
2020-10-23 00:45:48 +08:00
throw ;
2020-10-22 03:32:53 +08:00
}
#endif
2021-01-14 20:14:29 +08:00
Settings = new ImageResizerSettings ( resourceLoader ) ;
2020-09-22 01:14:44 +08:00
_settingsUtils . SaveSettings ( Settings . ToJsonString ( ) , ModuleName ) ;
2020-04-27 08:34:03 +08:00
}
2020-08-19 04:43:58 +08:00
// set the callback functions value to hangle outgoing IPC message.
SendConfigMSG = ipcMSGCallBackFunc ;
2020-09-24 04:20:32 +08:00
_isEnabled = GeneralSettingsConfig . Enabled . ImageResizer ;
2020-08-20 06:59:10 +08:00
_advancedSizes = Settings . Properties . ImageresizerSizes . Value ;
_jpegQualityLevel = Settings . Properties . ImageresizerJpegQualityLevel . Value ;
_pngInterlaceOption = Settings . Properties . ImageresizerPngInterlaceOption . Value ;
_tiffCompressOption = Settings . Properties . ImageresizerTiffCompressOption . Value ;
_fileName = Settings . Properties . ImageresizerFileName . Value ;
_keepDateModified = Settings . Properties . ImageresizerKeepDateModified . Value ;
_encoderGuidId = GetEncoderIndex ( Settings . Properties . ImageresizerFallbackEncoder . Value ) ;
2020-04-27 08:34:03 +08:00
int i = 0 ;
foreach ( ImageSize size in _advancedSizes )
{
size . Id = i ;
i + + ;
2020-10-10 08:58:52 +08:00
size . PropertyChanged + = SizePropertyChanged ;
2020-04-27 08:34:03 +08:00
}
}
2020-10-10 08:58:52 +08:00
private bool _isEnabled ;
2020-04-27 08:34:03 +08:00
private ObservableCollection < ImageSize > _advancedSizes = new ObservableCollection < ImageSize > ( ) ;
2020-10-10 08:58:52 +08:00
private int _jpegQualityLevel ;
2020-04-27 08:34:03 +08:00
private int _pngInterlaceOption ;
private int _tiffCompressOption ;
private string _fileName ;
private bool _keepDateModified ;
2020-10-10 08:58:52 +08:00
private int _encoderGuidId ;
2020-04-27 08:34:03 +08:00
2020-10-27 02:06:35 +08:00
public bool IsListViewFocusRequested { get ; set ; }
2020-04-27 08:34:03 +08:00
public bool IsEnabled
{
get
{
return _isEnabled ;
}
set
{
if ( value ! = _isEnabled )
{
2020-09-24 04:20:32 +08:00
// To set the status of ImageResizer in the General PowerToys settings.
2020-04-27 08:34:03 +08:00
_isEnabled = value ;
2020-09-24 04:20:32 +08:00
GeneralSettingsConfig . Enabled . ImageResizer = value ;
OutGoingGeneralSettings snd = new OutGoingGeneralSettings ( GeneralSettingsConfig ) ;
2020-08-19 04:43:58 +08:00
SendConfigMSG ( snd . ToString ( ) ) ;
2020-10-10 08:58:52 +08:00
OnPropertyChanged ( nameof ( IsEnabled ) ) ;
2020-04-27 08:34:03 +08:00
}
}
}
2020-10-20 04:32:05 +08:00
#pragma warning disable CA2227 // Collection properties should be read only
2020-04-27 08:34:03 +08:00
public ObservableCollection < ImageSize > Sizes
2020-10-20 04:32:05 +08:00
#pragma warning restore CA2227 // Collection properties should be read only
2020-04-27 08:34:03 +08:00
{
get
{
return _advancedSizes ;
}
2020-10-20 04:32:05 +08:00
// FxCop demands collection properties to be read-only, but this
// setter is used in autogenerated files (ImageResizerPage.g.cs)
// and replacing the setter with its own method will break the file
2020-04-27 08:34:03 +08:00
set
{
2020-08-19 04:43:58 +08:00
SavesImageSizes ( value ) ;
2020-04-27 08:34:03 +08:00
_advancedSizes = value ;
2020-10-10 08:58:52 +08:00
OnPropertyChanged ( nameof ( Sizes ) ) ;
2020-04-27 08:34:03 +08:00
}
}
public int JPEGQualityLevel
{
get
{
return _jpegQualityLevel ;
}
set
{
if ( _jpegQualityLevel ! = value )
{
_jpegQualityLevel = value ;
Settings . Properties . ImageresizerJpegQualityLevel . Value = value ;
2020-09-22 01:14:44 +08:00
_settingsUtils . SaveSettings ( Settings . ToJsonString ( ) , ModuleName ) ;
2020-10-10 08:58:52 +08:00
OnPropertyChanged ( nameof ( JPEGQualityLevel ) ) ;
2020-04-27 08:34:03 +08:00
}
}
}
public int PngInterlaceOption
{
get
{
return _pngInterlaceOption ;
}
set
{
if ( _pngInterlaceOption ! = value )
{
_pngInterlaceOption = value ;
Settings . Properties . ImageresizerPngInterlaceOption . Value = value ;
2020-09-22 01:14:44 +08:00
_settingsUtils . SaveSettings ( Settings . ToJsonString ( ) , ModuleName ) ;
2020-10-10 08:58:52 +08:00
OnPropertyChanged ( nameof ( PngInterlaceOption ) ) ;
2020-04-27 08:34:03 +08:00
}
}
}
public int TiffCompressOption
{
get
{
return _tiffCompressOption ;
}
set
{
if ( _tiffCompressOption ! = value )
{
_tiffCompressOption = value ;
Settings . Properties . ImageresizerTiffCompressOption . Value = value ;
2020-09-22 01:14:44 +08:00
_settingsUtils . SaveSettings ( Settings . ToJsonString ( ) , ModuleName ) ;
2020-10-10 08:58:52 +08:00
OnPropertyChanged ( nameof ( TiffCompressOption ) ) ;
2020-04-27 08:34:03 +08:00
}
}
}
public string FileName
{
get
{
return _fileName ;
}
set
{
2020-06-05 02:05:28 +08:00
if ( ! string . IsNullOrWhiteSpace ( value ) )
2020-04-27 08:34:03 +08:00
{
_fileName = value ;
Settings . Properties . ImageresizerFileName . Value = value ;
2020-09-22 01:14:44 +08:00
_settingsUtils . SaveSettings ( Settings . ToJsonString ( ) , ModuleName ) ;
2020-10-10 08:58:52 +08:00
OnPropertyChanged ( nameof ( FileName ) ) ;
2020-04-27 08:34:03 +08:00
}
}
}
public bool KeepDateModified
{
get
{
return _keepDateModified ;
}
set
{
_keepDateModified = value ;
Settings . Properties . ImageresizerKeepDateModified . Value = value ;
2020-09-22 01:14:44 +08:00
_settingsUtils . SaveSettings ( Settings . ToJsonString ( ) , ModuleName ) ;
2020-10-10 08:58:52 +08:00
OnPropertyChanged ( nameof ( KeepDateModified ) ) ;
2020-04-27 08:34:03 +08:00
}
}
public int Encoder
{
get
{
return _encoderGuidId ;
}
set
{
if ( _encoderGuidId ! = value )
{
_encoderGuidId = value ;
2020-09-22 01:14:44 +08:00
_settingsUtils . SaveSettings ( Settings . Properties . ImageresizerSizes . ToJsonString ( ) , ModuleName , "sizes.json" ) ;
2020-04-27 08:34:03 +08:00
Settings . Properties . ImageresizerFallbackEncoder . Value = GetEncoderGuid ( value ) ;
2020-09-22 01:14:44 +08:00
_settingsUtils . SaveSettings ( Settings . ToJsonString ( ) , ModuleName ) ;
2020-10-10 08:58:52 +08:00
OnPropertyChanged ( nameof ( Encoder ) ) ;
2020-04-27 08:34:03 +08:00
}
}
}
2020-10-10 08:58:52 +08:00
public string EncoderGuid
{
get
{
return ImageResizerViewModel . GetEncoderGuid ( _encoderGuidId ) ;
}
}
2021-09-22 06:55:42 +08:00
public void AddRow ( string sizeNamePrefix )
2020-04-27 08:34:03 +08:00
{
2021-09-23 05:43:28 +08:00
/// This is a fallback validation to eliminate the warning "CA1062:Validate arguments of public methods" when using the parameter (variable) "sizeNamePrefix" in the code.
/// If the parameter is unexpectedly empty or null, we fill the parameter with a non-localized string.
/// Normally the parameter "sizeNamePrefix" can't be null or empty because it is filled with a localized string when we call this method from <see cref="UI.Views.ImageResizerPage.AddSizeButton_Click"/>.
sizeNamePrefix = string . IsNullOrEmpty ( sizeNamePrefix ) ? "New Size" : sizeNamePrefix ;
2021-09-22 06:55:42 +08:00
2020-04-27 08:34:03 +08:00
ObservableCollection < ImageSize > imageSizes = Sizes ;
2020-05-15 23:03:30 +08:00
int maxId = imageSizes . Count > 0 ? imageSizes . OrderBy ( x = > x . Id ) . Last ( ) . Id : - 1 ;
2021-09-23 05:43:28 +08:00
string sizeName = GenerateNameForNewSize ( imageSizes , sizeNamePrefix ) ;
2021-09-22 06:55:42 +08:00
ImageSize newSize = new ImageSize ( maxId + 1 , sizeName , ResizeFit . Fit , 854 , 480 , ResizeUnit . Pixel ) ;
2020-10-10 08:58:52 +08:00
newSize . PropertyChanged + = SizePropertyChanged ;
2020-04-27 08:34:03 +08:00
imageSizes . Add ( newSize ) ;
2020-08-19 04:43:58 +08:00
_advancedSizes = imageSizes ;
SavesImageSizes ( imageSizes ) ;
2020-10-27 02:06:35 +08:00
// Set the focus requested flag to indicate that an add operation has occurred during the ContainerContentChanging event
IsListViewFocusRequested = true ;
2020-04-27 08:34:03 +08:00
}
public void DeleteImageSize ( int id )
{
2020-08-19 04:43:58 +08:00
ImageSize size = _advancedSizes . Where < ImageSize > ( x = > x . Id = = id ) . First ( ) ;
ObservableCollection < ImageSize > imageSizes = Sizes ;
imageSizes . Remove ( size ) ;
_advancedSizes = imageSizes ;
SavesImageSizes ( imageSizes ) ;
2020-04-27 08:34:03 +08:00
}
2020-08-19 04:43:58 +08:00
public void SavesImageSizes ( ObservableCollection < ImageSize > imageSizes )
2020-04-27 08:34:03 +08:00
{
2020-09-22 01:14:44 +08:00
_settingsUtils . SaveSettings ( Settings . Properties . ImageresizerSizes . ToJsonString ( ) , ModuleName , "sizes.json" ) ;
2020-08-19 04:43:58 +08:00
Settings . Properties . ImageresizerSizes = new ImageResizerSizes ( imageSizes ) ;
2020-09-22 01:14:44 +08:00
_settingsUtils . SaveSettings ( Settings . ToJsonString ( ) , ModuleName ) ;
2020-04-27 08:34:03 +08:00
}
2020-10-10 08:58:52 +08:00
public static string GetEncoderGuid ( int value )
2020-04-27 08:34:03 +08:00
{
// PNG Encoder guid
if ( value = = 0 )
{
return "1b7cfaf4-713f-473c-bbcd-6137425faeaf" ;
}
// Bitmap Encoder guid
else if ( value = = 1 )
{
return "0af1d87e-fcfe-4188-bdeb-a7906471cbe3" ;
}
// JPEG Encoder guid
else if ( value = = 2 )
{
return "19e4a5aa-5662-4fc5-a0c0-1758028e1057" ;
}
// Tiff encoder guid.
else if ( value = = 3 )
{
return "163bcc30-e2e9-4f0b-961d-a3e9fdb788a3" ;
}
// Tiff encoder guid.
else if ( value = = 4 )
{
return "57a37caa-367a-4540-916b-f183c5093a4b" ;
}
// Gif encoder guid.
else if ( value = = 5 )
{
return "1f8a5601-7d4d-4cbd-9c82-1bc8d4eeb9a5" ;
}
return null ;
}
2020-10-10 08:58:52 +08:00
public static int GetEncoderIndex ( string value )
2020-04-27 08:34:03 +08:00
{
// PNG Encoder guid
2020-10-10 08:58:52 +08:00
if ( value = = "1b7cfaf4-713f-473c-bbcd-6137425faeaf" )
2020-04-27 08:34:03 +08:00
{
return 0 ;
}
// Bitmap Encoder guid
2020-10-10 08:58:52 +08:00
else if ( value = = "0af1d87e-fcfe-4188-bdeb-a7906471cbe3" )
2020-04-27 08:34:03 +08:00
{
return 1 ;
}
// JPEG Encoder guid
2020-10-10 08:58:52 +08:00
else if ( value = = "19e4a5aa-5662-4fc5-a0c0-1758028e1057" )
2020-04-27 08:34:03 +08:00
{
return 2 ;
}
// Tiff encoder guid.
2020-10-10 08:58:52 +08:00
else if ( value = = "163bcc30-e2e9-4f0b-961d-a3e9fdb788a3" )
2020-04-27 08:34:03 +08:00
{
return 3 ;
}
// Tiff encoder guid.
2020-10-10 08:58:52 +08:00
else if ( value = = "57a37caa-367a-4540-916b-f183c5093a4b" )
2020-04-27 08:34:03 +08:00
{
return 4 ;
}
// Gif encoder guid.
2020-10-10 08:58:52 +08:00
else if ( value = = "1f8a5601-7d4d-4cbd-9c82-1bc8d4eeb9a5" )
2020-04-27 08:34:03 +08:00
{
return 5 ;
}
return - 1 ;
}
2020-10-10 08:58:52 +08:00
public void SizePropertyChanged ( object sender , PropertyChangedEventArgs e )
2020-04-27 08:34:03 +08:00
{
ImageSize modifiedSize = ( ImageSize ) sender ;
ObservableCollection < ImageSize > imageSizes = Sizes ;
imageSizes . Where < ImageSize > ( x = > x . Id = = modifiedSize . Id ) . First ( ) . Update ( modifiedSize ) ;
2020-08-19 04:43:58 +08:00
_advancedSizes = imageSizes ;
SavesImageSizes ( imageSizes ) ;
2020-03-31 20:32:22 +08:00
}
2021-09-22 06:55:42 +08:00
private static string GenerateNameForNewSize ( in ObservableCollection < ImageSize > sizesList , in string namePrefix )
{
int newSizeCounter = 0 ;
foreach ( ImageSize imgSize in sizesList )
{
string name = imgSize . Name ;
if ( name . StartsWith ( namePrefix , StringComparison . InvariantCulture ) )
{
if ( int . TryParse ( name . Substring ( namePrefix . Length ) , out int number ) )
{
if ( newSizeCounter < number )
{
newSizeCounter = number ;
}
}
}
}
return $"{namePrefix} {++newSizeCounter}" ;
}
2020-03-31 20:32:22 +08:00
}
2020-04-11 06:22:07 +08:00
}