Browse Source

Display gestures in NativeMenuBar.

To do this we needed to change the `KeyGesture.ToString()` method to produce input gesture text suitable for menus. Also demonstrated in `MainWindow` how to produce different gestures/headers depending on platform.
pull/3602/head
Steven Kirk 7 years ago
parent
commit
2944099428
  1. 6
      samples/ControlCatalog/MainWindow.xaml
  2. 14
      samples/ControlCatalog/MainWindow.xaml.cs
  3. 42
      src/Avalonia.Input/KeyGesture.cs
  4. 1
      src/Avalonia.Themes.Default/NativeMenuBar.xaml
  5. 31
      tests/Avalonia.Input.UnitTests/KeyGestureTests.cs

6
samples/ControlCatalog/MainWindow.xaml

@ -14,7 +14,7 @@
<NativeMenuItem Header="File">
<NativeMenuItem.Menu>
<NativeMenu>
<NativeMenuItem Header="Open" Clicked="OnOpenClicked"/>
<NativeMenuItem Header="Open" Clicked="OnOpenClicked" Gesture="Ctrl+O"/>
<NativeMenuItemSeperator/>
<NativeMenuItem Header="Recent">
<NativeMenuItem.Menu>
@ -22,7 +22,9 @@
</NativeMenuItem.Menu>
</NativeMenuItem>
<NativeMenuItemSeperator/>
<NativeMenuItem Header="Quit Avalonia" Clicked="OnCloseClicked" Gesture="CMD+Q"/>
<NativeMenuItem Header="{x:Static local:MainWindow.MenuQuitHeader}"
Gesture="{x:Static local:MainWindow.MenuQuitGesture}"
Clicked="OnCloseClicked" />
</NativeMenu>
</NativeMenuItem.Menu>
</NativeMenuItem>

14
samples/ControlCatalog/MainWindow.xaml.cs

@ -1,13 +1,11 @@
using System;
using System.Runtime.InteropServices;
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Notifications;
using Avalonia.Controls.Primitives;
using Avalonia.Input;
using Avalonia.Markup.Xaml;
using Avalonia.Threading;
using ControlCatalog.ViewModels;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace ControlCatalog
{
@ -35,6 +33,12 @@ namespace ControlCatalog
mainMenu.AttachedToVisualTree += MenuAttached;
}
public static string MenuQuitHeader => RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? "Quit Avalonia" : "E_xit";
public static KeyGesture MenuQuitGesture => RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ?
new KeyGesture(Key.Q, KeyModifiers.Meta) :
new KeyGesture(Key.F4, KeyModifiers.Alt);
public void MenuAttached(object sender, VisualTreeAttachmentEventArgs e)
{
if (NativeMenu.GetIsNativeMenuExported(this) && sender is Menu mainMenu)

42
src/Avalonia.Input/KeyGesture.cs

@ -1,9 +1,10 @@
// Copyright (c) The Avalonia Project. All rights reserved.
// Copyright (c) The Avalonia Project. All rights reserved.
// Licensed under the MIT license. See licence.md file in the project root for full license information.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Avalonia.Input
{
@ -108,19 +109,43 @@ namespace Avalonia.Input
public override string ToString()
{
var parts = new List<string>();
var s = new StringBuilder();
foreach (var flag in Enum.GetValues(typeof(KeyModifiers)).Cast<KeyModifiers>())
static void Plus(StringBuilder s)
{
if (KeyModifiers.HasFlag(flag) && flag != KeyModifiers.None)
if (s.Length > 0)
{
parts.Add(flag.ToString());
s.Append("+");
}
}
parts.Add(Key.ToString());
if (KeyModifiers.HasFlagCustom(KeyModifiers.Control))
{
s.Append("Ctrl");
}
if (KeyModifiers.HasFlagCustom(KeyModifiers.Shift))
{
Plus(s);
s.Append("Shift");
}
if (KeyModifiers.HasFlagCustom(KeyModifiers.Alt))
{
Plus(s);
s.Append("Alt");
}
if (KeyModifiers.HasFlagCustom(KeyModifiers.Meta))
{
Plus(s);
s.Append("⌘");
}
Plus(s);
s.Append(Key);
return string.Join(" + ", parts);
return s.ToString();
}
public bool Matches(KeyEventArgs keyEvent) => ResolveNumPadOperationKey(keyEvent.Key) == Key && keyEvent.KeyModifiers == KeyModifiers;
@ -141,7 +166,8 @@ namespace Avalonia.Input
return KeyModifiers.Control;
}
if (modifier.Equals("cmd".AsSpan(), StringComparison.OrdinalIgnoreCase))
if (modifier.Equals("cmd".AsSpan(), StringComparison.OrdinalIgnoreCase) ||
modifier.Equals("⌘".AsSpan(), StringComparison.OrdinalIgnoreCase))
{
return KeyModifiers.Meta;
}

1
src/Avalonia.Themes.Default/NativeMenuBar.xaml

@ -13,6 +13,7 @@
<Menu.Styles>
<Style Selector="MenuItem">
<Setter Property="Header" Value="{Binding Header}"/>
<Setter Property="InputGestureText" Value="{Binding Gesture}"/>
<Setter Property="Items" Value="{Binding Menu.Items}"/>
<Setter Property="Command" Value="{Binding Command}"/>
<Setter Property="CommandParameter" Value="{Binding CommandParameter}"/>

31
tests/Avalonia.Input.UnitTests/KeyGestureTests.cs

@ -1,19 +1,31 @@
using System.Collections.Generic;
using System.Collections.Generic;
using Xunit;
namespace Avalonia.Input.UnitTests
{
public class KeyGestureTests
{
public static readonly IEnumerable<object[]> SampleData = new object[][]
public static readonly IEnumerable<object[]> ParseData = new object[][]
{
new object[]{"Ctrl+A", new KeyGesture(Key.A, InputModifiers.Control)},
new object[]{" \tShift\t+Alt +B", new KeyGesture(Key.B, InputModifiers.Shift | InputModifiers.Alt) },
new object[]{"Control++", new KeyGesture(Key.OemPlus, InputModifiers.Control) }
new object[]{"Ctrl+A", new KeyGesture(Key.A, KeyModifiers.Control)},
new object[]{" \tShift\t+Alt +B", new KeyGesture(Key.B, KeyModifiers.Shift | KeyModifiers.Alt) },
new object[]{"Control++", new KeyGesture(Key.OemPlus, KeyModifiers.Control) },
new object[]{ "Shift+⌘+A", new KeyGesture(Key.A, KeyModifiers.Meta | KeyModifiers.Shift) },
new object[]{ "Shift+Cmd+A", new KeyGesture(Key.A, KeyModifiers.Meta | KeyModifiers.Shift) },
};
public static readonly IEnumerable<object[]> ToStringData = new object[][]
{
new object[]{new KeyGesture(Key.A), "A"},
new object[]{new KeyGesture(Key.A, KeyModifiers.Control), "Ctrl+A"},
new object[]{new KeyGesture(Key.A, KeyModifiers.Control | KeyModifiers.Shift), "Ctrl+Shift+A"},
new object[]{new KeyGesture(Key.A, KeyModifiers.Alt | KeyModifiers.Shift), "Shift+Alt+A"},
new object[]{new KeyGesture(Key.A, KeyModifiers.Control | KeyModifiers.Alt | KeyModifiers.Shift), "Ctrl+Shift+Alt+A"},
new object[]{new KeyGesture(Key.A, KeyModifiers.Meta | KeyModifiers.Shift), "Shift+⌘+A"},
};
[Theory]
[MemberData(nameof(SampleData))]
[MemberData(nameof(ParseData))]
public void Key_Gesture_Is_Able_To_Parse_Sample_Data(string text, KeyGesture gesture)
{
Assert.Equal(gesture, KeyGesture.Parse(text));
@ -32,5 +44,12 @@ namespace Avalonia.Input.UnitTests
Key = pressedKey
}));
}
[Theory]
[MemberData(nameof(ToStringData))]
public void ToString_Produces_Correct_Results(KeyGesture gesture, string expected)
{
Assert.Equal(expected, gesture.ToString());
}
}
}

Loading…
Cancel
Save