ShellViewModel.cs
1 // Copyright (c) Microsoft Corporation 2 // The Microsoft Corporation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System; 6 using System.Collections.Generic; 7 using System.IO; 8 using System.Linq; 9 using System.Threading.Tasks; 10 using System.Windows.Input; 11 12 using Microsoft.PowerToys.Settings.UI.Helpers; 13 using Microsoft.PowerToys.Settings.UI.Library; 14 using Microsoft.PowerToys.Settings.UI.Library.Helpers; 15 using Microsoft.PowerToys.Settings.UI.Library.Interfaces; 16 using Microsoft.PowerToys.Settings.UI.Services; 17 using Microsoft.UI.Xaml.Controls; 18 using Microsoft.UI.Xaml.Input; 19 using Microsoft.UI.Xaml.Navigation; 20 using Windows.System; 21 22 namespace Microsoft.PowerToys.Settings.UI.ViewModels 23 { 24 public partial class ShellViewModel : Observable 25 { 26 private readonly KeyboardAccelerator altLeftKeyboardAccelerator = BuildKeyboardAccelerator(VirtualKey.Left, VirtualKeyModifiers.Menu); 27 28 private readonly KeyboardAccelerator backKeyboardAccelerator = BuildKeyboardAccelerator(VirtualKey.GoBack); 29 30 private bool isBackEnabled; 31 private bool showCloseMenu; 32 private IList<KeyboardAccelerator> keyboardAccelerators; 33 private NavigationView navigationView; 34 private NavigationViewItem selected; 35 private NavigationViewItem expanding; 36 private ICommand loadedCommand; 37 private ICommand itemInvokedCommand; 38 private NavigationViewItem[] _fullListOfNavViewItems; 39 private NavigationViewItem[] _moduleNavViewItems; 40 private GeneralSettings _generalSettingsConfig; 41 42 public bool IsBackEnabled 43 { 44 get => isBackEnabled; 45 set => Set(ref isBackEnabled, value); 46 } 47 48 public bool ShowCloseMenu 49 { 50 get => showCloseMenu; 51 set => Set(ref showCloseMenu, value); 52 } 53 54 public NavigationViewItem Selected 55 { 56 get => selected; 57 set => Set(ref selected, value); 58 } 59 60 public NavigationViewItem Expanding 61 { 62 get { return expanding; } 63 set { Set(ref expanding, value); } 64 } 65 66 public NavigationViewItem[] NavItems 67 { 68 get { return _moduleNavViewItems; } 69 } 70 71 public ICommand LoadedCommand => loadedCommand ?? (loadedCommand = new RelayCommand(OnLoaded)); 72 73 public ICommand ItemInvokedCommand => itemInvokedCommand ?? (itemInvokedCommand = new RelayCommand<NavigationViewItemInvokedEventArgs>(OnItemInvoked)); 74 75 public ShellViewModel(ISettingsRepository<GeneralSettings> settingsRepository) 76 { 77 _generalSettingsConfig = settingsRepository.SettingsConfig; 78 ShowCloseMenu = !_generalSettingsConfig.ShowSysTrayIcon; 79 } 80 81 public void Initialize(Frame frame, NavigationView navigationView, IList<KeyboardAccelerator> keyboardAccelerators) 82 { 83 this.navigationView = navigationView; 84 this.keyboardAccelerators = keyboardAccelerators; 85 NavigationService.Frame = frame; 86 NavigationService.NavigationFailed += Frame_NavigationFailed; 87 NavigationService.Navigated += Frame_Navigated; 88 this.navigationView.BackRequested += OnBackRequested; 89 var topLevelItems = navigationView.MenuItems.OfType<NavigationViewItem>(); 90 _moduleNavViewItems = topLevelItems.SelectMany(menuItem => menuItem.MenuItems.OfType<NavigationViewItem>()).ToArray(); 91 _fullListOfNavViewItems = topLevelItems.Union(_moduleNavViewItems).ToArray(); 92 } 93 94 private static KeyboardAccelerator BuildKeyboardAccelerator(VirtualKey key, VirtualKeyModifiers? modifiers = null) 95 { 96 var keyboardAccelerator = new KeyboardAccelerator() { Key = key }; 97 if (modifiers.HasValue) 98 { 99 keyboardAccelerator.Modifiers = modifiers.Value; 100 } 101 102 keyboardAccelerator.Invoked += OnKeyboardAcceleratorInvoked; 103 return keyboardAccelerator; 104 } 105 106 private static void OnKeyboardAcceleratorInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args) 107 { 108 var result = NavigationService.GoBack(); 109 args.Handled = result; 110 } 111 112 private async void OnLoaded() 113 { 114 // Keyboard accelerators are added here to avoid showing 'Alt + left' tooltip on the page. 115 // More info on tracking issue https://github.com/Microsoft/microsoft-ui-xaml/issues/8 116 keyboardAccelerators.Add(altLeftKeyboardAccelerator); 117 keyboardAccelerators.Add(backKeyboardAccelerator); 118 await Task.CompletedTask.ConfigureAwait(false); 119 } 120 121 private void OnItemInvoked(NavigationViewItemInvokedEventArgs args) 122 { 123 var pageType = args.InvokedItemContainer.GetValue(NavHelper.NavigateToProperty) as Type; 124 125 if (pageType != null) 126 { 127 NavigationService.Navigate(pageType); 128 } 129 } 130 131 private void OnBackRequested(NavigationView sender, NavigationViewBackRequestedEventArgs args) 132 { 133 NavigationService.GoBack(); 134 } 135 136 private void Frame_NavigationFailed(object sender, NavigationFailedEventArgs e) 137 { 138 throw e.Exception; 139 } 140 141 private void Frame_Navigated(object sender, NavigationEventArgs e) 142 { 143 IsBackEnabled = NavigationService.CanGoBack; 144 Selected = _fullListOfNavViewItems.FirstOrDefault(menuItem => IsMenuItemForPageType(menuItem, e.SourcePageType)); 145 } 146 147 private static bool IsMenuItemForPageType(NavigationViewItem menuItem, Type sourcePageType) 148 { 149 var pageType = menuItem.GetValue(NavHelper.NavigateToProperty) as Type; 150 return pageType == sourcePageType; 151 } 152 } 153 }