[Settings]ImageResizer settings accessibility updates, fixes and refactor (#36903)
* Fix issue with missing Image Resizer unit and fit information in settings description. * Fix accessibility issues on Edit and Remove buttons. Fix various issues and refactor view model and ImageSize. New resources for accessibility text formats. * Fix unit test because of change to new preset width and height. Fix 2 unit tests having incorrect expected/actual orderings. * Post-review update: accessibility strings now formatted within the converter, instead of via format strings; simplified encoder GUID collection declaration and retrieval. * Minor example text fix.
This commit is contained in:
Родитель
b33e0be178
Коммит
438d17302e
|
@ -3,241 +3,119 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Settings.UI.Library.Resources;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library
|
||||
namespace Microsoft.PowerToys.Settings.UI.Library;
|
||||
|
||||
public partial class ImageSize : INotifyPropertyChanged
|
||||
{
|
||||
public class ImageSize : INotifyPropertyChanged
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
private bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
|
||||
{
|
||||
public ImageSize(int id)
|
||||
bool changed = !EqualityComparer<T>.Default.Equals(field, value);
|
||||
if (changed)
|
||||
{
|
||||
Id = id;
|
||||
Name = string.Empty;
|
||||
Fit = ResizeFit.Fit;
|
||||
Width = 0;
|
||||
Height = 0;
|
||||
Unit = ResizeUnit.Pixel;
|
||||
field = value;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(AccessibleTextHelper)));
|
||||
}
|
||||
|
||||
public ImageSize()
|
||||
return changed;
|
||||
}
|
||||
|
||||
public ImageSize(int id = 0, string name = "", ResizeFit fit = ResizeFit.Fit, double width = 0, double height = 0, ResizeUnit unit = ResizeUnit.Pixel)
|
||||
{
|
||||
Id = id;
|
||||
Name = name;
|
||||
Fit = fit;
|
||||
Width = width;
|
||||
Height = height;
|
||||
Unit = unit;
|
||||
}
|
||||
|
||||
private int _id;
|
||||
private string _name;
|
||||
private ResizeFit _fit;
|
||||
private double _height;
|
||||
private double _width;
|
||||
private ResizeUnit _unit;
|
||||
|
||||
public int Id
|
||||
{
|
||||
get => _id;
|
||||
set => SetProperty(ref _id, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether the <see cref="Height"/> property is used. When false, the
|
||||
/// <see cref="Width"/> property is used to evenly scale the image in both X and Y dimensions.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public bool IsHeightUsed
|
||||
{
|
||||
// Height is ignored when using percentage scaling where the aspect ratio is maintained
|
||||
// (i.e. non-stretch fits). In all other cases, both Width and Height are needed.
|
||||
get => !(Unit == ResizeUnit.Percent && Fit != ResizeFit.Stretch);
|
||||
}
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set => SetProperty(ref _name, value);
|
||||
}
|
||||
|
||||
[JsonPropertyName("fit")]
|
||||
public ResizeFit Fit
|
||||
{
|
||||
get => _fit;
|
||||
set
|
||||
{
|
||||
Id = 0;
|
||||
Name = string.Empty;
|
||||
Fit = ResizeFit.Fit;
|
||||
Width = 0;
|
||||
Height = 0;
|
||||
Unit = ResizeUnit.Pixel;
|
||||
}
|
||||
|
||||
public ImageSize(int id, string name, ResizeFit fit, double width, double height, ResizeUnit unit)
|
||||
{
|
||||
Id = id;
|
||||
Name = name;
|
||||
Fit = fit;
|
||||
Width = width;
|
||||
Height = height;
|
||||
Unit = unit;
|
||||
}
|
||||
|
||||
private int _id;
|
||||
private string _name;
|
||||
private ResizeFit _fit;
|
||||
private double _height;
|
||||
private double _width;
|
||||
private ResizeUnit _unit;
|
||||
|
||||
public int Id
|
||||
{
|
||||
get
|
||||
if (SetProperty(ref _fit, value))
|
||||
{
|
||||
return _id;
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsHeightUsed)));
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (_id != value)
|
||||
{
|
||||
_id = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int ExtraBoxOpacity
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Unit == ResizeUnit.Percent && Fit != ResizeFit.Stretch)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool EnableEtraBoxes
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Unit == ResizeUnit.Percent && Fit != ResizeFit.Stretch)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[JsonPropertyName("name")]
|
||||
public string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return _name;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (_name != value)
|
||||
{
|
||||
_name = value;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[JsonPropertyName("fit")]
|
||||
public ResizeFit Fit
|
||||
{
|
||||
get
|
||||
{
|
||||
return _fit;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (_fit != value)
|
||||
{
|
||||
_fit = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(ExtraBoxOpacity));
|
||||
OnPropertyChanged(nameof(EnableEtraBoxes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[JsonPropertyName("width")]
|
||||
public double Width
|
||||
{
|
||||
get
|
||||
{
|
||||
return _width;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
double newWidth = -1;
|
||||
|
||||
if (value < 0 || double.IsNaN(value))
|
||||
{
|
||||
newWidth = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
newWidth = value;
|
||||
}
|
||||
|
||||
if (_width != newWidth)
|
||||
{
|
||||
_width = newWidth;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[JsonPropertyName("height")]
|
||||
public double Height
|
||||
{
|
||||
get
|
||||
{
|
||||
return _height;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
double newHeight = -1;
|
||||
|
||||
if (value < 0 || double.IsNaN(value))
|
||||
{
|
||||
newHeight = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
newHeight = value;
|
||||
}
|
||||
|
||||
if (_height != newHeight)
|
||||
{
|
||||
_height = newHeight;
|
||||
OnPropertyChanged();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[JsonPropertyName("unit")]
|
||||
public ResizeUnit Unit
|
||||
{
|
||||
get
|
||||
{
|
||||
return _unit;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (_unit != value)
|
||||
{
|
||||
_unit = value;
|
||||
OnPropertyChanged();
|
||||
OnPropertyChanged(nameof(ExtraBoxOpacity));
|
||||
OnPropertyChanged(nameof(EnableEtraBoxes));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
public void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||
{
|
||||
var handler = PropertyChanged;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, new PropertyChangedEventArgs(propertyName));
|
||||
}
|
||||
}
|
||||
|
||||
public void Update(ImageSize modifiedSize)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(modifiedSize);
|
||||
|
||||
Id = modifiedSize.Id;
|
||||
Name = modifiedSize.Name;
|
||||
Fit = modifiedSize.Fit;
|
||||
Width = modifiedSize.Width;
|
||||
Height = modifiedSize.Height;
|
||||
Unit = modifiedSize.Unit;
|
||||
}
|
||||
|
||||
public string ToJsonString()
|
||||
{
|
||||
return JsonSerializer.Serialize(this);
|
||||
}
|
||||
}
|
||||
|
||||
[JsonPropertyName("width")]
|
||||
public double Width
|
||||
{
|
||||
get => _width;
|
||||
set => SetProperty(ref _width, value < 0 || double.IsNaN(value) ? 0 : value);
|
||||
}
|
||||
|
||||
[JsonPropertyName("height")]
|
||||
public double Height
|
||||
{
|
||||
get => _height;
|
||||
set => SetProperty(ref _height, value < 0 || double.IsNaN(value) ? 0 : value);
|
||||
}
|
||||
|
||||
[JsonPropertyName("unit")]
|
||||
public ResizeUnit Unit
|
||||
{
|
||||
get => _unit;
|
||||
set
|
||||
{
|
||||
if (SetProperty(ref _unit, value))
|
||||
{
|
||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsHeightUsed)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets access to all properties for formatting accessibility descriptions.
|
||||
/// </summary>
|
||||
[JsonIgnore]
|
||||
public ImageSize AccessibleTextHelper => this;
|
||||
|
||||
public string ToJsonString() => JsonSerializer.Serialize(this);
|
||||
}
|
||||
|
|
|
@ -205,7 +205,7 @@ namespace ViewModelTests
|
|||
}
|
||||
|
||||
[TestMethod]
|
||||
public void AddRowShouldAddNewImageSizeWhenSuccessful()
|
||||
public void AddImageSizeShouldAddNewImageSizeWhenSuccessful()
|
||||
{
|
||||
// arrange
|
||||
var mockSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils<ImageResizerSettings>();
|
||||
|
@ -214,7 +214,7 @@ namespace ViewModelTests
|
|||
int sizeOfOriginalArray = viewModel.Sizes.Count;
|
||||
|
||||
// act
|
||||
viewModel.AddRow("New size");
|
||||
viewModel.AddImageSize();
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(sizeOfOriginalArray + 1, viewModel.Sizes.Count);
|
||||
|
@ -229,15 +229,15 @@ namespace ViewModelTests
|
|||
ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), sendMockIPCConfigMSG, (string name) => name);
|
||||
|
||||
// act
|
||||
viewModel.AddRow("New size");
|
||||
viewModel.AddImageSize("New size");
|
||||
|
||||
// Assert
|
||||
ImageSize newTestSize = viewModel.Sizes.First(x => x.Id == 0);
|
||||
Assert.AreEqual(newTestSize.Name, "New size 1");
|
||||
Assert.AreEqual(newTestSize.Fit, ResizeFit.Fit);
|
||||
Assert.AreEqual(newTestSize.Width, 854);
|
||||
Assert.AreEqual(newTestSize.Height, 480);
|
||||
Assert.AreEqual(newTestSize.Unit, ResizeUnit.Pixel);
|
||||
Assert.AreEqual("New size 1", newTestSize.Name);
|
||||
Assert.AreEqual(ResizeFit.Fit, newTestSize.Fit);
|
||||
Assert.AreEqual(1024, newTestSize.Width);
|
||||
Assert.AreEqual(640, newTestSize.Height);
|
||||
Assert.AreEqual(ResizeUnit.Pixel, newTestSize.Unit);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
@ -247,7 +247,7 @@ namespace ViewModelTests
|
|||
var mockSettingsUtils = ISettingsUtilsMocks.GetStubSettingsUtils<ImageResizerSettings>();
|
||||
Func<string, int> sendMockIPCConfigMSG = msg => { return 0; };
|
||||
ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), sendMockIPCConfigMSG, (string name) => name);
|
||||
viewModel.AddRow("New Size");
|
||||
viewModel.AddImageSize("New Size");
|
||||
int sizeOfOriginalArray = viewModel.Sizes.Count;
|
||||
ImageSize deleteCandidate = viewModel.Sizes.First(x => x.Id == 0);
|
||||
|
||||
|
@ -268,16 +268,16 @@ namespace ViewModelTests
|
|||
ImageResizerViewModel viewModel = new ImageResizerViewModel(mockSettingsUtils.Object, SettingsRepository<GeneralSettings>.GetInstance(_mockGeneralSettingsUtils.Object), sendMockIPCConfigMSG, (string name) => name);
|
||||
|
||||
// act
|
||||
viewModel.AddRow("New size"); // Add: "New size 1"
|
||||
viewModel.AddRow("New size"); // Add: "New size 2"
|
||||
viewModel.AddRow("New size"); // Add: "New size 3"
|
||||
viewModel.AddImageSize("New size"); // Add: "New size 1"
|
||||
viewModel.AddImageSize("New size"); // Add: "New size 2"
|
||||
viewModel.AddImageSize("New size"); // Add: "New size 3"
|
||||
viewModel.DeleteImageSize(1); // Delete: "New size 2"
|
||||
viewModel.AddRow("New size"); // Add: "New Size 4"
|
||||
viewModel.AddImageSize("New size"); // Add: "New Size 4"
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(viewModel.Sizes[0].Name, "New size 1");
|
||||
Assert.AreEqual(viewModel.Sizes[1].Name, "New size 3");
|
||||
Assert.AreEqual(viewModel.Sizes[2].Name, "New size 4");
|
||||
Assert.AreEqual("New size 1", viewModel.Sizes[0].Name);
|
||||
Assert.AreEqual("New size 3", viewModel.Sizes[1].Name);
|
||||
Assert.AreEqual("New size 4", viewModel.Sizes[2].Name);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
|
|
|
@ -3,41 +3,38 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
using System.Windows;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Converters
|
||||
namespace Microsoft.PowerToys.Settings.UI.Converters;
|
||||
|
||||
public sealed partial class ImageResizerFitToStringConverter : IValueConverter
|
||||
{
|
||||
public sealed partial class ImageResizerFitToStringConverter : IValueConverter
|
||||
// Maps each ResizeFit to its localized string.
|
||||
private static readonly Dictionary<ResizeFit, string> FitToText = new()
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{ ResizeFit.Fill, Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Fit_Fill_ThirdPersonSingular") },
|
||||
{ ResizeFit.Fit, Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Fit_Fit_ThirdPersonSingular") },
|
||||
{ ResizeFit.Stretch, Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Fit_Stretch_ThirdPersonSingular") },
|
||||
};
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is ResizeFit fit && FitToText.TryGetValue(fit, out string fitText))
|
||||
{
|
||||
var toLower = false;
|
||||
if ((string)parameter == "ToLower")
|
||||
{
|
||||
toLower = true;
|
||||
}
|
||||
|
||||
string targetValue = string.Empty;
|
||||
switch (value)
|
||||
{
|
||||
case 0: targetValue = Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Fit_Fill_ThirdPersonSingular"); break;
|
||||
case 1: targetValue = Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Fit_Fit_ThirdPersonSingular"); break;
|
||||
case 2: targetValue = Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Fit_Stretch_ThirdPersonSingular"); break;
|
||||
}
|
||||
|
||||
if (toLower)
|
||||
{
|
||||
targetValue = targetValue.ToLower(CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
return targetValue;
|
||||
return parameter is string lowerParam && lowerParam == "ToLower" ?
|
||||
fitText.ToLower(CultureInfo.CurrentCulture) :
|
||||
fitText;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return DependencyProperty.UnsetValue;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,71 @@
|
|||
// 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.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Windows;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Converters;
|
||||
|
||||
/// <summary>
|
||||
/// Creates accessibility text for controls related to <see cref="ImageSize"/> properties.
|
||||
/// </summary>
|
||||
/// <example>(Name) "Edit the Small preset"</example>
|
||||
/// <example>(FullDescription) "Large - Fits within 1920 × 1080 pixels"</example>"
|
||||
public sealed partial class ImageResizerSizeToAccessibleTextConverter : IValueConverter
|
||||
{
|
||||
private const char TimesGlyph = '\u00D7'; // Unicode "MULTIPLICATION SIGN"
|
||||
|
||||
/// <summary>
|
||||
/// Maps the supplied accessibility identifier to the format string of the localized accessible text.
|
||||
/// </summary>
|
||||
private static readonly Dictionary<string, string> AccessibilityFormats = new()
|
||||
{
|
||||
{ "Edit", Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_EditButton_Accessibility_Name") },
|
||||
{ "Remove", Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_RemoveButton_Accessibility_Name") },
|
||||
};
|
||||
|
||||
private readonly ImageResizerFitToStringConverter _fitConverter = new();
|
||||
private readonly ImageResizerUnitToStringConverter _unitConverter = new();
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
return (value, parameter) switch
|
||||
{
|
||||
(string presetName, string nameId) => FormatNameText(presetName, nameId),
|
||||
(ImageSize preset, string _) => FormatDescriptionText(preset),
|
||||
_ => DependencyProperty.UnsetValue,
|
||||
};
|
||||
}
|
||||
|
||||
private object FormatNameText(string presetName, string nameId)
|
||||
{
|
||||
return AccessibilityFormats.TryGetValue(nameId, out string format) ?
|
||||
string.Format(CultureInfo.CurrentCulture, format, presetName) :
|
||||
DependencyProperty.UnsetValue;
|
||||
}
|
||||
|
||||
private object FormatDescriptionText(ImageSize preset)
|
||||
{
|
||||
if (preset == null)
|
||||
{
|
||||
return DependencyProperty.UnsetValue;
|
||||
}
|
||||
|
||||
string fitText = _fitConverter.Convert(preset.Fit, typeof(string), null, null) as string;
|
||||
string unitText = _unitConverter.Convert(preset.Unit, typeof(string), null, null) as string;
|
||||
|
||||
return preset.IsHeightUsed ?
|
||||
$"{preset.Name} - {fitText} {preset.Width} {TimesGlyph} {preset.Height} {unitText}" :
|
||||
$"{preset.Name} - {fitText} {preset.Width} {unitText}";
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
|
@ -3,42 +3,39 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
|
||||
using System.Windows;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.UI.Xaml.Data;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.Converters
|
||||
namespace Microsoft.PowerToys.Settings.UI.Converters;
|
||||
|
||||
public sealed partial class ImageResizerUnitToStringConverter : IValueConverter
|
||||
{
|
||||
public sealed partial class ImageResizerUnitToStringConverter : IValueConverter
|
||||
// Maps each ResizeUnit value to its localized string.
|
||||
private static readonly Dictionary<ResizeUnit, string> UnitToText = new()
|
||||
{
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{ ResizeUnit.Centimeter, Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Centimeter") },
|
||||
{ ResizeUnit.Inch, Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Inch") },
|
||||
{ ResizeUnit.Percent, Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Percent") },
|
||||
{ ResizeUnit.Pixel, Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Pixel") },
|
||||
};
|
||||
|
||||
public object Convert(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
if (value is ResizeUnit unit && UnitToText.TryGetValue(unit, out string unitText))
|
||||
{
|
||||
var toLower = false;
|
||||
if ((string)parameter == "ToLower")
|
||||
{
|
||||
toLower = true;
|
||||
}
|
||||
|
||||
string targetValue = string.Empty;
|
||||
switch (value)
|
||||
{
|
||||
case 0: targetValue = Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Centimeter"); break;
|
||||
case 1: targetValue = Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Inch"); break;
|
||||
case 2: targetValue = Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Percent"); break;
|
||||
case 3: targetValue = Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_Unit_Pixel"); break;
|
||||
}
|
||||
|
||||
if (toLower)
|
||||
{
|
||||
targetValue = targetValue.ToLower(CultureInfo.CurrentCulture);
|
||||
}
|
||||
|
||||
return targetValue;
|
||||
return parameter is string lowerParam && lowerParam == "ToLower" ?
|
||||
unitText.ToLower(CultureInfo.CurrentCulture) :
|
||||
unitText;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
return DependencyProperty.UnsetValue;
|
||||
}
|
||||
|
||||
public object ConvertBack(object value, Type targetType, object parameter, string language)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
<converters:ImageResizerFitToIntConverter x:Key="ImageResizerFitToIntConverter" />
|
||||
<converters:ImageResizerUnitToStringConverter x:Key="ImageResizerUnitToStringConverter" />
|
||||
<converters:ImageResizerUnitToIntConverter x:Key="ImageResizerUnitToIntConverter" />
|
||||
<converters:ImageResizerSizeToAccessibleTextConverter x:Key="ImageResizerSizeToAccessibleTextConverter" />
|
||||
<toolkitconverters:BoolToObjectConverter
|
||||
x:Key="BoolToComboBoxIndexConverter"
|
||||
FalseValue="1"
|
||||
|
@ -85,13 +86,13 @@
|
|||
FontSize="10"
|
||||
Style="{ThemeResource SecondaryTextStyle}"
|
||||
Text=""
|
||||
Visibility="{x:Bind EnableEtraBoxes, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
Visibility="{x:Bind IsHeightUsed, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<TextBlock
|
||||
Margin="0,0,4,0"
|
||||
FontWeight="SemiBold"
|
||||
Style="{ThemeResource SecondaryTextStyle}"
|
||||
Text="{x:Bind Height, Mode=OneWay}"
|
||||
Visibility="{x:Bind EnableEtraBoxes, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
Visibility="{x:Bind IsHeightUsed, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
|
||||
<TextBlock
|
||||
Margin="0,0,4,0"
|
||||
Style="{ThemeResource SecondaryTextStyle}"
|
||||
|
@ -104,12 +105,20 @@
|
|||
Orientation="Horizontal"
|
||||
Spacing="8">
|
||||
<Button
|
||||
x:Uid="EditButton"
|
||||
x:Uid="ImageResizer_EditButton"
|
||||
Width="40"
|
||||
Height="36"
|
||||
Content=""
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
Style="{StaticResource SubtleButtonStyle}"
|
||||
AutomationProperties.Name="{x:Bind Name,
|
||||
Mode=OneWay,
|
||||
Converter={StaticResource ImageResizerSizeToAccessibleTextConverter},
|
||||
ConverterParameter='Edit'}"
|
||||
AutomationProperties.FullDescription="{x:Bind AccessibleTextHelper,
|
||||
Mode=OneWay,
|
||||
Converter={StaticResource ImageResizerSizeToAccessibleTextConverter},
|
||||
ConverterParameter='Edit'}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="EditTooltip" />
|
||||
</ToolTipService.ToolTip>
|
||||
|
@ -145,10 +154,10 @@
|
|||
Width="116"
|
||||
Minimum="0"
|
||||
SpinButtonPlacementMode="Compact"
|
||||
Visibility="{x:Bind EnableEtraBoxes, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}"
|
||||
Visibility="{x:Bind IsHeightUsed, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}"
|
||||
Value="{x:Bind Height, Mode=TwoWay}" />
|
||||
|
||||
</StackPanel>
|
||||
|
||||
<ComboBox
|
||||
x:Uid="ImageResizer_Size"
|
||||
Width="240"
|
||||
|
@ -164,15 +173,22 @@
|
|||
</Button>
|
||||
|
||||
<Button
|
||||
x:Name="RemoveButton"
|
||||
x:Uid="RemoveButton"
|
||||
x:Uid="ImageResizer_RemoveButton"
|
||||
Width="40"
|
||||
Height="36"
|
||||
Click="DeleteCustomSize"
|
||||
CommandParameter="{Binding Id}"
|
||||
Content=""
|
||||
FontFamily="{ThemeResource SymbolThemeFontFamily}"
|
||||
Style="{StaticResource SubtleButtonStyle}">
|
||||
Style="{StaticResource SubtleButtonStyle}"
|
||||
AutomationProperties.Name="{x:Bind Name,
|
||||
Mode=OneWay,
|
||||
Converter={StaticResource ImageResizerSizeToAccessibleTextConverter},
|
||||
ConverterParameter='Remove'}"
|
||||
AutomationProperties.FullDescription="{x:Bind AccessibleTextHelper,
|
||||
Mode=OneWay,
|
||||
Converter={StaticResource ImageResizerSizeToAccessibleTextConverter},
|
||||
ConverterParameter='Remove'}">
|
||||
<ToolTipService.ToolTip>
|
||||
<TextBlock x:Uid="RemoveTooltip" />
|
||||
</ToolTipService.ToolTip>
|
||||
|
|
|
@ -22,11 +22,8 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||
{
|
||||
InitializeComponent();
|
||||
var settingsUtils = new SettingsUtils();
|
||||
var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
|
||||
Func<string, string> loader = (string name) =>
|
||||
{
|
||||
return resourceLoader.GetString(name);
|
||||
};
|
||||
var resourceLoader = ResourceLoaderInstance.ResourceLoader;
|
||||
Func<string, string> loader = resourceLoader.GetString;
|
||||
|
||||
ViewModel = new ImageResizerViewModel(settingsUtils, SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), ShellPage.SendDefaultIPCMessage, loader);
|
||||
DataContext = ViewModel;
|
||||
|
@ -69,7 +66,7 @@ namespace Microsoft.PowerToys.Settings.UI.Views
|
|||
{
|
||||
try
|
||||
{
|
||||
ViewModel.AddRow(Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_DefaultSize_NewSizePrefix"));
|
||||
ViewModel.AddImageSize();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
|
|
@ -1169,10 +1169,6 @@
|
|||
<data name="ImageResizer_Size.Header" xml:space="preserve">
|
||||
<value>Unit</value>
|
||||
</data>
|
||||
<data name="RemoveButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Remove</value>
|
||||
<comment>Removes a user defined setting group for Image Resizer</comment>
|
||||
</data>
|
||||
<data name="RemoveItem.Text" xml:space="preserve">
|
||||
<value>Delete</value>
|
||||
</data>
|
||||
|
@ -2352,12 +2348,29 @@ From there, simply click on one of the supported files in the File Explorer and
|
|||
<data name="ImageResizer_Unit_Pixel" xml:space="preserve">
|
||||
<value>Pixels</value>
|
||||
</data>
|
||||
<data name="EditButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<data name="ImageResizer_EditButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Edit</value>
|
||||
</data>
|
||||
<data name="ImageResizer_EditSize.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Edit size</value>
|
||||
</data>
|
||||
<data name="ImageResizer_Presets.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>ImageResizer presets</value>
|
||||
</data>
|
||||
<data name="ImageResizer_AddSizeButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Add a new preset</value>
|
||||
</data>
|
||||
<data name="ImageResizer_RemoveButton.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
|
||||
<value>Remove</value>
|
||||
</data>
|
||||
<data name="ImageResizer_EditButton_Accessibility_Name" xml:space="preserve">
|
||||
<value>Edit the {0} preset</value>
|
||||
<comment>Expands to the AutomationProperties.Name value for the Edit button. Example: "Edit the Small preset".</comment>
|
||||
</data>
|
||||
<data name="ImageResizer_RemoveButton_Accessibility_Name" xml:space="preserve">
|
||||
<value>Remove the {0} preset</value>
|
||||
<comment>Expands to the AutomationProperties.Name value for the Remove button. Example: "Remove the Large preset".</comment>
|
||||
</data>
|
||||
<data name="No" xml:space="preserve">
|
||||
<value>No</value>
|
||||
<comment>Label of a cancel button</comment>
|
||||
|
|
|
@ -3,431 +3,362 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Collections.Specialized;
|
||||
using System.ComponentModel;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
using System.Runtime.CompilerServices;
|
||||
using global::PowerToys.GPOWrapper;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Helpers;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Interfaces;
|
||||
|
||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels
|
||||
namespace Microsoft.PowerToys.Settings.UI.ViewModels;
|
||||
|
||||
public partial class ImageResizerViewModel : Observable
|
||||
{
|
||||
public class ImageResizerViewModel : Observable
|
||||
private static readonly string DefaultPresetNamePrefix =
|
||||
Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_DefaultSize_NewSizePrefix");
|
||||
|
||||
private static readonly List<string> EncoderGuids =
|
||||
[
|
||||
"1b7cfaf4-713f-473c-bbcd-6137425faeaf", // PNG Encoder
|
||||
"0af1d87e-fcfe-4188-bdeb-a7906471cbe3", // Bitmap Encoder
|
||||
"19e4a5aa-5662-4fc5-a0c0-1758028e1057", // JPEG Encoder
|
||||
"163bcc30-e2e9-4f0b-961d-a3e9fdb788a3", // TIFF Encoder
|
||||
"57a37caa-367a-4540-916b-f183c5093a4b", // TIFF Encoder
|
||||
"1f8a5601-7d4d-4cbd-9c82-1bc8d4eeb9a5", // GIF Encoder
|
||||
];
|
||||
|
||||
/// <summary>
|
||||
/// Used to skip saving settings to file during initialization.
|
||||
/// </summary>
|
||||
private readonly bool _isInitializing;
|
||||
|
||||
/// <summary>
|
||||
/// Holds defaults for new presets.
|
||||
/// </summary>
|
||||
private readonly ImageSize _customSize;
|
||||
|
||||
private GeneralSettings GeneralSettingsConfig { get; set; }
|
||||
|
||||
private readonly ISettingsUtils _settingsUtils;
|
||||
|
||||
private ImageResizerSettings Settings { get; set; }
|
||||
|
||||
private const string ModuleName = ImageResizerSettings.ModuleName;
|
||||
|
||||
private Func<string, int> SendConfigMSG { get; }
|
||||
|
||||
public ImageResizerViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc, Func<string, string> resourceLoader)
|
||||
{
|
||||
private GeneralSettings GeneralSettingsConfig { get; set; }
|
||||
_isInitializing = true;
|
||||
|
||||
private readonly ISettingsUtils _settingsUtils;
|
||||
_settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils));
|
||||
|
||||
private ImageResizerSettings Settings { get; set; }
|
||||
// To obtain the general settings configurations of PowerToys.
|
||||
ArgumentNullException.ThrowIfNull(settingsRepository);
|
||||
|
||||
private const string ModuleName = ImageResizerSettings.ModuleName;
|
||||
GeneralSettingsConfig = settingsRepository.SettingsConfig;
|
||||
|
||||
private Func<string, int> SendConfigMSG { get; }
|
||||
|
||||
public ImageResizerViewModel(ISettingsUtils settingsUtils, ISettingsRepository<GeneralSettings> settingsRepository, Func<string, int> ipcMSGCallBackFunc, Func<string, string> resourceLoader)
|
||||
try
|
||||
{
|
||||
_settingsUtils = settingsUtils ?? throw new ArgumentNullException(nameof(settingsUtils));
|
||||
|
||||
// To obtain the general settings configurations of PowerToys.
|
||||
ArgumentNullException.ThrowIfNull(settingsRepository);
|
||||
|
||||
GeneralSettingsConfig = settingsRepository.SettingsConfig;
|
||||
|
||||
try
|
||||
{
|
||||
Settings = _settingsUtils.GetSettings<ImageResizerSettings>(ModuleName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Exception encountered while reading {ModuleName} settings.", e);
|
||||
Settings = _settingsUtils.GetSettings<ImageResizerSettings>(ModuleName);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.LogError($"Exception encountered while reading {ModuleName} settings.", e);
|
||||
#if DEBUG
|
||||
if (e is ArgumentException || e is ArgumentNullException || e is PathTooLongException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
if (e is ArgumentException || e is ArgumentNullException || e is PathTooLongException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
#endif
|
||||
Settings = new ImageResizerSettings(resourceLoader);
|
||||
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
|
||||
}
|
||||
|
||||
// set the callback functions value to handle outgoing IPC message.
|
||||
SendConfigMSG = ipcMSGCallBackFunc;
|
||||
|
||||
InitializeEnabledValue();
|
||||
|
||||
_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);
|
||||
|
||||
int i = 0;
|
||||
foreach (ImageSize size in _advancedSizes)
|
||||
{
|
||||
size.Id = i;
|
||||
i++;
|
||||
size.PropertyChanged += SizePropertyChanged;
|
||||
}
|
||||
}
|
||||
|
||||
private void InitializeEnabledValue()
|
||||
{
|
||||
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredImageResizerEnabledValue();
|
||||
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
// Get the enabled state from GPO.
|
||||
_enabledStateIsGPOConfigured = true;
|
||||
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
|
||||
}
|
||||
else
|
||||
{
|
||||
_isEnabled = GeneralSettingsConfig.Enabled.ImageResizer;
|
||||
}
|
||||
}
|
||||
|
||||
private GpoRuleConfigured _enabledGpoRuleConfiguration;
|
||||
private bool _enabledStateIsGPOConfigured;
|
||||
private bool _isEnabled;
|
||||
private ObservableCollection<ImageSize> _advancedSizes = new ObservableCollection<ImageSize>();
|
||||
private int _jpegQualityLevel;
|
||||
private int _pngInterlaceOption;
|
||||
private int _tiffCompressOption;
|
||||
private string _fileName;
|
||||
private bool _keepDateModified;
|
||||
private int _encoderGuidId;
|
||||
|
||||
public bool IsListViewFocusRequested { get; set; }
|
||||
|
||||
public bool IsEnabled
|
||||
{
|
||||
get
|
||||
{
|
||||
return _isEnabled;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (_enabledStateIsGPOConfigured)
|
||||
{
|
||||
// If it's GPO configured, shouldn't be able to change this state.
|
||||
return;
|
||||
}
|
||||
|
||||
if (value != _isEnabled)
|
||||
{
|
||||
// To set the status of ImageResizer in the General PowerToys settings.
|
||||
_isEnabled = value;
|
||||
GeneralSettingsConfig.Enabled.ImageResizer = value;
|
||||
OutGoingGeneralSettings snd = new OutGoingGeneralSettings(GeneralSettingsConfig);
|
||||
|
||||
SendConfigMSG(snd.ToString());
|
||||
OnPropertyChanged(nameof(IsEnabled));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEnabledGpoConfigured
|
||||
{
|
||||
get => _enabledStateIsGPOConfigured;
|
||||
}
|
||||
|
||||
public ObservableCollection<ImageSize> Sizes
|
||||
{
|
||||
get
|
||||
{
|
||||
return _advancedSizes;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
SavesImageSizes(value);
|
||||
_advancedSizes = value;
|
||||
OnPropertyChanged(nameof(Sizes));
|
||||
}
|
||||
}
|
||||
|
||||
public int JPEGQualityLevel
|
||||
{
|
||||
get
|
||||
{
|
||||
return _jpegQualityLevel;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (_jpegQualityLevel != value)
|
||||
{
|
||||
_jpegQualityLevel = value;
|
||||
Settings.Properties.ImageresizerJpegQualityLevel.Value = value;
|
||||
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
|
||||
OnPropertyChanged(nameof(JPEGQualityLevel));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int PngInterlaceOption
|
||||
{
|
||||
get
|
||||
{
|
||||
return _pngInterlaceOption;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (_pngInterlaceOption != value)
|
||||
{
|
||||
_pngInterlaceOption = value;
|
||||
Settings.Properties.ImageresizerPngInterlaceOption.Value = value;
|
||||
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
|
||||
OnPropertyChanged(nameof(PngInterlaceOption));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int TiffCompressOption
|
||||
{
|
||||
get
|
||||
{
|
||||
return _tiffCompressOption;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (_tiffCompressOption != value)
|
||||
{
|
||||
_tiffCompressOption = value;
|
||||
Settings.Properties.ImageresizerTiffCompressOption.Value = value;
|
||||
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
|
||||
OnPropertyChanged(nameof(TiffCompressOption));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string FileName
|
||||
{
|
||||
get
|
||||
{
|
||||
return _fileName;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
_fileName = value;
|
||||
Settings.Properties.ImageresizerFileName.Value = value;
|
||||
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
|
||||
OnPropertyChanged(nameof(FileName));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool KeepDateModified
|
||||
{
|
||||
get
|
||||
{
|
||||
return _keepDateModified;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_keepDateModified = value;
|
||||
Settings.Properties.ImageresizerKeepDateModified.Value = value;
|
||||
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
|
||||
OnPropertyChanged(nameof(KeepDateModified));
|
||||
}
|
||||
}
|
||||
|
||||
public int Encoder
|
||||
{
|
||||
get
|
||||
{
|
||||
return _encoderGuidId;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
if (_encoderGuidId != value)
|
||||
{
|
||||
_encoderGuidId = value;
|
||||
_settingsUtils.SaveSettings(Settings.Properties.ImageresizerSizes.ToJsonString(), ModuleName, "sizes.json");
|
||||
Settings.Properties.ImageresizerFallbackEncoder.Value = GetEncoderGuid(value);
|
||||
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
|
||||
OnPropertyChanged(nameof(Encoder));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public string EncoderGuid
|
||||
{
|
||||
get
|
||||
{
|
||||
return ImageResizerViewModel.GetEncoderGuid(_encoderGuidId);
|
||||
}
|
||||
}
|
||||
|
||||
public void AddRow(string sizeNamePrefix)
|
||||
{
|
||||
/// 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;
|
||||
|
||||
ObservableCollection<ImageSize> imageSizes = Sizes;
|
||||
int maxId = imageSizes.Count > 0 ? imageSizes.OrderBy(x => x.Id).Last().Id : -1;
|
||||
string sizeName = GenerateNameForNewSize(imageSizes, sizeNamePrefix);
|
||||
|
||||
ImageSize newSize = new ImageSize(maxId + 1, sizeName, ResizeFit.Fit, 854, 480, ResizeUnit.Pixel);
|
||||
newSize.PropertyChanged += SizePropertyChanged;
|
||||
imageSizes.Add(newSize);
|
||||
_advancedSizes = imageSizes;
|
||||
SavesImageSizes(imageSizes);
|
||||
|
||||
// Set the focus requested flag to indicate that an add operation has occurred during the ContainerContentChanging event
|
||||
IsListViewFocusRequested = true;
|
||||
}
|
||||
|
||||
public void DeleteImageSize(int id)
|
||||
{
|
||||
ImageSize size = _advancedSizes.First(x => x.Id == id);
|
||||
ObservableCollection<ImageSize> imageSizes = Sizes;
|
||||
imageSizes.Remove(size);
|
||||
|
||||
_advancedSizes = imageSizes;
|
||||
SavesImageSizes(imageSizes);
|
||||
}
|
||||
|
||||
public void SavesImageSizes(ObservableCollection<ImageSize> imageSizes)
|
||||
{
|
||||
_settingsUtils.SaveSettings(Settings.Properties.ImageresizerSizes.ToJsonString(), ModuleName, "sizes.json");
|
||||
Settings.Properties.ImageresizerSizes = new ImageResizerSizes(imageSizes);
|
||||
Settings = new ImageResizerSettings(resourceLoader);
|
||||
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
|
||||
}
|
||||
|
||||
public static string GetEncoderGuid(int value)
|
||||
// set the callback functions value to handle outgoing IPC message.
|
||||
SendConfigMSG = ipcMSGCallBackFunc;
|
||||
|
||||
InitializeEnabledValue();
|
||||
|
||||
Sizes = new ObservableCollection<ImageSize>(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;
|
||||
Encoder = GetEncoderIndex(Settings.Properties.ImageresizerFallbackEncoder.Value);
|
||||
|
||||
_customSize = Settings.Properties.ImageresizerCustomSize.Value;
|
||||
|
||||
_isInitializing = false;
|
||||
}
|
||||
|
||||
private void InitializeEnabledValue()
|
||||
{
|
||||
_enabledGpoRuleConfiguration = GPOWrapper.GetConfiguredImageResizerEnabledValue();
|
||||
if (_enabledGpoRuleConfiguration == GpoRuleConfigured.Disabled || _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled)
|
||||
{
|
||||
// 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;
|
||||
// Get the enabled state from GPO.
|
||||
_enabledStateIsGPOConfigured = true;
|
||||
_isEnabled = _enabledGpoRuleConfiguration == GpoRuleConfigured.Enabled;
|
||||
}
|
||||
|
||||
public static int GetEncoderIndex(string value)
|
||||
else
|
||||
{
|
||||
// PNG Encoder guid
|
||||
if (value == "1b7cfaf4-713f-473c-bbcd-6137425faeaf")
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Bitmap Encoder guid
|
||||
else if (value == "0af1d87e-fcfe-4188-bdeb-a7906471cbe3")
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// JPEG Encoder guid
|
||||
else if (value == "19e4a5aa-5662-4fc5-a0c0-1758028e1057")
|
||||
{
|
||||
return 2;
|
||||
}
|
||||
|
||||
// Tiff encoder guid.
|
||||
else if (value == "163bcc30-e2e9-4f0b-961d-a3e9fdb788a3")
|
||||
{
|
||||
return 3;
|
||||
}
|
||||
|
||||
// Tiff encoder guid.
|
||||
else if (value == "57a37caa-367a-4540-916b-f183c5093a4b")
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
|
||||
// Gif encoder guid.
|
||||
else if (value == "1f8a5601-7d4d-4cbd-9c82-1bc8d4eeb9a5")
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void SizePropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
ImageSize modifiedSize = (ImageSize)sender;
|
||||
ObservableCollection<ImageSize> imageSizes = Sizes;
|
||||
imageSizes.First(x => x.Id == modifiedSize.Id).Update(modifiedSize);
|
||||
_advancedSizes = imageSizes;
|
||||
SavesImageSizes(imageSizes);
|
||||
}
|
||||
|
||||
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.AsSpan(namePrefix.Length), out int number))
|
||||
{
|
||||
if (newSizeCounter < number)
|
||||
{
|
||||
newSizeCounter = number;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $"{namePrefix} {++newSizeCounter}";
|
||||
}
|
||||
|
||||
public void RefreshEnabledState()
|
||||
{
|
||||
InitializeEnabledValue();
|
||||
OnPropertyChanged(nameof(IsEnabled));
|
||||
_isEnabled = GeneralSettingsConfig.Enabled.ImageResizer;
|
||||
}
|
||||
}
|
||||
|
||||
private GpoRuleConfigured _enabledGpoRuleConfiguration;
|
||||
private bool _enabledStateIsGPOConfigured;
|
||||
private bool _isEnabled;
|
||||
private ObservableCollection<ImageSize> _sizes = [];
|
||||
private int _jpegQualityLevel;
|
||||
private int _pngInterlaceOption;
|
||||
private int _tiffCompressOption;
|
||||
private string _fileName;
|
||||
private bool _keepDateModified;
|
||||
private int _encoderGuidId;
|
||||
|
||||
public bool IsListViewFocusRequested { get; set; }
|
||||
|
||||
public bool IsEnabled
|
||||
{
|
||||
get => _isEnabled;
|
||||
|
||||
set
|
||||
{
|
||||
if (_enabledStateIsGPOConfigured)
|
||||
{
|
||||
// If it's GPO configured, shouldn't be able to change this state.
|
||||
return;
|
||||
}
|
||||
|
||||
if (value != _isEnabled)
|
||||
{
|
||||
// To set the status of ImageResizer in the General PowerToys settings.
|
||||
_isEnabled = value;
|
||||
GeneralSettingsConfig.Enabled.ImageResizer = value;
|
||||
OutGoingGeneralSettings snd = new OutGoingGeneralSettings(GeneralSettingsConfig);
|
||||
|
||||
SendConfigMSG(snd.ToString());
|
||||
OnPropertyChanged(nameof(IsEnabled));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsEnabledGpoConfigured
|
||||
{
|
||||
get => _enabledStateIsGPOConfigured;
|
||||
}
|
||||
|
||||
public ObservableCollection<ImageSize> Sizes
|
||||
{
|
||||
get => _sizes;
|
||||
|
||||
set
|
||||
{
|
||||
if (_sizes != null)
|
||||
{
|
||||
_sizes.CollectionChanged -= Sizes_CollectionChanged;
|
||||
UnsubscribeFromItemPropertyChanged(_sizes);
|
||||
}
|
||||
|
||||
_sizes = value;
|
||||
|
||||
if (_sizes != null)
|
||||
{
|
||||
_sizes.CollectionChanged += Sizes_CollectionChanged;
|
||||
SubscribeToItemPropertyChanged(_sizes);
|
||||
}
|
||||
|
||||
OnPropertyChanged(nameof(Sizes));
|
||||
|
||||
if (!_isInitializing)
|
||||
{
|
||||
SaveImageSizes();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Sizes_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
|
||||
{
|
||||
SubscribeToItemPropertyChanged(e.NewItems?.Cast<ImageSize>());
|
||||
UnsubscribeFromItemPropertyChanged(e.OldItems?.Cast<ImageSize>());
|
||||
SaveImageSizes();
|
||||
}
|
||||
|
||||
private void SubscribeToItemPropertyChanged(IEnumerable<ImageSize> items)
|
||||
{
|
||||
if (items != null)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
item.PropertyChanged += SizePropertyChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void UnsubscribeFromItemPropertyChanged(IEnumerable<ImageSize> items)
|
||||
{
|
||||
if (items != null)
|
||||
{
|
||||
foreach (var item in items)
|
||||
{
|
||||
item.PropertyChanged -= SizePropertyChanged;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void SetProperty<T>(ref T backingField, T value, Action<T> updateSettingsAction, [CallerMemberName] string propertyName = null)
|
||||
{
|
||||
if (!EqualityComparer<T>.Default.Equals(backingField, value))
|
||||
{
|
||||
backingField = value;
|
||||
|
||||
if (!_isInitializing)
|
||||
{
|
||||
updateSettingsAction(value);
|
||||
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
|
||||
}
|
||||
|
||||
OnPropertyChanged(propertyName);
|
||||
}
|
||||
}
|
||||
|
||||
public int JPEGQualityLevel
|
||||
{
|
||||
get => _jpegQualityLevel;
|
||||
|
||||
set
|
||||
{
|
||||
SetProperty(ref _jpegQualityLevel, value, v => Settings.Properties.ImageresizerJpegQualityLevel.Value = v);
|
||||
}
|
||||
}
|
||||
|
||||
public int PngInterlaceOption
|
||||
{
|
||||
get => _pngInterlaceOption;
|
||||
|
||||
set
|
||||
{
|
||||
SetProperty(ref _pngInterlaceOption, value, v => Settings.Properties.ImageresizerPngInterlaceOption.Value = v);
|
||||
}
|
||||
}
|
||||
|
||||
public int TiffCompressOption
|
||||
{
|
||||
get => _tiffCompressOption;
|
||||
|
||||
set
|
||||
{
|
||||
SetProperty(ref _tiffCompressOption, value, v => Settings.Properties.ImageresizerTiffCompressOption.Value = v);
|
||||
}
|
||||
}
|
||||
|
||||
public string FileName
|
||||
{
|
||||
get => _fileName;
|
||||
|
||||
set
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(value))
|
||||
{
|
||||
SetProperty(ref _fileName, value, v => Settings.Properties.ImageresizerFileName.Value = v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool KeepDateModified
|
||||
{
|
||||
get => _keepDateModified;
|
||||
|
||||
set
|
||||
{
|
||||
SetProperty(ref _keepDateModified, value, v => Settings.Properties.ImageresizerKeepDateModified.Value = v);
|
||||
}
|
||||
}
|
||||
|
||||
public int Encoder
|
||||
{
|
||||
get => _encoderGuidId;
|
||||
|
||||
set
|
||||
{
|
||||
SetProperty(ref _encoderGuidId, value, v => Settings.Properties.ImageresizerFallbackEncoder.Value = GetEncoderGuid(v));
|
||||
}
|
||||
}
|
||||
|
||||
public string EncoderGuid => GetEncoderGuid(_encoderGuidId);
|
||||
|
||||
public static string GetEncoderGuid(int index) =>
|
||||
index < 0 || index >= EncoderGuids.Count ? throw new ArgumentOutOfRangeException(nameof(index)) : EncoderGuids[index];
|
||||
|
||||
public static int GetEncoderIndex(string encoderGuid)
|
||||
{
|
||||
int index = EncoderGuids.IndexOf(encoderGuid);
|
||||
return index == -1 ? throw new ArgumentException("Encoder GUID not found.", nameof(encoderGuid)) : index;
|
||||
}
|
||||
|
||||
public void AddImageSize(string namePrefix = "")
|
||||
{
|
||||
if (string.IsNullOrEmpty(namePrefix))
|
||||
{
|
||||
namePrefix = DefaultPresetNamePrefix;
|
||||
}
|
||||
|
||||
int maxId = Sizes.Count > 0 ? Sizes.Max(x => x.Id) : -1;
|
||||
string sizeName = GenerateNameForNewSize(namePrefix);
|
||||
|
||||
Sizes.Add(new ImageSize(maxId + 1, GenerateNameForNewSize(namePrefix), _customSize.Fit, _customSize.Width, _customSize.Height, _customSize.Unit));
|
||||
|
||||
// Set the focus requested flag to indicate that an add operation has occurred during the ContainerContentChanging event
|
||||
IsListViewFocusRequested = true;
|
||||
}
|
||||
|
||||
public void DeleteImageSize(int id)
|
||||
{
|
||||
ImageSize size = _sizes.First(x => x.Id == id);
|
||||
Sizes.Remove(size);
|
||||
}
|
||||
|
||||
public void SaveImageSizes()
|
||||
{
|
||||
Settings.Properties.ImageresizerSizes = new ImageResizerSizes(Sizes);
|
||||
_settingsUtils.SaveSettings(Settings.Properties.ImageresizerSizes.ToJsonString(), ModuleName, "sizes.json");
|
||||
_settingsUtils.SaveSettings(Settings.ToJsonString(), ModuleName);
|
||||
}
|
||||
|
||||
public void SizePropertyChanged(object sender, PropertyChangedEventArgs e)
|
||||
{
|
||||
SaveImageSizes();
|
||||
}
|
||||
|
||||
private string GenerateNameForNewSize(string namePrefix)
|
||||
{
|
||||
int newSizeCounter = 0;
|
||||
|
||||
foreach (var name in Sizes.Select(x => x.Name))
|
||||
{
|
||||
if (name.StartsWith(namePrefix, StringComparison.InvariantCulture) &&
|
||||
int.TryParse(name.AsSpan(namePrefix.Length), out int number) &&
|
||||
newSizeCounter < number)
|
||||
{
|
||||
newSizeCounter = number;
|
||||
}
|
||||
}
|
||||
|
||||
return $"{namePrefix} {++newSizeCounter}";
|
||||
}
|
||||
|
||||
public void RefreshEnabledState()
|
||||
{
|
||||
InitializeEnabledValue();
|
||||
OnPropertyChanged(nameof(IsEnabled));
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче