[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:
Dave Rayment
2025-01-21 11:55:02 +00:00
committed by GitHub
parent b33e0be178
commit 438d17302e
9 changed files with 615 additions and 715 deletions

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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;
}
}