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
This commit is contained in:
Tomas Raies 2020-04-03 19:02:38 -07:00 committed by Tomas Agustin Raies
parent cea6b7067a
commit 443b3c8b82
9 changed files with 733 additions and 228 deletions

View File

@ -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();
}
}
}

View File

@ -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";
}
}
}

View File

@ -8,22 +8,48 @@ namespace Microsoft.PowerToys.Settings.UI.Lib
{ {
public static class SettingsUtils 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}"));
}
/// <summary>
/// Get path to the json settings file.
/// </summary>
/// <returns>string path.</returns>
public static string GetSettingsPath(string powertoy) public static string GetSettingsPath(string powertoy)
{ {
if (string.IsNullOrWhiteSpace(powertoy)) if (string.IsNullOrWhiteSpace(powertoy))
{ {
return Path.Combine( return Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), LocalApplicationDataFolder(),
$"Microsoft\\PowerToys\\settings.json"); $"Microsoft\\PowerToys\\settings.json");
} }
return Path.Combine( return Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), LocalApplicationDataFolder(),
$"Microsoft\\PowerToys\\{powertoy}\\settings.json"); $"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));
}
/// <summary>
/// Get a Deserialized object of the json settings string.
/// </summary>
/// <returns>Deserialized json settings object.</returns>
public static T GetSettings<T>(string powertoy) public static T GetSettings<T>(string powertoy)
{ {
var jsonSettingsString = System.IO.File.ReadAllText(SettingsUtils.GetSettingsPath(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. // 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( if(jsonSettings != null)
SettingsUtils.GetSettingsPath(powertoyModuleName), {
moduleJsonSettings); if (!SettingsFolderExists(powertoy))
{
CreateSettingsFolder(powertoy);
}
System.IO.File.WriteAllText(
SettingsUtils.GetSettingsPath(powertoy),
jsonSettings);
}
} }
} }
} }

View File

@ -0,0 +1,14 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.Controls.HotkeySettingsControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300"
d:DesignWidth="400">
<TextBox x:Name="HotkeyTextBox"
IsReadOnly="True"
Header="{x:Bind Header, Mode=OneTime}"/>
</UserControl>

View File

@ -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;
}
}
}

View File

@ -1,160 +1,217 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<root> <root>
<!-- <!--
Microsoft ResX Schema Microsoft ResX Schema
Version 2.0 Version 2.0
The primary goals of this format is to allow a simple XML format The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes various data types are done through the TypeConverter classes
associated with the data types. associated with the data types.
Example: Example:
... ado.net/XML headers & schema ... ... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader> <resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader> <resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader> <resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader> <resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data> <data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data> <data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64"> <data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value> <value>[base64 mime encoded serialized .NET Framework object]</value>
</data> </data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64"> <data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value> <value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment> <comment>This is a comment</comment>
</data> </data>
There are any number of "resheader" rows that contain simple There are any number of "resheader" rows that contain simple
name/value pairs. name/value pairs.
Each data row contains a name, and value. The row also contains a Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture. text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the Classes that don't support this are serialized and stored with the
mimetype set. mimetype set.
The mimetype is used for serialized objects, and tells the The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly: extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below. read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64 mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter : System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64 mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter : System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64 mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter : using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding. : and then encoded with base64 encoding.
--> -->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata"> <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" /> <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true"> <xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType> <xsd:complexType>
<xsd:choice maxOccurs="unbounded"> <xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata"> <xsd:element name="metadata">
<xsd:complexType> <xsd:complexType>
<xsd:sequence> <xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" /> <xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence> </xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" /> <xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" /> <xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" /> <xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" /> <xsd:attribute ref="xml:space" />
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
<xsd:element name="assembly"> <xsd:element name="assembly">
<xsd:complexType> <xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" /> <xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" /> <xsd:attribute name="name" type="xsd:string" />
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
<xsd:element name="data"> <xsd:element name="data">
<xsd:complexType> <xsd:complexType>
<xsd:sequence> <xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" /> <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence> </xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" /> <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" /> <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" /> <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" /> <xsd:attribute ref="xml:space" />
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
<xsd:element name="resheader"> <xsd:element name="resheader">
<xsd:complexType> <xsd:complexType>
<xsd:sequence> <xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" /> <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence> </xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" /> <xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
</xsd:choice> </xsd:choice>
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
</xsd:schema> </xsd:schema>
<resheader name="resmimetype"> <resheader name="resmimetype">
<value>text/microsoft-resx</value> <value>text/microsoft-resx</value>
</resheader> </resheader>
<resheader name="version"> <resheader name="version">
<value>2.0</value> <value>2.0</value>
</resheader> </resheader>
<resheader name="reader"> <resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<resheader name="writer"> <resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value> <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader> </resheader>
<data name="AppDisplayName" xml:space="preserve"> <data name="AppDisplayName" xml:space="preserve">
<value>Microsoft.PowerToys.Settings.UI</value> <value>Microsoft.PowerToys.Settings.UI</value>
<comment>Application display name</comment> <comment>Application display name</comment>
</data> </data>
<data name="AppDescription" xml:space="preserve"> <data name="AppDescription" xml:space="preserve">
<value>Microsoft.PowerToys.Settings.UI</value> <value>Microsoft.PowerToys.Settings.UI</value>
<comment>Application description</comment> <comment>Application description</comment>
</data> </data>
<data name="Shell_Main.Content" xml:space="preserve"> <data name="Shell_Main.Content" xml:space="preserve">
<value>Main</value> <value>Main</value>
<comment>Navigation view item name for Main</comment> <comment>Navigation view item name for Main</comment>
</data> </data>
<data name="Shell_General.Content" xml:space="preserve"> <data name="Shell_General.Content" xml:space="preserve">
<value>General</value> <value>General</value>
<comment>Navigation view item name for General</comment> <comment>Navigation view item name for General</comment>
</data> </data>
<data name="Shell_PowerLauncher.Content" xml:space="preserve"> <data name="Shell_PowerLauncher.Content" xml:space="preserve">
<value>PowerLauncher</value> <value>PowerLauncher</value>
<comment>Navigation view item name for PowerLauncher</comment> <comment>Navigation view item name for PowerLauncher</comment>
</data> </data>
<data name="Shell_PowerRename.Content" xml:space="preserve"> <data name="Shell_PowerRename.Content" xml:space="preserve">
<value>PowerRename</value> <value>PowerRename</value>
<comment>Navigation view item name for PowerRename</comment> <comment>Navigation view item name for PowerRename</comment>
</data> </data>
<data name="Shell_ShortcutGuide.Content" xml:space="preserve"> <data name="Shell_ShortcutGuide.Content" xml:space="preserve">
<value>Shortcut Guide</value> <value>Shortcut Guide</value>
<comment>Navigation view item name for Shortcut Guide</comment> <comment>Navigation view item name for Shortcut Guide</comment>
</data> </data>
<data name="Shell_PowerPreview.Content" xml:space="preserve"> <data name="Shell_PowerPreview.Content" xml:space="preserve">
<value>File Explorer Preview</value> <value>File Explorer Preview</value>
<comment>Navigation view item name for File Explorer Preview</comment> <comment>Navigation view item name for File Explorer Preview</comment>
</data> </data>
<data name="Shell_FancyZones.Content" xml:space="preserve"> <data name="Shell_FancyZones.Content" xml:space="preserve">
<value>FancyZones</value> <value>FancyZones</value>
<comment>Navigation view item name for FancyZones</comment> <comment>Navigation view item name for FancyZones</comment>
</data> </data>
<data name="Shell_ImageResizer.Content" xml:space="preserve"> <data name="Shell_ImageResizer.Content" xml:space="preserve">
<value>Image Resizer</value> <value>Image Resizer</value>
<comment>Navigation view item name for Image Resizer</comment> <comment>Navigation view item name for Image Resizer</comment>
</data> </data>
<data name="PowerLauncher_Description.Text" xml:space="preserve">
<value>A quick launcher that has additional capabilities without sacrificing performance.</value>
</data>
<data name="PowerLauncher_EnablePowerLauncher.Header" xml:space="preserve">
<value>Enable PowerLauncher</value>
</data>
<data name="PowerLauncher_SearchResults.Text" xml:space="preserve">
<value>Search &amp; results</value>
</data>
<data name="PowerLauncher_SearchResultPreference.Header" xml:space="preserve">
<value>Search result preference</value>
</data>
<data name="PowerLauncher_SearchResultPreference_MostRecentlyUsed" xml:space="preserve">
<value>Most recently used</value>
</data>
<data name="PowerLauncher_SearchResultPreference_AlphabeticalOrder" xml:space="preserve">
<value>Alphabetical order</value>
</data>
<data name="PowerLauncher_SearchResultPreference_RunningProcessesOpenApplications" xml:space="preserve">
<value>Running processes/open applications</value>
</data>
<data name="PowerLauncher_SearchTypePreference.Header" xml:space="preserve">
<value>Search type preference</value>
</data>
<data name="PowerLauncher_SearchTypePreference_ApplicationName" xml:space="preserve">
<value>Application name</value>
</data>
<data name="PowerLauncher_SearchTypePreference_StringInApplication" xml:space="preserve">
<value>A string that is contained in the application</value>
</data>
<data name="PowerLauncher_SearchTypePreference_ExecutableName" xml:space="preserve">
<value>Executable name</value>
</data>
<data name="PowerLauncher_MaximumNumberOfResults.Header" xml:space="preserve">
<value>Maximum numbers of results</value>
</data>
<data name="PowerLauncher_Shortcuts.Text" xml:space="preserve">
<value>Shortcuts</value>
</data>
<data name="PowerLauncher_OpenPowerLauncher.Header" xml:space="preserve">
<value>Open PowerLauncher</value>
</data>
<data name="PowerLauncher_OpenFileLocation.Header" xml:space="preserve">
<value>Open file location</value>
</data>
<data name="PowerLauncher_CopyPathLocation.Header" xml:space="preserve">
<value>Copy path location</value>
</data>
<data name="PowerLauncher_OpenConsole.Header" xml:space="preserve">
<value>Open console</value>
</data>
<data name="PowerLauncher_OverrideWinRKey.Content" xml:space="preserve">
<value>Override Win+R key</value>
</data>
<data name="PowerLauncher_OverrideWinSKey.Content" xml:space="preserve">
<value>Override Win+S key</value>
</data>
</root> </root>

View File

@ -1,15 +1,181 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // 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.Helpers;
using Microsoft.PowerToys.Settings.UI.Lib;
using Microsoft.PowerToys.Settings.UI.Views;
using Windows.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.ViewModels namespace Microsoft.PowerToys.Settings.UI.ViewModels
{ {
public class PowerLauncherViewModel : Observable public class PowerLauncherViewModel : Observable
{ {
public PowerLauncherSettings settings;
private const string POWERTOY_NAME = "PowerLauncher";
public PowerLauncherViewModel() public PowerLauncherViewModel()
{ {
if (SettingsUtils.SettingsExists(POWERTOY_NAME))
{
settings = SettingsUtils.GetSettings<PowerLauncherSettings>(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();
}
}
} }
} }
} }

View File

@ -1,11 +1,12 @@
<Page <Page
x:Class="Microsoft.PowerToys.Settings.UI.Views.PowerLauncherPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Views" xmlns:local="using:Microsoft.PowerToys.Settings.UI.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls" xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:Custom="using:Microsoft.PowerToys.Settings.UI.Controls"
x:Class="Microsoft.PowerToys.Settings.UI.Views.PowerLauncherPage"
mc:Ignorable="d" mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
@ -42,79 +43,80 @@
</Grid.RowDefinitions> </Grid.RowDefinitions>
<StackPanel Orientation="Vertical"> <StackPanel Orientation="Vertical">
<TextBlock Text="A quick launcher that has additional capabilities without sacrificing performance." Style="{StaticResource BodyTextBlockStyle}" <TextBlock x:Uid="PowerLauncher_Description" Style="{StaticResource BodyTextBlockStyle}"
TextWrapping="Wrap"/> TextWrapping="Wrap"/>
<ToggleSwitch Header="Enable PowerLauncher" <ToggleSwitch x:Uid="PowerLauncher_EnablePowerLauncher"
IsOn="True" IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.EnablePowerLauncher}"
Margin="{StaticResource SmallTopMargin}" /> Margin="{StaticResource SmallTopMargin}"/>
<TextBlock Text="Search &amp; results" <TextBlock x:Uid="PowerLauncher_SearchResults"
Style="{StaticResource SettingsGroupTitleStyle}"/> Style="{StaticResource SettingsGroupTitleStyle}"/>
<ComboBox x:Uid="PowerLauncher_SearchResultPreference"
MinWidth="320"
Margin="{StaticResource SmallTopMargin}"
ItemsSource="{x:Bind SearchResultPreferencesOptions}"
SelectedItem="{x:Bind Mode=TwoWay, Path=SelectedSearchResultPreference}"
SelectedValuePath="Item2"
DisplayMemberPath="Item1"
/>
<ComboBox Header="Search result preference" <ComboBox x:Uid="PowerLauncher_SearchTypePreference"
SelectedIndex="0" MinWidth="320"
MinWidth="320" Margin="{StaticResource SmallTopMargin}"
Margin="{StaticResource SmallTopMargin}"> ItemsSource="{x:Bind SearchTypePreferencesOptions}"
<ComboBoxItem>Most commonly used</ComboBoxItem> SelectedItem="{x:Bind Mode=TwoWay, Path=SelectedSearchTypePreference}"
<ComboBoxItem>Most recently used</ComboBoxItem> SelectedValuePath="Item2"
<ComboBoxItem>Alphabetical order</ComboBoxItem> DisplayMemberPath="Item1"
<ComboBoxItem>Running processes/opened applications</ComboBoxItem> />
</ComboBox>
<ComboBox Header="Search type preference" <muxc:NumberBox x:Uid="PowerLauncher_MaximumNumberOfResults"
SelectedIndex="0" Value="{x:Bind Mode=TwoWay, Path=ViewModel.MaximumNumberOfResults}"
MinWidth="320"
Margin="{StaticResource SmallTopMargin}">
<ComboBoxItem>Application name</ComboBoxItem>
<ComboBoxItem>A string that is contained in the application</ComboBoxItem>
<ComboBoxItem>Executable name</ComboBoxItem>
</ComboBox>
<muxc:NumberBox Header="Maximum numbers of results"
Value="4"
Width="320" Width="320"
SpinButtonPlacementMode="Inline" SpinButtonPlacementMode="Inline"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}" /> Margin="{StaticResource SmallTopMargin}"
Minimum="1"/>
<TextBlock x:Uid="PowerLauncher_Shortcuts"
<TextBlock Text="Shortcuts"
Width="320" Width="320"
HorizontalAlignment="Left" HorizontalAlignment="Left"
Style="{StaticResource SettingsGroupTitleStyle}"/> Style="{StaticResource SettingsGroupTitleStyle}"/>
<!-- TO DO: Add logic to only allow specific (or combination of) keys as entries --> <Custom:HotkeySettingsControl x:Uid="PowerLauncher_OpenPowerLauncher"
<TextBox Header="Open PowerLauncher" Width="320"
Width="320" HorizontalAlignment="Left"
HorizontalAlignment="Left" Margin="{StaticResource SmallTopMargin}"
Margin="{StaticResource SmallTopMargin}"/> HotkeySettings="{x:Bind Path=ViewModel.OpenPowerLauncher, Mode=TwoWay}"
/>
<Custom:HotkeySettingsControl x:Uid="PowerLauncher_OpenFileLocation"
Width="320"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"
HotkeySettings="{x:Bind Path=ViewModel.OpenFileLocation, Mode=TwoWay}"
/>
<Custom:HotkeySettingsControl x:Uid="PowerLauncher_CopyPathLocation"
Width="320"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"
HotkeySettings="{x:Bind Path=ViewModel.CopyPathLocation, Mode=TwoWay}"
/>
<Custom:HotkeySettingsControl x:Uid="PowerLauncher_OpenConsole"
Width="320"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"
HotkeySettings="{x:Bind Path=ViewModel.OpenConsole, Mode=TwoWay}"
/>
<!-- TO DO: Add logic to only allow specific (or combination of) keys as entries --> <CheckBox x:Uid="PowerLauncher_OverrideWinRKey"
<TextBox Header="Open file location" Margin="{StaticResource SmallTopMargin}"
Width="320" IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.OverrideWinRKey}"/>
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"/>
<!-- TO DO: Add logic to only allow specific (or combination of) keys as entries --> <CheckBox x:Uid="PowerLauncher_OverrideWinSKey"
<TextBox Header="Copy path location" Margin="{StaticResource SmallTopMargin}"
Width="320" IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.OverrideWinSKey}" />
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"/>
<!-- TO DO: Add logic to only allow specific (or combination of) keys as entries -->
<TextBox Header="Open console"
HorizontalAlignment="Left"
Width="320"
Margin="{StaticResource SmallTopMargin}"/>
<CheckBox Content="Override Win+R key"
IsChecked="True"
Margin="{StaticResource SmallTopMargin}"/>
<CheckBox Content="Override Win+S key"
IsChecked="True"
Margin="{StaticResource SmallTopMargin}" />
</StackPanel> </StackPanel>

View File

@ -1,13 +1,14 @@
// Copyright (c) Microsoft Corporation // Copyright (c) Microsoft Corporation
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using Microsoft.PowerToys.Settings.UI.ViewModels;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime; using System.Runtime.InteropServices.WindowsRuntime;
using Microsoft.PowerToys.Settings.UI.ViewModels; using System.Text;
using Windows.Foundation; using Windows.Foundation;
using Windows.Foundation.Collections; using Windows.Foundation.Collections;
using Windows.UI.Xaml; using Windows.UI.Xaml;
@ -17,16 +18,63 @@ using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation; using Windows.UI.Xaml.Navigation;
using Microsoft.PowerToys.Settings.UI.Controls;
using System.Collections.ObjectModel;
namespace Microsoft.PowerToys.Settings.UI.Views namespace Microsoft.PowerToys.Settings.UI.Views
{ {
public sealed partial class PowerLauncherPage : Page public sealed partial class PowerLauncherPage : Page
{ {
public PowerLauncherViewModel ViewModel { get; } = new PowerLauncherViewModel(); public PowerLauncherViewModel ViewModel { get; } = new PowerLauncherViewModel();
ObservableCollection<Tuple<string, string>> SearchResultPreferencesOptions;
ObservableCollection<Tuple<string, string>> SearchTypePreferencesOptions;
public PowerLauncherPage() public PowerLauncherPage()
{ {
this.InitializeComponent(); this.InitializeComponent();
var loader = Windows.ApplicationModel.Resources.ResourceLoader.GetForCurrentView();
SearchResultPreferencesOptions = new ObservableCollection<Tuple<string, string>>();
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<Tuple<string, string>>();
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<string, string> SelectedSearchResultPreference
{
get
{
return SearchResultPreferencesOptions.First(item => item.Item2 == ViewModel.SearchResultPreference);
}
set
{
if (ViewModel.SearchResultPreference != value.Item2)
{
ViewModel.SearchResultPreference = value.Item2;
}
}
}
public Tuple<string, string> SelectedSearchTypePreference
{
get
{
return SearchTypePreferencesOptions.First(item => item.Item2 == ViewModel.SearchTypePreference);
}
set
{
if (ViewModel.SearchTypePreference != value.Item2)
{
ViewModel.SearchTypePreference = value.Item2;
}
}
} }
} }
} }