Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Windows/macOS] Implement menu key accelerators #14740

Merged
merged 58 commits into from
Jul 3, 2023
Merged
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
5810b4c
Implement Meny Accelerators on Windows
jsuarezruiz Apr 24, 2023
c3c2301
More comments
jsuarezruiz Apr 24, 2023
6d6ce6b
Fix build errors
jsuarezruiz Apr 24, 2023
883bc19
Updated extension
jsuarezruiz Apr 24, 2023
288e4ea
More samples
jsuarezruiz Apr 24, 2023
d637c24
Merge branch 'main' into fix-5211
jsuarezruiz Apr 25, 2023
a96555d
Merge branch 'main' into fix-5211
rachelkang Apr 25, 2023
d65e20e
Merge branch 'main' into fix-5211
jsuarezruiz Apr 27, 2023
e138b2a
Small code refactoring
jsuarezruiz Apr 27, 2023
041fe62
Merge branch 'main' into fix-5211
jsuarezruiz Apr 28, 2023
2dbfe81
Merge branch 'main' into fix-5211
jsuarezruiz May 2, 2023
3796218
Updated implementation
jsuarezruiz May 2, 2023
625098a
Tweak interface to reflect single key only usage
rachelkang May 4, 2023
f8d3133
Add Mac implementation
rachelkang May 4, 2023
49f5f1f
Auto-format source code
May 4, 2023
af99754
Add samples from XAML and with different key combos
rachelkang May 5, 2023
dd33b18
Merge branch 'main' into fix-5211
jsuarezruiz May 11, 2023
1d5ba90
Small tweaks based on feedback
rachelkang May 26, 2023
a3b8e09
Update src/Core/src/Platform/Windows/KeyboardAcceleratorExtensions.cs
jsuarezruiz May 31, 2023
e01563f
Update src/Core/src/PublicAPI/net-android/PublicAPI.Unshipped.txt
jsuarezruiz May 31, 2023
25324d2
Update src/Core/src/PublicAPI/net-tizen/PublicAPI.Unshipped.txt
jsuarezruiz May 31, 2023
14aadf2
Update src/Core/src/PublicAPI/net/PublicAPI.Unshipped.txt
jsuarezruiz May 31, 2023
9c3034b
Update src/Core/src/PublicAPI/netstandard2.0/PublicAPI.Unshipped.txt
jsuarezruiz May 31, 2023
d2490d8
Update src/Core/src/PublicAPI/netstandard/PublicAPI.Unshipped.txt
jsuarezruiz May 31, 2023
e4810c7
Update src/Core/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt
jsuarezruiz May 31, 2023
0071004
Update src/Core/src/PublicAPI/net-ios/PublicAPI.Unshipped.txt
jsuarezruiz May 31, 2023
bfadcb3
Update src/Core/src/PublicAPI/net-maccatalyst/PublicAPI.Unshipped.txt
jsuarezruiz May 31, 2023
8905ee3
Update src/Core/src/Core/IMenuElement.cs
jsuarezruiz May 31, 2023
717f599
Add if/defs for netstandard2.1 DIM support
rachelkang Jun 5, 2023
2c3145d
Merge branch 'main' into fix-5211
rachelkang Jun 5, 2023
e6e6b79
Allow to use numbers as key on Windows
jsuarezruiz Jun 7, 2023
3e44575
Tweak ifdefs
rachelkang Jun 8, 2023
28e3090
Tweaks based on my understanding of feedback
rachelkang Jun 12, 2023
f04031d
Remove irrelevant sandbox changes
rachelkang Jun 12, 2023
3008fa1
Undo more sandbox changes
rachelkang Jun 12, 2023
e1552ce
Merge branch 'main' into fix-5211
rachelkang Jun 12, 2023
d3001bb
Merge branch 'main' into fix-5211
jsuarezruiz Jun 14, 2023
e03e584
Added support to multiple accelerators on Windows
jsuarezruiz Jun 14, 2023
995398c
Merge branch 'main' into fix-5211
jsuarezruiz Jun 14, 2023
3f7fbde
Merge branch 'main' into fix-5211
jsuarezruiz Jun 15, 2023
179d623
Updates based on feedback
rachelkang Jun 15, 2023
43a1f6d
More updates based on feedback
rachelkang Jun 15, 2023
93a3bd2
Small refactoring (from for to foreach)
jsuarezruiz Jun 16, 2023
3df0456
More refactoring
jsuarezruiz Jun 16, 2023
b13e77c
Merge branch 'main' into fix-5211
rachelkang Jun 19, 2023
8f2ed58
Update based on feedback
rachelkang Jun 19, 2023
dcae302
Merge branch 'main' into fix-5211
jsuarezruiz Jun 22, 2023
51f3161
Fix build errors
jsuarezruiz Jun 22, 2023
e3d0802
Add some API doc comments
rachelkang Jun 22, 2023
3fd2187
Merge branch 'main' into fix-5211
rachelkang Jun 22, 2023
4f73a8f
Fix broken tests
jsuarezruiz Jun 23, 2023
daccc5e
Added more docstrings in the public APIs
jsuarezruiz Jun 27, 2023
4eea4f6
Fix typo in tests and add key only case
rachelkang Jun 27, 2023
7efafdc
Add more doc comments
rachelkang Jun 27, 2023
5e35b7f
Update src/Core/src/Handlers/MenuFlyoutItem/MenuFlyoutItemHandler.Win…
rachelkang Jun 27, 2023
cfc14fb
Fix and update api docs some more
rachelkang Jun 27, 2023
ea70d71
Changes based on feedback
jsuarezruiz Jun 28, 2023
9f4f905
Avoid to use Linq in Accelerator class
jsuarezruiz Jul 3, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 0 additions & 25 deletions src/Controls/docs/Microsoft.Maui.Controls/Accelerator.xml
Original file line number Diff line number Diff line change
Expand Up @@ -120,31 +120,6 @@
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="Modifiers">
<MemberSignature Language="C#" Value="public System.Collections.Generic.IEnumerable&lt;string&gt; Modifiers { get; set; }" />
<MemberSignature Language="ILAsm" Value=".property instance class System.Collections.Generic.IEnumerable`1&lt;string&gt; Modifiers" />
<MemberSignature Language="DocId" Value="P:Microsoft.Maui.Controls.Accelerator.Modifiers" />
<MemberSignature Language="F#" Value="member this.Modifiers : seq&lt;string&gt; with get, set" Usage="Microsoft.Maui.Controls.Accelerator.Modifiers" />
<MemberType>Property</MemberType>
<AssemblyInfo>
<AssemblyVersion>0.0.0.0</AssemblyVersion>
<AssemblyVersion>2.0.0.0</AssemblyVersion>
<AssemblyName>Microsoft.Maui.Controls.Core</AssemblyName>
</AssemblyInfo>
<Attributes>
<Attribute>
<AttributeName>System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)</AttributeName>
</Attribute>
</Attributes>
<ReturnValue>
<ReturnType>System.Collections.Generic.IEnumerable&lt;System.String&gt;</ReturnType>
</ReturnValue>
<Docs>
<summary>For internal use only.</summary>
<value>To be added.</value>
<remarks>To be added.</remarks>
</Docs>
</Member>
<Member MemberName="op_Implicit">
<MemberSignature Language="C#" Value="public static implicit operator Microsoft.Maui.Controls.Accelerator (string accelerator);" />
<MemberSignature Language="ILAsm" Value=".method public static hidebysig specialname class Microsoft.Maui.Controls.Accelerator op_Implicit(string accelerator) cil managed" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@
<Button Text="Increment by 1 (or right-click me)" Clicked="OnIncrementByOneClicked" FontSize="30" BackgroundColor="DarkGray">
<FlyoutBase.ContextFlyout>
<MenuFlyout>
<MenuFlyoutItem Text="Increment by 10" Clicked="OnIncrementMenuItemClicked" CommandParameter="10"></MenuFlyoutItem>
<MenuFlyoutItem Text="Increment by 20" Clicked="OnIncrementMenuItemClicked" CommandParameter="20"></MenuFlyoutItem>
<MenuFlyoutItem Text="Increment by 30 (disabled)" Clicked="OnIncrementMenuItemClicked" CommandParameter="30" x:Name="bbb"></MenuFlyoutItem>
<MenuFlyoutItem Text="Increment by 40 (dynamic enabled/disabled)" Command="{Binding DynamicEnabledCommand}" CommandParameter="40"></MenuFlyoutItem>
<MenuFlyoutItem x:Name="Increment10MenuFlyoutItem" Text="Increment by 10" Clicked="OnIncrementMenuItemClicked" CommandParameter="10" />
<MenuFlyoutItem x:Name="Increment20MenuFlyoutItem" Text="Increment by 20" Clicked="OnIncrementMenuItemClicked" CommandParameter="20" />
<MenuFlyoutItem Text="Increment by 30 (disabled)" Clicked="OnIncrementMenuItemClicked" CommandParameter="30" x:Name="bbb" />
<MenuFlyoutItem Text="Increment by 40 (dynamic enabled/disabled)" Command="{Binding DynamicEnabledCommand}" CommandParameter="40" />
<MenuFlyoutSubItem Text="More options">
<MenuFlyoutItem Text="Increment by 1,000!" Clicked="OnIncrementMenuItemClicked" CommandParameter="1000"></MenuFlyoutItem>
<MenuFlyoutItem Text="Increment by 1,000,000!" Clicked="OnIncrementMenuItemClicked" CommandParameter="1000000"></MenuFlyoutItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ await DisplayAlert(
bbb.IsEnabled = false;

ContextMenuWebView.HandlerChanged += OnWebViewHandlerChanged;

mattleibow marked this conversation as resolved.
Show resolved Hide resolved
MenuItem.SetAccelerator(Increment10MenuFlyoutItem, Accelerator.FromString("alt+ctrl+a"));
MenuItem.SetAccelerator(Increment20MenuFlyoutItem, Accelerator.FromString("ctrl+b"));
MenuItem.SetAccelerator(bbb, Accelerator.FromString("c"));
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Maui.Controls;
using Microsoft.Maui.Graphics;

namespace Maui.Controls.Sample.Pages
{
Expand All @@ -13,6 +10,8 @@ public partial class MenuBarPage
public MenuBarPage()
{
InitializeComponent();

MenuItem.SetAccelerator(CustomFileMenuFlyoutItem, Accelerator.FromString("ctrl+shift+f"));
}

void ItemClicked(object sender, EventArgs e)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
xmlns:views="clr-namespace:Maui.Controls.Sample.Pages.Base">
<views:BasePage.MenuBarItems>
<MenuBarItem Text="Before File">
<MenuFlyoutItem Clicked="ItemClicked" Text="Before File Action"></MenuFlyoutItem>
<MenuFlyoutItem Clicked="ItemClicked" Text="Before File Action" Accelerator="b" />
<MenuFlyoutItem Text="Cool item 1"></MenuFlyoutItem>
<MenuFlyoutSeparator />
<MenuFlyoutItem Text="Cool item 2"></MenuFlyoutItem>
</MenuBarItem>
<MenuBarItem Text="File">
<MenuFlyoutItem Clicked="ItemClicked" Text="Custom File">
<MenuFlyoutItem x:Name="CustomFileMenuFlyoutItem" Clicked="ItemClicked" Text="Custom File" >
<MenuFlyoutItem.IconImageSource>
<FontImageSource
FontAutoScalingEnabled="False"
Expand All @@ -23,17 +23,17 @@
</MenuFlyoutItem>
</MenuBarItem>
<MenuBarItem Text="Custom Menu">
<MenuFlyoutItem Clicked="ItemClicked" Text="Item 1"></MenuFlyoutItem>
<MenuFlyoutItem Clicked="ItemClicked" Text="Item 1" Accelerator="ctrl+5" />
<MenuFlyoutSubItem Clicked="ItemClicked" Text="Sub Menu 1">
<MenuFlyoutItem IconImageSource="mic.png" Clicked="ItemClicked" Text="Flyout item 1"></MenuFlyoutItem>
<MenuFlyoutItem IconImageSource="coffee.png" Clicked="ItemClicked" Text="Flyout item 2"></MenuFlyoutItem>
<MenuFlyoutItem IconImageSource="mic.png" Clicked="ItemClicked" Text="Flyout item 1" Accelerator="Shift+M" />
<MenuFlyoutItem IconImageSource="coffee.png" Clicked="ItemClicked" Text="Flyout item 2" Accelerator="ALT+C" />
</MenuFlyoutSubItem>
</MenuBarItem>
</views:BasePage.MenuBarItems>
<views:BasePage.Content>
<VerticalStackLayout Margin="12">
<Label x:Name="menuLabel" Text="You clicked on Menu Item:"></Label>
<Button Text="Toggle Menu Bar Item" Clicked="ToggleMenuBarItem"></Button>
<Label x:Name="menuLabel" Text="You clicked on Menu Item:" />
<Button Text="Toggle Menu Bar Item" Clicked="ToggleMenuBarItem" />
</VerticalStackLayout>
</views:BasePage.Content>
</views:BasePage>
66 changes: 43 additions & 23 deletions src/Controls/src/Core/Accelerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,61 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;

namespace Microsoft.Maui.Controls
{
/// <include file="../../docs/Microsoft.Maui.Controls/Accelerator.xml" path="Type[@FullName='Microsoft.Maui.Controls.Accelerator']/Docs/*" />
[System.ComponentModel.TypeConverter(typeof(AcceleratorTypeConverter))]
public class Accelerator
public class Accelerator : IAccelerator
mattleibow marked this conversation as resolved.
Show resolved Hide resolved
{
const char Separator = '+';
string _text;
const string Separator = "+";
readonly string _text;

internal Accelerator(string text)
internal Accelerator(string text, List<string> modifiers, string key)
jsuarezruiz marked this conversation as resolved.
Show resolved Hide resolved
{
if (string.IsNullOrEmpty(text))
throw new ArgumentNullException(nameof(text));

_text = text;
Key = key;
Modifiers = modifiers;
}

/// <include file="../../docs/Microsoft.Maui.Controls/Accelerator.xml" path="//Member[@MemberName='Modifiers']/Docs/*" />
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<string> Modifiers { get; set; }
/// <summary>
/// Gets the modifiers for the accelerator.
/// </summary>
public IEnumerable<string> Modifiers { get; }

IReadOnlyList<string> IAccelerator.Modifiers => Modifiers?.ToList();
jsuarezruiz marked this conversation as resolved.
Show resolved Hide resolved

/// <include file="../../docs/Microsoft.Maui.Controls/Accelerator.xml" path="//Member[@MemberName='Keys']/Docs/*" />
[EditorBrowsable(EditorBrowsableState.Never)]
public IEnumerable<string> Keys { get; set; }
[Obsolete("Use Key instead.")]
public IEnumerable<string> Keys
{
get => Key is null ? null : new[] { Key };
mattleibow marked this conversation as resolved.
Show resolved Hide resolved
}

/// <summary>
/// Gets the key for the accelerator.
/// </summary>
public string Key { get; }

/// <include file="../../docs/Microsoft.Maui.Controls/Accelerator.xml" path="//Member[@MemberName='FromString']/Docs/*" />
public static Accelerator FromString(string text)
{
var accelarat = new Accelerator(text);
if (string.IsNullOrEmpty(text))
throw new ArgumentNullException(nameof(text));

var str = text;
var modifiers = new List<string>();
var key = string.Empty;

var acceleratorParts = text.Split(Separator);
var acceleratorParts = text.Split(new[] { Separator }, StringSplitOptions.None);

if (acceleratorParts.Length > 1)
{
var modifiers = new List<string>();
for (int i = 0; i < acceleratorParts.Length; i++)
{
var modifierMask = acceleratorParts[i];
Expand All @@ -51,27 +71,27 @@ public static Accelerator FromString(string text)
case "win":
modifiers.Add(modiferMaskLower);
#if NETSTANDARD2_0
text = text.Replace(modifierMask, "");
text = text.Replace(modifierMask, string.Empty);
#else
text = text.Replace(modifierMask, "", StringComparison.Ordinal);
text = text.Replace(modifierMask, string.Empty, StringComparison.Ordinal);
#endif
break;
}
}
accelarat.Modifiers = modifiers;

}

if (text != Separator.ToString())
{
var keys = text.Split(new char[] { Separator }, StringSplitOptions.RemoveEmptyEntries);
accelarat.Keys = keys;
}
else
if (!string.Equals(text, Separator, StringComparison.Ordinal))
{
accelarat.Keys = new[] { text };
#if NETSTANDARD2_0
text = text.Replace(Separator, string.Empty);
#else
text = text.Replace(Separator, string.Empty, StringComparison.Ordinal);
#endif
}
return accelarat;

key = text;

return new Accelerator(str, modifiers, key);
}

/// <include file="../../docs/Microsoft.Maui.Controls/Accelerator.xml" path="//Member[@MemberName='ToString']/Docs/*" />
Expand Down
5 changes: 4 additions & 1 deletion src/Controls/src/Core/Menu/MenuItem.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#nullable disable
#nullable disable
using System;
using System.Collections.Generic;
using System.ComponentModel;
Expand Down Expand Up @@ -145,6 +145,9 @@ static object CoerceIsEnabledProperty(BindableObject bindable, object value)
return false;
}

IReadOnlyList<IAccelerator> IMenuElement.Accelerators =>
GetAccelerator(this) is Accelerator acc ? new[] { acc } : null;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment, should we one returning null? Or an empty list of IAccelerator. Why the need of a IReadOnlyList? Are users going to access the by index?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The order matters I think because you want the accelerators to be in a specific order. The null is not my favorite but some people like it - not sure it matters. We can always not-null it later, but making it null later is breaking.


IImageSource IImageSourcePart.Source => this.IconImageSource;

bool IImageSourcePart.IsAnimationPlaying => false;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#nullable enable
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Modifiers.set -> void
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Keys.set -> void
~Microsoft.Maui.Controls.Accelerator.Key.get -> string
*REMOVED*override Microsoft.Maui.Controls.RefreshView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
Microsoft.Maui.Controls.Border.~Border() -> void
Microsoft.Maui.Controls.IWindowCreator
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#nullable enable
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Modifiers.set -> void
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Keys.set -> void
~Microsoft.Maui.Controls.Accelerator.Key.get -> string
*REMOVED*override Microsoft.Maui.Controls.RefreshView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
Microsoft.Maui.Controls.Border.~Border() -> void
Microsoft.Maui.Controls.IWindowCreator
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,8 +97,8 @@
~Microsoft.Maui.Controls.AbsoluteLayout.SetLayoutFlags(Microsoft.Maui.IView view, Microsoft.Maui.Layouts.AbsoluteLayoutFlags flags) -> void
~Microsoft.Maui.Controls.Accelerator.Keys.get -> System.Collections.Generic.IEnumerable<string>
~Microsoft.Maui.Controls.Accelerator.Keys.set -> void
~Microsoft.Maui.Controls.Accelerator.Modifiers.get -> System.Collections.Generic.IEnumerable<string>
rachelkang marked this conversation as resolved.
Show resolved Hide resolved
~Microsoft.Maui.Controls.Accelerator.Modifiers.set -> void
~Microsoft.Maui.Controls.Accelerator.Modifiers.get -> System.Collections.Generic.IEnumerable<string>
~Microsoft.Maui.Controls.ActivityIndicator.Color.get -> Microsoft.Maui.Graphics.Color
~Microsoft.Maui.Controls.ActivityIndicator.Color.set -> void
~Microsoft.Maui.Controls.ActivityIndicator.On<T>() -> Microsoft.Maui.Controls.IPlatformElementConfiguration<T, Microsoft.Maui.Controls.ActivityIndicator>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#nullable enable
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Modifiers.set -> void
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Keys.set -> void
~Microsoft.Maui.Controls.Accelerator.Key.get -> string
*REMOVED*override Microsoft.Maui.Controls.RefreshView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
Microsoft.Maui.Controls.Border.~Border() -> void
Microsoft.Maui.Controls.IWindowCreator
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#nullable enable
#nullable enable
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Modifiers.set -> void
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Keys.set -> void
~Microsoft.Maui.Controls.Accelerator.Key.get -> string
Microsoft.Maui.Controls.Border.~Border() -> void
Microsoft.Maui.Controls.IWindowCreator
Microsoft.Maui.Controls.IWindowCreator.CreateWindow(Microsoft.Maui.Controls.Application! app, Microsoft.Maui.IActivationState? activationState) -> Microsoft.Maui.Controls.Window!
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#nullable enable
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Modifiers.set -> void
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Keys.set -> void
~Microsoft.Maui.Controls.Accelerator.Key.get -> string
*REMOVED*override Microsoft.Maui.Controls.RefreshView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
Microsoft.Maui.Controls.Border.~Border() -> void
Microsoft.Maui.Controls.IWindowCreator
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#nullable enable
#nullable enable
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Modifiers.set -> void
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Keys.set -> void
~Microsoft.Maui.Controls.Accelerator.Key.get -> string
*REMOVED*override Microsoft.Maui.Controls.RefreshView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
Microsoft.Maui.Controls.Border.~Border() -> void
Microsoft.Maui.Controls.IWindowCreator
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
#nullable enable
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Modifiers.set -> void
*REMOVED*~Microsoft.Maui.Controls.Accelerator.Keys.set -> void
~Microsoft.Maui.Controls.Accelerator.Key.get -> string
*REMOVED*override Microsoft.Maui.Controls.RefreshView.MeasureOverride(double widthConstraint, double heightConstraint) -> Microsoft.Maui.Graphics.Size
Microsoft.Maui.Controls.Border.~Border() -> void
Microsoft.Maui.Controls.IWindowCreator
Expand Down
27 changes: 18 additions & 9 deletions src/Controls/tests/Core.UnitTests/AcceleratorUnitTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

namespace Microsoft.Maui.Controls.Core.UnitTests
{

public class AcceleratorUnitTests : BaseTestFixture
{

Expand All @@ -22,19 +21,27 @@ public void AcceleratorThrowsOnNull()
Assert.Throws<ArgumentNullException>(() => Accelerator.FromString(null));
}

[Fact]
public void AcceleratorFromString()
[Theory]
[InlineData("ctrl+A")]
[InlineData("cmd+A")]
[InlineData("ctrl+1")]
[InlineData("cmd+1")]
[InlineData("ctrl+alt+A")]
[InlineData("cmd+alt+A")]
public void AcceleratorFromString(string shourtCutKeyBinding)
{
string shourtCutKeyBinding = "ctrl+A";
var accelerator = Accelerator.FromString(shourtCutKeyBinding);

Assert.Equal(shourtCutKeyBinding, accelerator.ToString());
}

[Fact]
public void AcceleratorFromOnlyLetter()
[Theory]
[InlineData("A")]
[InlineData("B")]
[InlineData("1")]
[InlineData("2")]
public void AcceleratorFromOnlyLetter(string shourtCutKeyBinding)
{
string shourtCutKeyBinding = "A";
var accelerator = Accelerator.FromString(shourtCutKeyBinding);

Assert.Single(accelerator.Keys);
Expand All @@ -45,16 +52,18 @@ public void AcceleratorFromOnlyLetter()
public void AcceleratorFromLetterAndModifier(TestShortcut shourtcut)
{
string modifier = shourtcut.Modifier;
Assert.NotNull(modifier);

string key = shourtcut.Key;
var accelerator = Accelerator.FromString(shourtcut.ToString());
Assert.NotNull(key);

var accelerator = Accelerator.FromString(shourtcut.ToString());
Assert.Single(accelerator.Keys);
Assert.Single(accelerator.Modifiers);
Assert.Equal(accelerator.Keys.ElementAt(0), shourtcut.Key);
Assert.Equal(accelerator.Modifiers.ElementAt(0), shourtcut.Modifier);
}


[Fact]
public void AcceleratorFromLetterAnd2Modifier()
{
Expand Down
20 changes: 20 additions & 0 deletions src/Core/src/Core/IAccelerator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
using System.Collections.Generic;

namespace Microsoft.Maui
{
/// <summary>
/// Represents a shortcut key for a <see cref="T:Microsoft.Maui.Controls.MenuItem" />.
/// </summary>
public interface IAccelerator
{
/// <summary>
/// Specifies the virtual key used to modify another keypress.
/// </summary>
public IReadOnlyList<string> Modifiers { get; }

/// <summary>
/// Specifies the values for the virtual key.
/// </summary>
public string Key { get; }
}
}
Loading