diff --git a/demo/Ursa.Demo/Models/MenuKeys.cs b/demo/Ursa.Demo/Models/MenuKeys.cs index 1d8954e..8faf23a 100644 --- a/demo/Ursa.Demo/Models/MenuKeys.cs +++ b/demo/Ursa.Demo/Models/MenuKeys.cs @@ -8,9 +8,11 @@ public static class MenuKeys public const string MenuKeyDivider = "Divider"; public const string MenuKeyDualBadge = "DualBadge"; public const string MenuKeyIpBox = "IPv4Box"; + public const string MenuKeyKeyGestureInput = "KeyGestureInput"; public const string MenuKeyLoading = "Loading"; public const string MenuKeyNavigation = "Navigation"; public const string MenuKeyPagination = "Pagination"; public const string MenuKeyTagInput = "TagInput"; public const string MenuKeyTimeline = "Timeline"; + } \ No newline at end of file diff --git a/demo/Ursa.Demo/Pages/KeyGestureInputDemo.axaml b/demo/Ursa.Demo/Pages/KeyGestureInputDemo.axaml new file mode 100644 index 0000000..406c353 --- /dev/null +++ b/demo/Ursa.Demo/Pages/KeyGestureInputDemo.axaml @@ -0,0 +1,20 @@ + + + + + + + + \ No newline at end of file diff --git a/demo/Ursa.Demo/Pages/KeyGestureInputDemo.axaml.cs b/demo/Ursa.Demo/Pages/KeyGestureInputDemo.axaml.cs new file mode 100644 index 0000000..f213756 --- /dev/null +++ b/demo/Ursa.Demo/Pages/KeyGestureInputDemo.axaml.cs @@ -0,0 +1,18 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace Ursa.Demo.Pages; + +public partial class KeyGestureInputDemo : UserControl +{ + public KeyGestureInputDemo() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } +} \ No newline at end of file diff --git a/demo/Ursa.Demo/Ursa.Demo.csproj b/demo/Ursa.Demo/Ursa.Demo.csproj index 4f0188d..d11b6e7 100644 --- a/demo/Ursa.Demo/Ursa.Demo.csproj +++ b/demo/Ursa.Demo/Ursa.Demo.csproj @@ -7,23 +7,23 @@ - + - + - + - - - + + + - - + + diff --git a/demo/Ursa.Demo/ViewModels/KeyGestureInputDemoViewModel.cs b/demo/Ursa.Demo/ViewModels/KeyGestureInputDemoViewModel.cs new file mode 100644 index 0000000..b69f20c --- /dev/null +++ b/demo/Ursa.Demo/ViewModels/KeyGestureInputDemoViewModel.cs @@ -0,0 +1,13 @@ +using System.Collections.Generic; +using Avalonia.Input; +using CommunityToolkit.Mvvm.ComponentModel; + +namespace Ursa.Demo.ViewModels; + +public class KeyGestureInputDemoViewModel: ObservableObject +{ + public List AcceptableKeys { get; set; } = new List() + { + Key.A, Key.B, Key.C, + }; +} \ No newline at end of file diff --git a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs index 54109ae..8487910 100644 --- a/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs +++ b/demo/Ursa.Demo/ViewModels/MainViewViewModel.cs @@ -30,6 +30,7 @@ public class MainViewViewModel : ViewModelBase MenuKeys.MenuKeyDivider => new DividerDemoViewModel(), MenuKeys.MenuKeyDualBadge => new DualBadgeDemoViewModel(), MenuKeys.MenuKeyIpBox => new IPv4BoxDemoViewModel(), + MenuKeys.MenuKeyKeyGestureInput => new KeyGestureInputDemoViewModel(), MenuKeys.MenuKeyLoading => new LoadingDemoViewModel(), MenuKeys.MenuKeyNavigation => new NavigationMenuDemoViewModel(), MenuKeys.MenuKeyPagination => new PaginationDemoViewModel(), diff --git a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs index 011375b..f55365f 100644 --- a/demo/Ursa.Demo/ViewModels/MenuViewModel.cs +++ b/demo/Ursa.Demo/ViewModels/MenuViewModel.cs @@ -17,6 +17,7 @@ public class MenuViewModel: ViewModelBase new() { MenuHeader = "Divider", Key = MenuKeys.MenuKeyDivider }, new() { MenuHeader = "DualBadge", Key = MenuKeys.MenuKeyDualBadge }, new() { MenuHeader = "IPv4Box", Key = MenuKeys.MenuKeyIpBox }, + new() { MenuHeader = "KeyGestureInput", Key = MenuKeys.MenuKeyKeyGestureInput }, new() { MenuHeader = "Loading", Key = MenuKeys.MenuKeyLoading }, new() { MenuHeader = "Navigation", Key = MenuKeys.MenuKeyNavigation }, new() { MenuHeader = "Pagination", Key = MenuKeys.MenuKeyPagination }, diff --git a/src/Ursa.Themes.Semi/Controls/KeyGestureInput.axaml b/src/Ursa.Themes.Semi/Controls/KeyGestureInput.axaml new file mode 100644 index 0000000..2bbbd31 --- /dev/null +++ b/src/Ursa.Themes.Semi/Controls/KeyGestureInput.axaml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Ursa.Themes.Semi/Controls/_index.axaml b/src/Ursa.Themes.Semi/Controls/_index.axaml index dee9b3c..2038cd0 100644 --- a/src/Ursa.Themes.Semi/Controls/_index.axaml +++ b/src/Ursa.Themes.Semi/Controls/_index.axaml @@ -7,6 +7,7 @@ + diff --git a/src/Ursa.Themes.Semi/Themes/Dark/KeyGestureInput.axaml b/src/Ursa.Themes.Semi/Themes/Dark/KeyGestureInput.axaml new file mode 100644 index 0000000..ed7c331 --- /dev/null +++ b/src/Ursa.Themes.Semi/Themes/Dark/KeyGestureInput.axaml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/Ursa.Themes.Semi/Themes/Dark/_index.axaml b/src/Ursa.Themes.Semi/Themes/Dark/_index.axaml index aa85239..c2ff413 100644 --- a/src/Ursa.Themes.Semi/Themes/Dark/_index.axaml +++ b/src/Ursa.Themes.Semi/Themes/Dark/_index.axaml @@ -7,6 +7,7 @@ + diff --git a/src/Ursa.Themes.Semi/Themes/Light/KeyGestureInput.axaml b/src/Ursa.Themes.Semi/Themes/Light/KeyGestureInput.axaml new file mode 100644 index 0000000..490e1a4 --- /dev/null +++ b/src/Ursa.Themes.Semi/Themes/Light/KeyGestureInput.axaml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/src/Ursa.Themes.Semi/Themes/Light/_index.axaml b/src/Ursa.Themes.Semi/Themes/Light/_index.axaml index aa85239..c2ff413 100644 --- a/src/Ursa.Themes.Semi/Themes/Light/_index.axaml +++ b/src/Ursa.Themes.Semi/Themes/Light/_index.axaml @@ -7,6 +7,7 @@ + diff --git a/src/Ursa.Themes.Semi/Themes/Shared/KeyGestureInput.axaml b/src/Ursa.Themes.Semi/Themes/Shared/KeyGestureInput.axaml new file mode 100644 index 0000000..19752fa --- /dev/null +++ b/src/Ursa.Themes.Semi/Themes/Shared/KeyGestureInput.axaml @@ -0,0 +1,7 @@ + + + 80 + 32 + 3 + 1 + diff --git a/src/Ursa.Themes.Semi/Themes/Shared/_index.axaml b/src/Ursa.Themes.Semi/Themes/Shared/_index.axaml index 7bf0b4d..3d93ea5 100644 --- a/src/Ursa.Themes.Semi/Themes/Shared/_index.axaml +++ b/src/Ursa.Themes.Semi/Themes/Shared/_index.axaml @@ -7,6 +7,7 @@ + diff --git a/src/Ursa/Controls/KeyGestureInput.cs b/src/Ursa/Controls/KeyGestureInput.cs new file mode 100644 index 0000000..5c4e535 --- /dev/null +++ b/src/Ursa/Controls/KeyGestureInput.cs @@ -0,0 +1,97 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Controls.Converters; +using Avalonia.Controls.Primitives; +using Avalonia.Input; +using Avalonia.Layout; + +namespace Ursa.Controls; + +public class KeyGestureInput: TemplatedControl +{ + static KeyGestureInput() + { + InputElement.FocusableProperty.OverrideDefaultValue(true); + } + + public static readonly StyledProperty GestureProperty = AvaloniaProperty.Register( + nameof(Gesture)); + + public KeyGesture Gesture + { + get => GetValue(GestureProperty); + set => SetValue(GestureProperty, value); + } + + public static readonly StyledProperty?> AcceptableKeysProperty = AvaloniaProperty.Register?>( + nameof(AcceptableKeys)); + + public IList? AcceptableKeys + { + get => GetValue(AcceptableKeysProperty); + set => SetValue(AcceptableKeysProperty, value); + } + + public static readonly StyledProperty ConsiderKeyModifiersProperty = AvaloniaProperty.Register( + nameof(ConsiderKeyModifiers), true); + + public bool ConsiderKeyModifiers + { + get => GetValue(ConsiderKeyModifiersProperty); + set => SetValue(ConsiderKeyModifiersProperty, value); + } + + public static readonly StyledProperty HorizontalContentAlignmentProperty = + ContentControl.HorizontalContentAlignmentProperty.AddOwner( + new StyledPropertyMetadata(HorizontalAlignment.Center)); + + public HorizontalAlignment HorizontalContentAlignment + { + get => GetValue(HorizontalContentAlignmentProperty); + set => SetValue(HorizontalContentAlignmentProperty, value); + } + + public static readonly StyledProperty VerticalContentAlignmentProperty = + ContentControl.VerticalContentAlignmentProperty.AddOwner( + new StyledPropertyMetadata(VerticalAlignment.Center)); + + public VerticalAlignment VerticalContentAlignment + { + get => GetValue(VerticalContentAlignmentProperty); + set => SetValue(VerticalContentAlignmentProperty, value); + } + + + protected override void OnKeyDown(KeyEventArgs e) + { + // base.OnKeyDown(e); + if (AcceptableKeys is not null && !AcceptableKeys.Contains(e.Key)) + { + return; + } + + if (!ConsiderKeyModifiers) + { + if(e.Key is Key.LeftCtrl or Key.RightCtrl or Key.LeftAlt or Key.RightAlt or Key.LeftShift or Key.RightShift or Key.LWin or Key.RWin) + { + return; + } + Gesture = new KeyGesture(e.Key); + } + KeyGesture gesture; + switch (e.KeyModifiers) + { + case KeyModifiers.Control when e.Key is Key.LeftCtrl or Key.RightCtrl: + case KeyModifiers.Alt when e.Key is Key.LeftAlt or Key.RightAlt: + case KeyModifiers.Shift when e.Key is Key.LeftShift or Key.RightShift: + case KeyModifiers.Meta when e.Key is Key.LWin or Key.RWin: + gesture = new KeyGesture(e.Key); + break; + default: + gesture = new KeyGesture(e.Key, e.KeyModifiers); + break; + } + Gesture = gesture; + e.Handled = true; + } +} \ No newline at end of file