mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-04-03 01:36:31 +02:00
[ImageResizer] Fix issues with blank Width and Height controls (#37373)
* Allow custom preset's dimensions to be blank in the UI while still persisted as 0. * XAML formatting - reorder namespaces. * Add "(auto)" text to zero-value Width/Height in Settings. Ensure Width and Height fields in flyout are formatted to empty when their value is 0.
This commit is contained in:
@@ -21,6 +21,8 @@
|
||||
<v:VisibilityBoolConverter x:Key="VisibilityBoolConverter" />
|
||||
<v:EnumToIntConverter x:Key="EnumToIntConverter" />
|
||||
<v:AccessTextToTextConverter x:Key="AccessTextToTextConverter" />
|
||||
<v:NumberBoxValueConverter x:Key="NumberBoxValueConverter" />
|
||||
<v:ZeroToEmptyStringNumberFormatter x:Key="ZeroToEmptyStringNumberFormatter" />
|
||||
</ResourceDictionary>
|
||||
</Application.Resources>
|
||||
</Application>
|
||||
@@ -10,29 +10,55 @@ using System.Windows.Data;
|
||||
|
||||
using ImageResizer.Properties;
|
||||
|
||||
namespace ImageResizer.Views
|
||||
namespace ImageResizer.Views;
|
||||
|
||||
/// <summary>
|
||||
/// 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".
|
||||
/// </summary>
|
||||
[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)
|
||||
/// <summary>
|
||||
/// Converts a double to a string, optionally showing "Auto" for 0 values. NaN values are
|
||||
/// converted to empty strings.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to convert from <see cref="double"/> to
|
||||
/// <see cref="string"/>.</param>
|
||||
/// <param name="targetType">The conversion target type. <see cref="string"/> here.</param>
|
||||
/// <param name="parameter">Set to "Auto" to return the localized "Auto" string if the
|
||||
/// value is 0.</param>
|
||||
/// <param name="culture">The <see cref="CultureInfo"/> to use for the number formatting.
|
||||
/// </param>
|
||||
/// <returns>The string representation of the passed-in value.</returns>
|
||||
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)
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="value">The string value to convert.</param>
|
||||
/// <param name="targetType">The conversion target type. <see cref="double"/> here.</param>
|
||||
/// <param name="parameter">Converter parameter. Unused.</param>
|
||||
/// <param name="culture">The <see cref="CultureInfo"/> to use for the text parsing.</param>
|
||||
/// <returns>The corresponding double value.</returns>
|
||||
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,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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">
|
||||
|
||||
<Grid>
|
||||
<Grid.RowDefinitions>
|
||||
@@ -114,8 +115,12 @@
|
||||
KeyDown="Button_KeyDown"
|
||||
Minimum="0"
|
||||
SpinButtonPlacementMode="Inline">
|
||||
<ui:NumberBox.NumberFormatter>
|
||||
<v:ZeroToEmptyStringNumberFormatter />
|
||||
</ui:NumberBox.NumberFormatter>
|
||||
<ui:NumberBox.Value>
|
||||
<Binding
|
||||
Converter="{StaticResource NumberBoxValueConverter}"
|
||||
ElementName="SizeComboBox"
|
||||
Mode="TwoWay"
|
||||
Path="SelectedValue.Width"
|
||||
@@ -143,8 +148,12 @@
|
||||
Minimum="0"
|
||||
SpinButtonPlacementMode="Inline"
|
||||
Visibility="{Binding ElementName=SizeComboBox, Path=SelectedValue.ShowHeight, Converter={StaticResource BoolValueConverter}}">
|
||||
<ui:NumberBox.NumberFormatter>
|
||||
<v:ZeroToEmptyStringNumberFormatter />
|
||||
</ui:NumberBox.NumberFormatter>
|
||||
<ui:NumberBox.Value>
|
||||
<Binding
|
||||
Converter="{StaticResource NumberBoxValueConverter}"
|
||||
ElementName="SizeComboBox"
|
||||
Mode="TwoWay"
|
||||
Path="SelectedValue.Height"
|
||||
|
||||
32
src/modules/imageresizer/ui/Views/NumberBoxValueConverter.cs
Normal file
32
src/modules/imageresizer/ui/Views/NumberBoxValueConverter.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
// 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 System.Windows.Data;
|
||||
|
||||
namespace ImageResizer.Views;
|
||||
|
||||
public class NumberBoxValueConverter : IValueConverter
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts the underlying double value to a display-friendly format. Ensures that NaN values
|
||||
/// are not propagated to the UI.
|
||||
/// </summary>
|
||||
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) =>
|
||||
value is double d && double.IsNaN(d) ? 0 : value;
|
||||
|
||||
/// <summary>
|
||||
/// Converts the user input back to the underlying double value. If the input is not a valid
|
||||
/// number, 0 is returned.
|
||||
/// </summary>
|
||||
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,
|
||||
};
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
Reference in New Issue
Block a user