From bce9ac6e6fae5a0060834cca14871b2061ae1f10 Mon Sep 17 00:00:00 2001 From: h3xds1nz Date: Sat, 11 Jan 2025 15:54:34 +0100 Subject: [PATCH 1/8] Stop duplicating functionality of IsDefinedMouseAction --- .../Windows/Input/Command/MouseGesture.cs | 33 ++++++++----------- 1 file changed, 14 insertions(+), 19 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGesture.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGesture.cs index 9320b104a99..31ec452f878 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGesture.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGesture.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. @@ -53,13 +53,13 @@ public MouseGesture(MouseAction mouseAction): this(mouseAction, ModifierKeys.Non /// /// Mouse Action /// Modifiers - public MouseGesture( MouseAction mouseAction,ModifierKeys modifiers) // acclerator action + public MouseGesture(MouseAction mouseAction, ModifierKeys modifiers) // acclerator action { - if (!MouseGesture.IsDefinedMouseAction(mouseAction)) - throw new InvalidEnumArgumentException("mouseAction", (int)mouseAction, typeof(MouseAction)); + if (!MouseActionConverter.IsDefinedMouseAction(mouseAction)) + throw new InvalidEnumArgumentException(nameof(mouseAction), (int)mouseAction, typeof(MouseAction)); if (!ModifierKeysConverter.IsDefinedModifierKeys(modifiers)) - throw new InvalidEnumArgumentException("modifiers", (int)modifiers, typeof(ModifierKeys)); + throw new InvalidEnumArgumentException(nameof(modifiers), (int)modifiers, typeof(ModifierKeys)); _modifiers = modifiers; _mouseAction = mouseAction; @@ -86,12 +86,13 @@ public MouseAction MouseAction } set { - if (!MouseGesture.IsDefinedMouseAction((MouseAction)value)) - throw new InvalidEnumArgumentException("value", (int)value, typeof(MouseAction)); + if (!MouseActionConverter.IsDefinedMouseAction(value)) + throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(MouseAction)); + if (_mouseAction != value) { - _mouseAction = (MouseAction)value; - OnPropertyChanged("MouseAction"); + _mouseAction = value; + OnPropertyChanged(nameof(MouseAction)); } } } @@ -107,13 +108,13 @@ public ModifierKeys Modifiers } set { - if (!ModifierKeysConverter.IsDefinedModifierKeys((ModifierKeys)value)) - throw new InvalidEnumArgumentException("value", (int)value, typeof(ModifierKeys)); + if (!ModifierKeysConverter.IsDefinedModifierKeys(value)) + throw new InvalidEnumArgumentException(nameof(value), (int)value, typeof(ModifierKeys)); if (_modifiers != value) { - _modifiers = (ModifierKeys)value; - OnPropertyChanged("Modifiers"); + _modifiers = value; + OnPropertyChanged(nameof(Modifiers)); } } } @@ -135,12 +136,6 @@ public override bool Matches(object targetElement, InputEventArgs inputEventArgs return false; } - - // Helper like Enum.IsDefined, for MouseAction. - internal static bool IsDefinedMouseAction(MouseAction mouseAction) - { - return (mouseAction >= MouseAction.None && mouseAction <= MouseAction.MiddleDoubleClick); - } #endregion Public Methods #region Internal NotifyProperty changed From 0ce941a299433ff02573a1b0590e1115a84a0daa Mon Sep 17 00:00:00 2001 From: h3xds1nz Date: Sat, 11 Jan 2025 15:56:36 +0100 Subject: [PATCH 2/8] Simplify CanConvertFrom --- .../Windows/Input/Command/MouseGestureConverter.cs | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs index a864915b898..152674a17f1 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. @@ -31,14 +31,7 @@ public class MouseGestureConverter : TypeConverter public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { // We can only handle string. - if (sourceType == typeof(string)) - { - return true; - } - else - { - return false; - } + return sourceType == typeof(string); } /// From 3942dda840a36a067c7c60701e9de590000fa61b Mon Sep 17 00:00:00 2001 From: h3xds1nz Date: Sat, 11 Jan 2025 15:59:06 +0100 Subject: [PATCH 3/8] Simplify CanConvertTo --- .../Input/Command/MouseGestureConverter.cs | 45 +++++++++---------- 1 file changed, 20 insertions(+), 25 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs index 152674a17f1..265a5750a3d 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs @@ -34,6 +34,26 @@ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceT return sourceType == typeof(string); } + /// + ///TypeConverter method override. + /// + ///ITypeDescriptorContext + ///Type to convert to + ///true if conversion is possible + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) + { + // We can convert to an InstanceDescriptor or to a string. + if (destinationType != typeof(string)) + return false; + + // When invoked by the serialization engine we can convert to string only for known type + if (context?.Instance is not MouseGesture mouseGesture) + return false; + + return ModifierKeysConverter.IsDefinedModifierKeys(mouseGesture.Modifiers) && + MouseActionConverter.IsDefinedMouseAction(mouseGesture.MouseAction); + } + /// /// ConvertFrom /// @@ -97,31 +117,6 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c throw GetConvertFromException(source); } - /// - ///TypeConverter method override. - /// - ///ITypeDescriptorContext - ///Type to convert to - ///true if conversion is possible - public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) - { - // We can convert to an InstanceDescriptor or to a string. - if (destinationType == typeof(string)) - { - // When invoked by the serialization engine we can convert to string only for known type - if (context != null && context.Instance != null) - { - MouseGesture mouseGesture = context.Instance as MouseGesture; - if (mouseGesture != null) - { - return (ModifierKeysConverter.IsDefinedModifierKeys(mouseGesture.Modifiers) - && MouseActionConverter.IsDefinedMouseAction(mouseGesture.MouseAction)); - } - } - } - return false; - } - /// /// ConvertTo() /// From f45f779d3996a975fea84cd88049e34f95620680 Mon Sep 17 00:00:00 2001 From: h3xds1nz Date: Sat, 11 Jan 2025 16:39:18 +0100 Subject: [PATCH 4/8] Optimize ConvertFrom --- .../Input/Command/MouseActionConverter.cs | 37 ++++++----- .../Input/Command/MouseGestureConverter.cs | 64 ++++--------------- .../Windows/Input/ModifierKeysConverter.cs | 12 ++++ 3 files changed, 48 insertions(+), 65 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseActionConverter.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseActionConverter.cs index 62f3ad65dc8..076adfb69e1 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseActionConverter.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseActionConverter.cs @@ -1,7 +1,7 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. +using System.Runtime.CompilerServices; using System.ComponentModel; using System.Globalization; @@ -57,21 +57,28 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c throw GetConvertFromException(source); ReadOnlySpan mouseActionToken = mouseAction.AsSpan().Trim(); - return mouseActionToken switch - { - _ when mouseActionToken.IsEmpty => MouseAction.None, // Special casing as produced by "ConvertTo" - _ when mouseActionToken.Equals("None", StringComparison.OrdinalIgnoreCase) => MouseAction.None, - _ when mouseActionToken.Equals("LeftClick", StringComparison.OrdinalIgnoreCase) => MouseAction.LeftClick, - _ when mouseActionToken.Equals("RightClick", StringComparison.OrdinalIgnoreCase) => MouseAction.RightClick, - _ when mouseActionToken.Equals("MiddleClick", StringComparison.OrdinalIgnoreCase) => MouseAction.MiddleClick, - _ when mouseActionToken.Equals("WheelClick", StringComparison.OrdinalIgnoreCase) => MouseAction.WheelClick, - _ when mouseActionToken.Equals("LeftDoubleClick", StringComparison.OrdinalIgnoreCase) => MouseAction.LeftDoubleClick, - _ when mouseActionToken.Equals("RightDoubleClick", StringComparison.OrdinalIgnoreCase) => MouseAction.RightDoubleClick, - _ when mouseActionToken.Equals("MiddleDoubleClick", StringComparison.OrdinalIgnoreCase) => MouseAction.MiddleDoubleClick, - _ => throw new NotSupportedException(SR.Format(SR.Unsupported_MouseAction, mouseActionToken.ToString())) - }; + + return ConvertFromImpl(mouseActionToken); } + /// + /// Converts to its represensation. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static MouseAction ConvertFromImpl(ReadOnlySpan mouseActionToken) => mouseActionToken switch + { + _ when mouseActionToken.IsEmpty => MouseAction.None, // Special casing as produced by "ConvertTo" + _ when mouseActionToken.Equals("None", StringComparison.OrdinalIgnoreCase) => MouseAction.None, + _ when mouseActionToken.Equals("LeftClick", StringComparison.OrdinalIgnoreCase) => MouseAction.LeftClick, + _ when mouseActionToken.Equals("RightClick", StringComparison.OrdinalIgnoreCase) => MouseAction.RightClick, + _ when mouseActionToken.Equals("MiddleClick", StringComparison.OrdinalIgnoreCase) => MouseAction.MiddleClick, + _ when mouseActionToken.Equals("WheelClick", StringComparison.OrdinalIgnoreCase) => MouseAction.WheelClick, + _ when mouseActionToken.Equals("LeftDoubleClick", StringComparison.OrdinalIgnoreCase) => MouseAction.LeftDoubleClick, + _ when mouseActionToken.Equals("RightDoubleClick", StringComparison.OrdinalIgnoreCase) => MouseAction.RightDoubleClick, + _ when mouseActionToken.Equals("MiddleDoubleClick", StringComparison.OrdinalIgnoreCase) => MouseAction.MiddleDoubleClick, + _ => throw new NotSupportedException(SR.Format(SR.Unsupported_MouseAction, mouseActionToken.ToString())) + }; + /// /// Converts a of to its represensation. /// diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs index 265a5750a3d..c895dfaa9ae 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs @@ -63,58 +63,22 @@ public override bool CanConvertTo(ITypeDescriptorContext context, Type destinati /// public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object source) { - if (source is string && source != null) + if (source is not string sourceString) + throw GetConvertFromException(source); + + ReadOnlySpan trimmedSource = sourceString.AsSpan().Trim(); + + // Break apart MouseAction and ModifierKeys + int index = trimmedSource.LastIndexOf('+'); + if (index >= 0) { - string fullName = ((string)source).Trim(); - string mouseActionToken; - string modifiersToken; - - if (fullName.Length == 0) - return new MouseGesture(MouseAction.None, ModifierKeys.None); - - // break apart LocalName and Prefix - int Offset = fullName.LastIndexOf(MODIFIERS_DELIMITER); - if (Offset >= 0) - { // modifiers exists - modifiersToken = fullName.Substring(0,Offset); - mouseActionToken = fullName.Substring(Offset + 1); - } - else - { - modifiersToken = String.Empty; - mouseActionToken = fullName; - } - - TypeConverter mouseActionConverter = TypeDescriptor.GetConverter(typeof(System.Windows.Input.MouseAction)); - if (null != mouseActionConverter ) - { - object mouseAction = mouseActionConverter.ConvertFrom(context, culture, mouseActionToken); - // mouseAction Converter will throw Exception, if it fails, - // so we don't need to check once more for bogus - // MouseAction values - if (mouseAction != null) - { - if (modifiersToken != String.Empty) - { - TypeConverter modifierKeysConverter = TypeDescriptor.GetConverter(typeof(System.Windows.Input.ModifierKeys)); - if (null != modifierKeysConverter) - { - object modifierKeys = modifierKeysConverter.ConvertFrom(context, culture, modifiersToken); - - if (modifierKeys != null && modifierKeys is ModifierKeys) - { - return new MouseGesture((MouseAction)mouseAction, (ModifierKeys)modifierKeys); - } - } - } - else - { - return new MouseGesture((MouseAction)mouseAction); - } - } - } + ReadOnlySpan mouseActionToken = trimmedSource.Slice(index + 1).TrimStart(); + ReadOnlySpan modifiersToken = trimmedSource.Slice(0, index).TrimEnd(); + + return new MouseGesture(MouseActionConverter.ConvertFromImpl(mouseActionToken), ModifierKeysConverter.ConvertFromImpl(modifiersToken)); } - throw GetConvertFromException(source); + + return new MouseGesture(MouseActionConverter.ConvertFromImpl(trimmedSource), ModifierKeys.None); } /// diff --git a/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Input/ModifierKeysConverter.cs b/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Input/ModifierKeysConverter.cs index 3d2789703f0..112c741faed 100644 --- a/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Input/ModifierKeysConverter.cs +++ b/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Input/ModifierKeysConverter.cs @@ -58,6 +58,18 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c ReadOnlySpan modifiersToken = stringSource.AsSpan().Trim(); + return ConvertFromImpl(modifiersToken); + } + + /// + /// Converts to its represensation. + /// + /// + /// is expected to have separated with '+', with any amount of whitespace. + /// + [MethodImpl(MethodImplOptions.AggressiveInlining)] + internal static ModifierKeys ConvertFromImpl(ReadOnlySpan modifiersToken) + { // Empty token means there were no modifiers, exit early if (modifiersToken.IsEmpty) return ModifierKeys.None; From 189fce1bdfccbc32ad4f5dbac519aed066d71d26 Mon Sep 17 00:00:00 2001 From: h3xds1nz Date: Sat, 11 Jan 2025 16:57:10 +0100 Subject: [PATCH 5/8] Put back regular Trim due to the pre-check missing on those --- .../System/Windows/Input/Command/MouseGestureConverter.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs index c895dfaa9ae..db6f8e7c3c3 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs @@ -72,8 +72,8 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c int index = trimmedSource.LastIndexOf('+'); if (index >= 0) { - ReadOnlySpan mouseActionToken = trimmedSource.Slice(index + 1).TrimStart(); - ReadOnlySpan modifiersToken = trimmedSource.Slice(0, index).TrimEnd(); + ReadOnlySpan mouseActionToken = trimmedSource.Slice(index + 1).Trim(); + ReadOnlySpan modifiersToken = trimmedSource.Slice(0, index).Trim(); return new MouseGesture(MouseActionConverter.ConvertFromImpl(mouseActionToken), ModifierKeysConverter.ConvertFromImpl(modifiersToken)); } From b97b0976fe6fcc7cc65198807bcdb51d3a4277e8 Mon Sep 17 00:00:00 2001 From: h3xds1nz Date: Sat, 11 Jan 2025 18:03:57 +0100 Subject: [PATCH 6/8] Optimize ConvertTo; small opt in ModifierKeysConverter --- .../Input/Command/MouseGestureConverter.cs | 54 +++++++++---------- .../Windows/Input/ModifierKeysConverter.cs | 34 +++++++++--- 2 files changed, 52 insertions(+), 36 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs index db6f8e7c3c3..af18366391a 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs @@ -20,8 +20,11 @@ namespace System.Windows.Input /// public class MouseGestureConverter : TypeConverter { - private const char MODIFIERS_DELIMITER = '+' ; - + /// + /// To aid with conversion from to . + /// + private static readonly MouseActionConverter s_mouseActionConverter = new(); + /// /// CanConvertFrom() /// @@ -93,34 +96,25 @@ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cul { ArgumentNullException.ThrowIfNull(destinationType); - if (destinationType == typeof(string)) - { - if (value == null) - return String.Empty; - - MouseGesture mouseGesture = value as MouseGesture; - if (mouseGesture != null) - { - string strGesture = ""; - - TypeConverter modifierKeysConverter = TypeDescriptor.GetConverter(typeof(System.Windows.Input.ModifierKeys)); - if (null != modifierKeysConverter) - { - strGesture += modifierKeysConverter.ConvertTo(context, culture, mouseGesture.Modifiers, destinationType) as string; - if (strGesture != String.Empty) - { - strGesture += MODIFIERS_DELIMITER ; - } - } - TypeConverter mouseActionConverter = TypeDescriptor.GetConverter(typeof(System.Windows.Input.MouseAction)); - if (null != mouseActionConverter) - { - strGesture += mouseActionConverter.ConvertTo(context, culture, mouseGesture.MouseAction, destinationType) as string; - } - return strGesture; - } - } - throw GetConvertToException(value,destinationType); + if (destinationType != typeof(string)) + throw GetConvertToException(value, destinationType); + + // Following checks are here to match the previous behavior + if (value is null) + return string.Empty; + + if (value is not MouseGesture mouseGesture) + throw GetConvertToException(value, destinationType); + + string mouseAction = (string)s_mouseActionConverter.ConvertTo(context, culture, mouseGesture.MouseAction, destinationType); + + if (mouseGesture.Modifiers is ModifierKeys.None) + return mouseAction; + + ReadOnlySpan modifierSpan = ModifierKeysConverter.ConvertMultipleModifiers(mouseGesture.Modifiers, stackalloc char[22]); + + // This will result in "Ctrl+" in case MouseAction was None but that's fine + return string.Create(CultureInfo.InvariantCulture, stackalloc char[42], $"{modifierSpan}+{mouseAction}"); } } } diff --git a/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Input/ModifierKeysConverter.cs b/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Input/ModifierKeysConverter.cs index 112c741faed..28b18c0ed01 100644 --- a/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Input/ModifierKeysConverter.cs +++ b/src/Microsoft.DotNet.Wpf/src/WindowsBase/System/Windows/Input/ModifierKeysConverter.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. @@ -135,10 +135,32 @@ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cul }; } - private static string ConvertMultipleModifiers(ModifierKeys modifiers) + /// + /// This is a proxy function for + /// so we do not initialize a stack-allocated buffer when we do not need to. + /// + /// The modifiers bits to format. + /// Formatted in [modifier_1]+[modifier_2] format. + [MethodImpl(MethodImplOptions.NoInlining)] + internal static string ConvertMultipleModifiers(ModifierKeys modifiers) + { + return new string(ConvertMultipleModifiers(modifiers, stackalloc char[22])); + } + + /// + /// Format multiple into -provided buffer. + /// + /// The modifiers bits to format. + /// The buffer to write formatted modifiers into. + /// Formatted in [modifier_1]+[modifier_2] format. + /// + /// Make sure the is at least 22 chars long, otherwise conversion might fail. + /// + internal static ReadOnlySpan ConvertMultipleModifiers(ModifierKeys modifiers, Span modifierSpan) { // Ctrl+Alt+Windows+Shift is the maximum char length, though the composition of such value is improbable - Span modifierSpan = stackalloc char[22]; + Debug.Assert(modifierSpan.Length > 21); + int totalLength = 0; if (modifiers.HasFlag(ModifierKeys.Control)) @@ -153,14 +175,14 @@ private static string ConvertMultipleModifiers(ModifierKeys modifiers) if (modifiers.HasFlag(ModifierKeys.Shift)) AppendWithDelimiter("Shift", ref totalLength, ref modifierSpan); - //Helper function to concatenate modifiers + // Helper function to concatenate modifiers [MethodImpl(MethodImplOptions.AggressiveInlining)] static void AppendWithDelimiter(string literal, ref int totalLength, ref Span modifierSpan) { // If this is not the first modifier in the span, we prepend a delimiter (e.g. Ctrl -> Ctrl+Alt) if (totalLength > 0) { - "+".CopyTo(modifierSpan.Slice(totalLength)); + modifierSpan[totalLength] = '+'; totalLength++; } @@ -168,7 +190,7 @@ static void AppendWithDelimiter(string literal, ref int totalLength, ref Span From 4a0ba6fdb0f3c0a1065ca90258b5716b94644e32 Mon Sep 17 00:00:00 2001 From: h3xds1nz Date: Sat, 11 Jan 2025 18:05:06 +0100 Subject: [PATCH 7/8] Fix license/header summary --- .../Windows/Input/Command/MouseGestureConverter.cs | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs index af18366391a..e8e005770f9 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs @@ -1,14 +1,5 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -// -// -// -// Description: MouseGestureConverter - Converts a MouseGesture string -// to the *Type* that the string represents -// -// using System.ComponentModel; // for TypeConverter using System.Globalization; // for CultureInfo @@ -16,7 +7,7 @@ namespace System.Windows.Input { /// - /// MouseGesture - Converter class for converting between a string and the Type of a MouseGesture + /// Converter class for converting between a and . /// public class MouseGestureConverter : TypeConverter { From 898e77e6f9313f192c92f048e4bc4d9dee660fa3 Mon Sep 17 00:00:00 2001 From: h3xds1nz Date: Sat, 11 Jan 2025 18:11:29 +0100 Subject: [PATCH 8/8] Update docs --- .../Input/Command/MouseActionConverter.cs | 16 ++--- .../Input/Command/MouseGestureConverter.cs | 63 +++++++++++-------- 2 files changed, 46 insertions(+), 33 deletions(-) diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseActionConverter.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseActionConverter.cs index 076adfb69e1..9b4863c11d6 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseActionConverter.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseActionConverter.cs @@ -8,12 +8,12 @@ namespace System.Windows.Input { /// - /// Converter class for converting between a and . + /// Converter class for converting between a and . /// public class MouseActionConverter : TypeConverter { /// - /// Used to check whether we can convert a into a . + /// Used to check whether we can convert a into a . /// ///ITypeDescriptorContext ///type to convert from @@ -25,11 +25,11 @@ public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceT } /// - /// Used to check whether we can convert specified value to . + /// Used to check whether we can convert specified value to . /// /// ITypeDescriptorContext /// Type to convert to - /// if conversion to is possible, otherwise. + /// if conversion to is possible, otherwise. public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { // We can convert to an InstanceDescriptor or to a string @@ -45,12 +45,12 @@ public override bool CanConvertTo(ITypeDescriptorContext context, Type destinati } /// - /// Converts of type to its represensation. + /// Converts of type to its represensation. /// /// Parser Context /// Culture Info /// MouseAction String - /// A representing the specified by . + /// A representing the specified by . public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object source) { if (source is not string mouseAction) @@ -80,13 +80,13 @@ _ when mouseActionToken.Equals("MiddleDoubleClick", StringComparison.OrdinalIgno }; /// - /// Converts a of to its represensation. + /// Converts a of to its represensation. /// /// Serialization Context /// Culture Info /// MouseAction value /// Type to Convert - /// A representing the specified by . + /// A representing the specified by . public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { ArgumentNullException.ThrowIfNull(destinationType); diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs index e8e005770f9..1a8cb27861b 100644 --- a/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs +++ b/src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Input/Command/MouseGestureConverter.cs @@ -16,24 +16,28 @@ public class MouseGestureConverter : TypeConverter /// private static readonly MouseActionConverter s_mouseActionConverter = new(); - /// - /// CanConvertFrom() - /// - ///ITypeDescriptorContext - ///type to convert from - ///true if the given type can be converted, false otherwise + /// + /// Returns whether or not this class can convert from a given . + /// + /// The for this call. + /// The being queried for support. + /// + /// if the given can be converted, otherwise. + /// public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { // We can only handle string. return sourceType == typeof(string); } - /// - ///TypeConverter method override. - /// - ///ITypeDescriptorContext - ///Type to convert to - ///true if conversion is possible + /// + /// Returns whether or not this class can convert to a given . + /// + /// The for this call. + /// The being queried for support. + /// + /// if this class can convert to , otherwise. + /// public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { // We can convert to an InstanceDescriptor or to a string. @@ -49,12 +53,15 @@ public override bool CanConvertTo(ITypeDescriptorContext context, Type destinati } /// - /// ConvertFrom + /// Converts of type to its represensation. /// - /// Parser Context - /// Culture Info - /// MouseGesture String - /// + /// This parameter is ignored during the call. + /// This parameter is ignored during the call. + /// The object to convert to a . + /// + /// A new instance of class representing the data contained in . + /// + /// Thrown in case the was not a . public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object source) { if (source is not string sourceString) @@ -76,13 +83,20 @@ public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo c } /// - /// ConvertTo() + /// Attempts to convert a object to the . /// - /// Serialization Context - /// Culture Info - /// MouseGesture value - /// Type to Convert - /// string if parameter is a MouseGesture + /// This parameter is ignored during the call. + /// This parameter is ignored during the call. + /// The object to convert to a . + /// The to convert to. + /// + /// The formatted to its representation. + /// + /// Thrown in case was . + /// + /// Thrown in case the was not a + /// or was not a . + /// public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType) { ArgumentNullException.ThrowIfNull(destinationType); @@ -99,6 +113,7 @@ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cul string mouseAction = (string)s_mouseActionConverter.ConvertTo(context, culture, mouseGesture.MouseAction, destinationType); + // This returns the converted MouseAction only if (mouseGesture.Modifiers is ModifierKeys.None) return mouseAction; @@ -109,5 +124,3 @@ public override object ConvertTo(ITypeDescriptorContext context, CultureInfo cul } } } - -