From 443b3c8b82d77a033e5833d4c07d9d0ce8f5d502 Mon Sep 17 00:00:00 2001 From: Tomas Raies Date: Fri, 3 Apr 2020 19:02:38 -0700 Subject: [PATCH] PowerLauncher Settings * Cherry Picked commit branch due to merge conflicts * add HotkeySettingsControl * add localization strings * add PowerLauncherPage ViewModel * fix build dependency - settings.ui.runner depends on TwoWayIPCLib * uncomment IPC settings propagation --- .../HotkeySettings.cs | 40 ++ .../PowerLauncherSettings.cs | 42 ++ .../SettingsUtils.cs | 49 ++- .../Controls/HotkeySettingsControl.xaml | 14 + .../Controls/HotkeySettingsControl.xaml.cs | 103 +++++ .../Strings/en-us/Resources.resw | 375 ++++++++++-------- .../ViewModels/PowerLauncherViewModel.cs | 168 +++++++- .../Views/PowerLauncherPage.xaml | 116 +++--- .../Views/PowerLauncherPage.xaml.cs | 54 ++- 9 files changed, 733 insertions(+), 228 deletions(-) create mode 100644 src/core/Microsoft.PowerToys.Settings.UI.Lib/HotkeySettings.cs create mode 100644 src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerLauncherSettings.cs create mode 100644 src/core/Microsoft.PowerToys.Settings.UI/Controls/HotkeySettingsControl.xaml create mode 100644 src/core/Microsoft.PowerToys.Settings.UI/Controls/HotkeySettingsControl.xaml.cs diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/HotkeySettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/HotkeySettings.cs new file mode 100644 index 0000000000..3c366281ff --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/HotkeySettings.cs @@ -0,0 +1,40 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + public class HotkeySettings + { + public bool win { get; set; } + public bool ctrl { get; set; } + public bool alt { get; set; } + public bool shift { get; set; } + public string key { get; set; } + public int code { get; set; } + + public override string ToString() + { + StringBuilder output = new StringBuilder(); + + if (win) + { + output.Append("Win + "); + } + if (ctrl) + { + output.Append("Ctrl + "); + } + if (alt) + { + output.Append("Alt + "); + } + if (shift) + { + output.Append("Shift + "); + } + output.Append(key); + return output.ToString(); + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerLauncherSettings.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerLauncherSettings.cs new file mode 100644 index 0000000000..caf722f830 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/PowerLauncherSettings.cs @@ -0,0 +1,42 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Microsoft.PowerToys.Settings.UI.Lib +{ + public class PowerLauncherSettings : BasePTModuleSettings + { + public PowerLauncherProperties properties { get; set; } + + public PowerLauncherSettings() + { + this.properties = new PowerLauncherProperties(); + this.version = "1"; + this.name = "_unset_"; + } + } + + public class PowerLauncherProperties + { + public bool enable_powerlauncher { get; set; } + public string search_result_preference { get; set; } + public string search_type_preference { get; set; } + public int maximum_number_of_results { get; set; } + public HotkeySettings open_powerlauncher { get; set; } + public HotkeySettings open_file_location { get; set; } + public HotkeySettings copy_path_location { get; set; } + public HotkeySettings open_console { get; set; } + public bool override_win_r_key { get; set; } + public bool override_win_s_key { get; set; } + + public PowerLauncherProperties() + { + open_powerlauncher = new HotkeySettings(); + open_file_location = new HotkeySettings(); + copy_path_location = new HotkeySettings(); + open_console = new HotkeySettings(); + search_result_preference = "most_recently_used"; + search_type_preference = "application_name"; + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs index 205607e2b5..e349d7f7d4 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI.Lib/SettingsUtils.cs @@ -8,22 +8,48 @@ namespace Microsoft.PowerToys.Settings.UI.Lib { public static class SettingsUtils { - // Get path to the json settings file. + private static string LocalApplicationDataFolder() + { + return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + } + + public static bool SettingsFolderExists(string powertoy) + { + return Directory.Exists(Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}")); + } + + public static void CreateSettingsFolder(string powertoy) + { + Directory.CreateDirectory(Path.Combine(LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}")); + } + + /// + /// Get path to the json settings file. + /// + /// string path. public static string GetSettingsPath(string powertoy) { if (string.IsNullOrWhiteSpace(powertoy)) { return Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\settings.json"); } return Path.Combine( - Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), + LocalApplicationDataFolder(), $"Microsoft\\PowerToys\\{powertoy}\\settings.json"); } - // Get a Deserialized object of the json settings string. + public static bool SettingsExists(string powertoy) + { + return File.Exists(SettingsUtils.GetSettingsPath(powertoy)); + } + + /// + /// Get a Deserialized object of the json settings string. + /// + /// Deserialized json settings object. public static T GetSettings(string powertoy) { var jsonSettingsString = System.IO.File.ReadAllText(SettingsUtils.GetSettingsPath(powertoy)); @@ -31,11 +57,18 @@ namespace Microsoft.PowerToys.Settings.UI.Lib } // Save settings to a json file. - public static void SaveSettings(string moduleJsonSettings, string powertoyModuleName) + public static void SaveSettings(string jsonSettings, string powertoy) { - System.IO.File.WriteAllText( - SettingsUtils.GetSettingsPath(powertoyModuleName), - moduleJsonSettings); + if(jsonSettings != null) + { + if (!SettingsFolderExists(powertoy)) + { + CreateSettingsFolder(powertoy); + } + System.IO.File.WriteAllText( + SettingsUtils.GetSettingsPath(powertoy), + jsonSettings); + } } } } diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Controls/HotkeySettingsControl.xaml b/src/core/Microsoft.PowerToys.Settings.UI/Controls/HotkeySettingsControl.xaml new file mode 100644 index 0000000000..08cb0d604e --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI/Controls/HotkeySettingsControl.xaml @@ -0,0 +1,14 @@ + + + diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Controls/HotkeySettingsControl.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Controls/HotkeySettingsControl.xaml.cs new file mode 100644 index 0000000000..fc5a404c28 --- /dev/null +++ b/src/core/Microsoft.PowerToys.Settings.UI/Controls/HotkeySettingsControl.xaml.cs @@ -0,0 +1,103 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices.WindowsRuntime; +using System.Text; +using Windows.Foundation; +using Windows.Foundation.Collections; +using Windows.UI.Core; +using Windows.UI.Xaml; +using Windows.UI.Xaml.Controls; +using Windows.UI.Xaml.Controls.Primitives; +using Windows.UI.Xaml.Data; +using Windows.UI.Xaml.Input; +using Windows.UI.Xaml.Media; +using Windows.UI.Xaml.Navigation; + +using Microsoft.PowerToys.Settings.UI.Lib; +using System.ComponentModel; +using System.Runtime.CompilerServices; +// The User Control item template is documented at https://go.microsoft.com/fwlink/?LinkId=234236 + +namespace Microsoft.PowerToys.Settings.UI.Controls +{ + public sealed partial class HotkeySettingsControl : UserControl + { + public string Header { get; set; } + + public static readonly DependencyProperty HotkeySettingsProperty = + DependencyProperty.Register( + "HotkeySettings", + typeof(HotkeySettings), + typeof(HotkeySettingsControl), + null); + + private HotkeySettings _hotkeySettings; + public HotkeySettings HotkeySettings + { + get { return _hotkeySettings; } + set + { + if (_hotkeySettings != value) + { + _hotkeySettings = value; + SetValue(HotkeySettingsProperty, value); + HotkeyTextBox.Text = HotkeySettings.ToString(); + } + } + } + + public HotkeySettingsControl() + { + this.InitializeComponent(); + HotkeyTextBox.PreviewKeyDown += HotkeyTextBox_KeyDown; + } + + private static bool IsDown(Windows.System.VirtualKey key) + { + return Window.Current.CoreWindow.GetKeyState(key).HasFlag(CoreVirtualKeyStates.Down); + } + + private void HotkeyTextBox_KeyDown(object sender, KeyRoutedEventArgs e) + { + e.Handled = true; + if ( + e.Key == Windows.System.VirtualKey.LeftWindows || + e.Key == Windows.System.VirtualKey.RightWindows || + e.Key == Windows.System.VirtualKey.Control || + e.Key == Windows.System.VirtualKey.Menu || + e.Key == Windows.System.VirtualKey.Shift + ) + { + return; + } + + var settings = new HotkeySettings(); + // Display HotKey value + if (IsDown(Windows.System.VirtualKey.LeftWindows) || + IsDown(Windows.System.VirtualKey.RightWindows)) + { + settings.win = true; + } + if (IsDown(Windows.System.VirtualKey.Control)) + { + settings.ctrl = true; + } + if (IsDown(Windows.System.VirtualKey.Menu)) + { + settings.alt = true; + } + if (IsDown(Windows.System.VirtualKey.Shift)) + { + settings.shift = true; + } + + settings.key = e.Key.ToString(); + + // TODO: Check that e.OriginalKey is the ScanCode. It is not clear from docs. + settings.code = (int) e.OriginalKey; + HotkeySettings = settings; + } + } +} diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw b/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw index 13bf1145e1..ac3585c89d 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw +++ b/src/core/Microsoft.PowerToys.Settings.UI/Strings/en-us/Resources.resw @@ -1,160 +1,217 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - Microsoft.PowerToys.Settings.UI - Application display name - - - Microsoft.PowerToys.Settings.UI - Application description - - - Main - Navigation view item name for Main - - - General - Navigation view item name for General - - - PowerLauncher - Navigation view item name for PowerLauncher - - - PowerRename - Navigation view item name for PowerRename - - - Shortcut Guide - Navigation view item name for Shortcut Guide - - - File Explorer Preview - Navigation view item name for File Explorer Preview - - - FancyZones - Navigation view item name for FancyZones - - - Image Resizer - Navigation view item name for Image Resizer - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Microsoft.PowerToys.Settings.UI + Application display name + + + Microsoft.PowerToys.Settings.UI + Application description + + + Main + Navigation view item name for Main + + + General + Navigation view item name for General + + + PowerLauncher + Navigation view item name for PowerLauncher + + + PowerRename + Navigation view item name for PowerRename + + + Shortcut Guide + Navigation view item name for Shortcut Guide + + + File Explorer Preview + Navigation view item name for File Explorer Preview + + + FancyZones + Navigation view item name for FancyZones + + + Image Resizer + Navigation view item name for Image Resizer + + + A quick launcher that has additional capabilities without sacrificing performance. + + + Enable PowerLauncher + + + Search & results + + + Search result preference + + + Most recently used + + + Alphabetical order + + + Running processes/open applications + + + Search type preference + + + Application name + + + A string that is contained in the application + + + Executable name + + + Maximum numbers of results + + + Shortcuts + + + Open PowerLauncher + + + Open file location + + + Copy path location + + + Open console + + + Override Win+R key + + + Override Win+S key + \ No newline at end of file diff --git a/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/PowerLauncherViewModel.cs b/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/PowerLauncherViewModel.cs index 3fa18551f8..a4d4788c07 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/PowerLauncherViewModel.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI/ViewModels/PowerLauncherViewModel.cs @@ -1,15 +1,181 @@ -// Copyright (c) Microsoft Corporation +// Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; +using System.Collections.Generic; +using System.Runtime.CompilerServices; +using System.Text.Json; using Microsoft.PowerToys.Settings.UI.Helpers; +using Microsoft.PowerToys.Settings.UI.Lib; +using Microsoft.PowerToys.Settings.UI.Views; +using Windows.UI.Xaml.Controls; namespace Microsoft.PowerToys.Settings.UI.ViewModels { public class PowerLauncherViewModel : Observable { + public PowerLauncherSettings settings; + private const string POWERTOY_NAME = "PowerLauncher"; + + public PowerLauncherViewModel() { + if (SettingsUtils.SettingsExists(POWERTOY_NAME)) + { + settings = SettingsUtils.GetSettings(POWERTOY_NAME); + } else + { + settings = new PowerLauncherSettings(); + } + } + + private void UpdateSettings([CallerMemberName] string propertyName = null) + { + // Notify UI of property change + OnPropertyChanged(propertyName); + + // Save settings to file + var options = new JsonSerializerOptions + { + WriteIndented = true + }; + SettingsUtils.SaveSettings(JsonSerializer.Serialize(settings, options), POWERTOY_NAME); + + // Propagate changes to Power Launcher through IPC + var propertiesJson = JsonSerializer.Serialize(settings.properties); + ShellPage.Default_SndMSG_Callback( + string.Format("{{ \"{0}\": {1} }}", POWERTOY_NAME, JsonSerializer.Serialize(settings.properties))); + } + + public bool EnablePowerLauncher + { + get { return settings.properties.enable_powerlauncher; } + set + { + if (settings.properties.enable_powerlauncher != value) + { + settings.properties.enable_powerlauncher = value; + UpdateSettings(); + } + } + } + + public string SearchResultPreference + { + get { return settings.properties.search_result_preference; } + set + { + if (settings.properties.search_result_preference != value) + { + settings.properties.search_result_preference = value; + UpdateSettings(); + } + } + } + + public string SearchTypePreference + { + get { return settings.properties.search_type_preference; } + set + { + if (settings.properties.search_type_preference != value) + { + settings.properties.search_type_preference = value; + UpdateSettings(); + } + } + } + + public int MaximumNumberOfResults + { + get { return settings.properties.maximum_number_of_results; } + set + { + if (settings.properties.maximum_number_of_results != value) + { + settings.properties.maximum_number_of_results = value; + UpdateSettings(); + } + } + } + + public HotkeySettings OpenPowerLauncher + { + get { return settings.properties.open_powerlauncher; } + set + { + if (settings.properties.open_powerlauncher != value) + { + settings.properties.open_powerlauncher = value; + UpdateSettings(); + } + } + } + + public HotkeySettings OpenFileLocation + { + get { return settings.properties.open_file_location; } + set + { + if (settings.properties.open_file_location != value) + { + settings.properties.open_file_location = value; + UpdateSettings(); + } + } + } + + public HotkeySettings CopyPathLocation + { + get { return settings.properties.copy_path_location; } + set + { + if (settings.properties.copy_path_location != value) + { + settings.properties.copy_path_location = value; + UpdateSettings(); + } + } + } + + public HotkeySettings OpenConsole + { + get { return settings.properties.open_console; } + set + { + if (settings.properties.open_console != value) + { + settings.properties.open_console = value; + UpdateSettings(); + } + } + } + + public bool OverrideWinRKey + { + get { return settings.properties.override_win_r_key; } + set + { + if (settings.properties.override_win_r_key != value) + { + settings.properties.override_win_r_key = value; + UpdateSettings(); + } + } + } + + public bool OverrideWinSKey + { + get { return settings.properties.override_win_s_key; } + set + { + if (settings.properties.override_win_s_key != value) + { + settings.properties.override_win_s_key = value; + UpdateSettings(); + } + } } } } \ No newline at end of file diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml b/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml index df78df3cc5..b19f631e65 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml +++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml @@ -1,11 +1,12 @@  @@ -42,79 +43,80 @@ - - + - + + - - Most commonly used - Most recently used - Alphabetical order - Running processes/opened applications - + - - Application name - A string that is contained in the application - Executable name - - - + Margin="{StaticResource SmallTopMargin}" + Minimum="1"/> - - - - + + + + - - + - - + - - - - - - diff --git a/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml.cs b/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml.cs index e71b798e36..5e0be4494c 100644 --- a/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml.cs +++ b/src/core/Microsoft.PowerToys.Settings.UI/Views/PowerLauncherPage.xaml.cs @@ -1,13 +1,14 @@ -// Copyright (c) Microsoft Corporation +// Copyright (c) Microsoft Corporation // The Microsoft Corporation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. - +using Microsoft.PowerToys.Settings.UI.ViewModels; using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; -using Microsoft.PowerToys.Settings.UI.ViewModels; +using System.Text; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.UI.Xaml; @@ -17,16 +18,63 @@ using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; +using Microsoft.PowerToys.Settings.UI.Controls; +using System.Collections.ObjectModel; namespace Microsoft.PowerToys.Settings.UI.Views { public sealed partial class PowerLauncherPage : Page { public PowerLauncherViewModel ViewModel { get; } = new PowerLauncherViewModel(); + ObservableCollection> SearchResultPreferencesOptions; + ObservableCollection> SearchTypePreferencesOptions; public PowerLauncherPage() { this.InitializeComponent(); + + var loader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView(); + + SearchResultPreferencesOptions = new ObservableCollection>(); + SearchResultPreferencesOptions.Add(Tuple.Create(loader.GetString("PowerLauncher_SearchResultPreference_AlphabeticalOrder"), "alphabetical_order")); + SearchResultPreferencesOptions.Add(Tuple.Create(loader.GetString("PowerLauncher_SearchResultPreference_MostRecentlyUsed"), "most_recently_used")); + SearchResultPreferencesOptions.Add(Tuple.Create(loader.GetString("PowerLauncher_SearchResultPreference_RunningProcessesOpenApplications"), "running_processes_open_applications")); + + SearchTypePreferencesOptions = new ObservableCollection>(); + SearchTypePreferencesOptions.Add(Tuple.Create(loader.GetString("PowerLauncher_SearchTypePreference_ApplicationName"), "application_name")); + SearchTypePreferencesOptions.Add(Tuple.Create(loader.GetString("PowerLauncher_SearchTypePreference_StringInApplication"), "string_in_application")); + SearchTypePreferencesOptions.Add(Tuple.Create(loader.GetString("PowerLauncher_SearchTypePreference_ExecutableName"), "executable_name")); + + } + + public Tuple SelectedSearchResultPreference + { + get + { + return SearchResultPreferencesOptions.First(item => item.Item2 == ViewModel.SearchResultPreference); + } + set + { + if (ViewModel.SearchResultPreference != value.Item2) + { + ViewModel.SearchResultPreference = value.Item2; + } + } + } + + public Tuple SelectedSearchTypePreference + { + get + { + return SearchTypePreferencesOptions.First(item => item.Item2 == ViewModel.SearchTypePreference); + } + set + { + if (ViewModel.SearchTypePreference != value.Item2) + { + ViewModel.SearchTypePreference = value.Item2; + } + } } } }