diff --git a/src/modules/imageresizer/ui/App.xaml b/src/modules/imageresizer/ui/App.xaml
index 30dd38a48fe9..a25c2c7a51b4 100644
--- a/src/modules/imageresizer/ui/App.xaml
+++ b/src/modules/imageresizer/ui/App.xaml
@@ -20,6 +20,8 @@
+
+
\ No newline at end of file
diff --git a/src/modules/imageresizer/ui/Views/AutoDoubleConverter.cs b/src/modules/imageresizer/ui/Views/AutoDoubleConverter.cs
index 69f886036b1e..631416a7c0ba 100644
--- a/src/modules/imageresizer/ui/Views/AutoDoubleConverter.cs
+++ b/src/modules/imageresizer/ui/Views/AutoDoubleConverter.cs
@@ -10,29 +10,55 @@
using ImageResizer.Properties;
-namespace ImageResizer.Views
+namespace ImageResizer.Views;
+
+///
+/// Converts between double and string for text-based controls bound to Width or Height fields.
+/// Optionally returns localized "Auto" text when the underlying value is 0, letting the UI show,
+/// for example "(auto) x 1024 pixels".
+///
+[ValueConversion(typeof(double), typeof(string))]
+internal class AutoDoubleConverter : IValueConverter
{
- [ValueConversion(typeof(double), typeof(string))]
- internal class AutoDoubleConverter : IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
+ ///
+ /// Converts a double to a string, optionally showing "Auto" for 0 values. NaN values are
+ /// converted to empty strings.
+ ///
+ /// The value to convert from to
+ /// .
+ /// The conversion target type. here.
+ /// Set to "Auto" to return the localized "Auto" string if the
+ /// value is 0.
+ /// The to use for the number formatting.
+ ///
+ /// The string representation of the passed-in value.
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
+ value switch
{
- var d = (double)value;
+ double d => d switch
+ {
+ double.NaN => "0",
+ 0 => (string)parameter == "Auto" ? Resources.Input_Auto : "0",
+ _ => d.ToString(culture),
+ },
- return d != 0
- ? d.ToString(culture)
- : (string)parameter == "Auto"
- ? Resources.Input_Auto
- : string.Empty;
- }
+ _ => "0",
+ };
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
+ ///
+ /// Converts the string representation back to a double, returning 0 if the string is empty,
+ /// null or not a valid number in the specified culture.
+ ///
+ /// The string value to convert.
+ /// The conversion target type. here.
+ /// Converter parameter. Unused.
+ /// The to use for the text parsing.
+ /// The corresponding double value.
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
+ value switch
{
- var text = (string)value;
-
- return !string.IsNullOrEmpty(text)
- ? double.Parse(text, culture)
- : 0;
- }
- }
+ null or "" => 0,
+ string text when double.TryParse(text, NumberStyles.Any, culture, out double result) => result,
+ _ => 0,
+ };
}
diff --git a/src/modules/imageresizer/ui/Views/InputPage.xaml b/src/modules/imageresizer/ui/Views/InputPage.xaml
index f1e997022b09..8249aef00dd1 100644
--- a/src/modules/imageresizer/ui/Views/InputPage.xaml
+++ b/src/modules/imageresizer/ui/Views/InputPage.xaml
@@ -4,7 +4,8 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:m="clr-namespace:ImageResizer.Models"
xmlns:p="clr-namespace:ImageResizer.Properties"
- xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml">
+ xmlns:ui="http://schemas.lepo.co/wpfui/2022/xaml"
+ xmlns:v="clr-namespace:ImageResizer.Views">
@@ -107,8 +108,12 @@
KeyDown="Button_KeyDown"
Minimum="0"
SpinButtonPlacementMode="Inline">
+
+
+
+
+
+
+ /// Converts the underlying double value to a display-friendly format. Ensures that NaN values
+ /// are not propagated to the UI.
+ ///
+ public object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
+ value is double d && double.IsNaN(d) ? 0 : value;
+
+ ///
+ /// Converts the user input back to the underlying double value. If the input is not a valid
+ /// number, 0 is returned.
+ ///
+ public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) =>
+ value switch
+ {
+ null => 0,
+ double d when double.IsNaN(d) => 0,
+ string str when !double.TryParse(str, out _) => 0,
+ _ => value,
+ };
+}
diff --git a/src/modules/imageresizer/ui/Views/ZeroToEmptyStringNumberFormatter.cs b/src/modules/imageresizer/ui/Views/ZeroToEmptyStringNumberFormatter.cs
new file mode 100644
index 000000000000..a753895e58bf
--- /dev/null
+++ b/src/modules/imageresizer/ui/Views/ZeroToEmptyStringNumberFormatter.cs
@@ -0,0 +1,37 @@
+// 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.Globalization;
+using Wpf.Ui.Controls;
+
+namespace ImageResizer.Views;
+
+public class ZeroToEmptyStringNumberFormatter : INumberFormatter, INumberParser
+{
+ public string FormatDouble(double? value) => value switch
+ {
+ null => string.Empty,
+ 0 => string.Empty,
+ _ => value.Value.ToString(CultureInfo.CurrentCulture),
+ };
+
+ public double? ParseDouble(string value)
+ {
+ if (string.IsNullOrWhiteSpace(value))
+ {
+ return 0;
+ }
+
+ return double.TryParse(value, NumberStyles.Any, CultureInfo.CurrentCulture, out double result) ? result : 0;
+ }
+
+ public string FormatInt(int? value) => throw new NotImplementedException();
+
+ public string FormatUInt(uint? value) => throw new NotImplementedException();
+
+ public int? ParseInt(string value) => throw new NotImplementedException();
+
+ public uint? ParseUInt(string value) => throw new NotImplementedException();
+}
diff --git a/src/settings-ui/Settings.UI/Converters/ImageResizerDoubleToAutoConverter.cs b/src/settings-ui/Settings.UI/Converters/ImageResizerDoubleToAutoConverter.cs
new file mode 100644
index 000000000000..63ba8cde9278
--- /dev/null
+++ b/src/settings-ui/Settings.UI/Converters/ImageResizerDoubleToAutoConverter.cs
@@ -0,0 +1,61 @@
+// 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.Globalization;
+using Microsoft.UI.Xaml.Data;
+
+namespace Microsoft.PowerToys.Settings.UI.Converters;
+
+///
+/// Converts between double and string for text-based controls bound to Width or Height fields.
+/// Optionally returns localized "Auto" text when the underlying value is 0, letting the UI show,
+/// for example "(auto) x 1024 pixels".
+///
+public sealed partial class ImageResizerDoubleToAutoConverter : IValueConverter
+{
+ private static readonly string AutoText =
+ Helpers.ResourceLoaderInstance.ResourceLoader.GetString("ImageResizer_AutoText");
+
+ ///
+ /// Converts a double to a string, optionally showing "Auto" for 0 values. NaN values are
+ /// converted to empty strings.
+ ///
+ /// The value to convert from to
+ /// .
+ /// The conversion target type. here.
+ /// Set to "Auto" to return the localized "Auto" string if the
+ /// value is 0.
+ /// Ignored.
+ /// The string representation of the passed-in value.
+ public object Convert(object value, Type targetType, object parameter, string language) =>
+ value switch
+ {
+ double d => d switch
+ {
+ double.NaN => "0",
+ 0 => (string)parameter == "Auto" ? AutoText : "0",
+ _ => d.ToString(CultureInfo.CurrentCulture),
+ },
+
+ _ => "0",
+ };
+
+ ///
+ /// Converts the string representation back to a double, returning 0 if the string is empty,
+ /// null or not a valid number in the specified culture.
+ ///
+ /// The string value to convert.
+ /// The conversion target type. here.
+ /// Converter parameter. Unused.
+ /// Ignored.
+ /// The corresponding double value.
+ public object ConvertBack(object value, Type targetType, object parameter, string language) =>
+ value switch
+ {
+ null or "" => 0.0,
+ string text when double.TryParse(text, NumberStyles.Any, CultureInfo.CurrentCulture, out double result) => result,
+ _ => 0.0,
+ };
+}
diff --git a/src/settings-ui/Settings.UI/Converters/ImageResizerNumberBoxValueConverter.cs b/src/settings-ui/Settings.UI/Converters/ImageResizerNumberBoxValueConverter.cs
new file mode 100644
index 000000000000..777657186df2
--- /dev/null
+++ b/src/settings-ui/Settings.UI/Converters/ImageResizerNumberBoxValueConverter.cs
@@ -0,0 +1,31 @@
+// 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 Microsoft.UI.Xaml.Data;
+
+namespace Microsoft.PowerToys.Settings.UI.Converters;
+
+public partial class ImageResizerNumberBoxValueConverter : IValueConverter
+{
+ ///
+ /// Converts the underlying double value to a display-friendly format. Ensures that NaN values
+ /// are not propagated to the UI.
+ ///
+ public object Convert(object value, Type targetType, object parameter, string language) =>
+ value is double d && double.IsNaN(d) ? 0.0 : value;
+
+ ///
+ /// Converts the user input back to the underlying double value. If the input is not a valid
+ /// number, a double with value 0 is returned.
+ ///
+ public object ConvertBack(object value, Type targetType, object parameter, string language) =>
+ value switch
+ {
+ null => 0.0,
+ double d when double.IsNaN(d) => 0.0,
+ string str when !double.TryParse(str, out _) => 0.0,
+ _ => value,
+ };
+}
diff --git a/src/settings-ui/Settings.UI/Converters/ImageResizerZeroToEmptyStringNumberFormatter.cs b/src/settings-ui/Settings.UI/Converters/ImageResizerZeroToEmptyStringNumberFormatter.cs
new file mode 100644
index 000000000000..241210f6c056
--- /dev/null
+++ b/src/settings-ui/Settings.UI/Converters/ImageResizerZeroToEmptyStringNumberFormatter.cs
@@ -0,0 +1,39 @@
+// 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.Globalization;
+using Microsoft.UI.Xaml.Controls;
+
+namespace Microsoft.PowerToys.Settings.UI.Converters;
+
+public partial class ImageResizerZeroToEmptyStringNumberFormatter
+{
+ public string Format(long value) => throw new NotImplementedException();
+
+ public string Format(ulong value) => throw new NotImplementedException();
+
+ public string Format(double value) => throw new NotImplementedException();
+
+ public string FormatDouble(double? value) => value switch
+ {
+ null => string.Empty,
+ 0 => string.Empty,
+ _ => value.Value.ToString(CultureInfo.CurrentCulture),
+ };
+
+ public double? ParseDouble(string text)
+ {
+ if (string.IsNullOrWhiteSpace(text))
+ {
+ return 0.0;
+ }
+
+ return double.TryParse(text, NumberStyles.Any, CultureInfo.CurrentCulture, out double result) ? result : 0.0;
+ }
+
+ public long? ParseInt(string text) => throw new NotImplementedException();
+
+ public ulong? ParseUInt(string text) => throw new NotImplementedException();
+}
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Controls/ImageResizerDimensionsNumberBox.cs b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ImageResizerDimensionsNumberBox.cs
new file mode 100644
index 000000000000..a310f2d675c1
--- /dev/null
+++ b/src/settings-ui/Settings.UI/SettingsXAML/Controls/ImageResizerDimensionsNumberBox.cs
@@ -0,0 +1,38 @@
+// 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 Microsoft.UI.Xaml;
+using Microsoft.UI.Xaml.Controls;
+
+namespace Microsoft.PowerToys.Settings.UI.Controls;
+
+public partial class ImageResizerDimensionsNumberBox : NumberBox
+{
+ public ImageResizerDimensionsNumberBox()
+ {
+ this.Loaded += (_, _) => UpdateDisplayText();
+
+ this.ValueChanged += (_, _) => UpdateDisplayText();
+
+ this.GotFocus += (s, e) =>
+ {
+ // Show "0" in the UI when focused on the empty value. This ensures that the spinbutton
+ // controls are usable.
+ if (Value is double.NaN)
+ {
+ Value = 0.0;
+ }
+ };
+
+ this.LostFocus += (_, _) => UpdateDisplayText();
+ }
+
+ private void UpdateDisplayText()
+ {
+ if (FocusState == FocusState.Unfocused && Value == 0)
+ {
+ Text = string.Empty;
+ }
+ }
+}
diff --git a/src/settings-ui/Settings.UI/SettingsXAML/Views/ImageResizerPage.xaml b/src/settings-ui/Settings.UI/SettingsXAML/Views/ImageResizerPage.xaml
index 7e7d956ce91b..2db21e91adfb 100644
--- a/src/settings-ui/Settings.UI/SettingsXAML/Views/ImageResizerPage.xaml
+++ b/src/settings-ui/Settings.UI/SettingsXAML/Views/ImageResizerPage.xaml
@@ -19,6 +19,9 @@
+
+
+
+ Text="{x:Bind Width, Mode=OneWay, Converter={StaticResource ImageResizerDoubleToAutoConverter}, ConverterParameter=Auto}" />
-
+ Value="{x:Bind Width, Mode=TwoWay, Converter={StaticResource ImageResizerNumberBoxValueConverter}}" />
-
+ Value="{x:Bind Height, Mode=TwoWay, Converter={StaticResource ImageResizerNumberBoxValueConverter}}" />
TIFF compression
{Locked="TIFF"}
+
+ (auto)
+ Displayed on the preset card when the Width or Height property is zero. The same as "Input_Auto" in the ImageResizerUI project's resources.
+
File
as in a computer file