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
{
// 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)
{
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));
}
/// <summary>
/// Get a Deserialized object of the json settings string.
/// </summary>
/// <returns>Deserialized json settings object.</returns>
public static T GetSettings<T>(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);
}
}
}
}

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"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, 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="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<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>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: 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:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<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:sequence>
<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="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AppDisplayName" xml:space="preserve">
<value>Microsoft.PowerToys.Settings.UI</value>
<comment>Application display name</comment>
</data>
<data name="AppDescription" xml:space="preserve">
<value>Microsoft.PowerToys.Settings.UI</value>
<comment>Application description</comment>
</data>
<data name="Shell_Main.Content" xml:space="preserve">
<value>Main</value>
<comment>Navigation view item name for Main</comment>
</data>
<data name="Shell_General.Content" xml:space="preserve">
<value>General</value>
<comment>Navigation view item name for General</comment>
</data>
<data name="Shell_PowerLauncher.Content" xml:space="preserve">
<value>PowerLauncher</value>
<comment>Navigation view item name for PowerLauncher</comment>
</data>
<data name="Shell_PowerRename.Content" xml:space="preserve">
<value>PowerRename</value>
<comment>Navigation view item name for PowerRename</comment>
</data>
<data name="Shell_ShortcutGuide.Content" xml:space="preserve">
<value>Shortcut Guide</value>
<comment>Navigation view item name for Shortcut Guide</comment>
</data>
<data name="Shell_PowerPreview.Content" xml:space="preserve">
<value>File Explorer Preview</value>
<comment>Navigation view item name for File Explorer Preview</comment>
</data>
<data name="Shell_FancyZones.Content" xml:space="preserve">
<value>FancyZones</value>
<comment>Navigation view item name for FancyZones</comment>
</data>
<data name="Shell_ImageResizer.Content" xml:space="preserve">
<value>Image Resizer</value>
<comment>Navigation view item name for Image Resizer</comment>
</data>
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, 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="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<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>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: 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:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<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:sequence>
<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="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="AppDisplayName" xml:space="preserve">
<value>Microsoft.PowerToys.Settings.UI</value>
<comment>Application display name</comment>
</data>
<data name="AppDescription" xml:space="preserve">
<value>Microsoft.PowerToys.Settings.UI</value>
<comment>Application description</comment>
</data>
<data name="Shell_Main.Content" xml:space="preserve">
<value>Main</value>
<comment>Navigation view item name for Main</comment>
</data>
<data name="Shell_General.Content" xml:space="preserve">
<value>General</value>
<comment>Navigation view item name for General</comment>
</data>
<data name="Shell_PowerLauncher.Content" xml:space="preserve">
<value>PowerLauncher</value>
<comment>Navigation view item name for PowerLauncher</comment>
</data>
<data name="Shell_PowerRename.Content" xml:space="preserve">
<value>PowerRename</value>
<comment>Navigation view item name for PowerRename</comment>
</data>
<data name="Shell_ShortcutGuide.Content" xml:space="preserve">
<value>Shortcut Guide</value>
<comment>Navigation view item name for Shortcut Guide</comment>
</data>
<data name="Shell_PowerPreview.Content" xml:space="preserve">
<value>File Explorer Preview</value>
<comment>Navigation view item name for File Explorer Preview</comment>
</data>
<data name="Shell_FancyZones.Content" xml:space="preserve">
<value>FancyZones</value>
<comment>Navigation view item name for FancyZones</comment>
</data>
<data name="Shell_ImageResizer.Content" xml:space="preserve">
<value>Image Resizer</value>
<comment>Navigation view item name for Image Resizer</comment>
</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>

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.
// 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<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
x:Class="Microsoft.PowerToys.Settings.UI.Views.PowerLauncherPage"
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.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
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"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
@ -42,79 +43,80 @@
</Grid.RowDefinitions>
<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"/>
<ToggleSwitch Header="Enable PowerLauncher"
IsOn="True"
Margin="{StaticResource SmallTopMargin}" />
<ToggleSwitch x:Uid="PowerLauncher_EnablePowerLauncher"
IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.EnablePowerLauncher}"
Margin="{StaticResource SmallTopMargin}"/>
<TextBlock Text="Search &amp; results"
<TextBlock x:Uid="PowerLauncher_SearchResults"
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"
SelectedIndex="0"
MinWidth="320"
Margin="{StaticResource SmallTopMargin}">
<ComboBoxItem>Most commonly used</ComboBoxItem>
<ComboBoxItem>Most recently used</ComboBoxItem>
<ComboBoxItem>Alphabetical order</ComboBoxItem>
<ComboBoxItem>Running processes/opened applications</ComboBoxItem>
</ComboBox>
<ComboBox x:Uid="PowerLauncher_SearchTypePreference"
MinWidth="320"
Margin="{StaticResource SmallTopMargin}"
ItemsSource="{x:Bind SearchTypePreferencesOptions}"
SelectedItem="{x:Bind Mode=TwoWay, Path=SelectedSearchTypePreference}"
SelectedValuePath="Item2"
DisplayMemberPath="Item1"
/>
<ComboBox Header="Search type preference"
SelectedIndex="0"
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"
<muxc:NumberBox x:Uid="PowerLauncher_MaximumNumberOfResults"
Value="{x:Bind Mode=TwoWay, Path=ViewModel.MaximumNumberOfResults}"
Width="320"
SpinButtonPlacementMode="Inline"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}" />
Margin="{StaticResource SmallTopMargin}"
Minimum="1"/>
<TextBlock Text="Shortcuts"
<TextBlock x:Uid="PowerLauncher_Shortcuts"
Width="320"
HorizontalAlignment="Left"
Style="{StaticResource SettingsGroupTitleStyle}"/>
<!-- TO DO: Add logic to only allow specific (or combination of) keys as entries -->
<TextBox Header="Open PowerLauncher"
Width="320"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"/>
<Custom:HotkeySettingsControl x:Uid="PowerLauncher_OpenPowerLauncher"
Width="320"
HorizontalAlignment="Left"
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 -->
<TextBox Header="Open file location"
Width="320"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"/>
<CheckBox x:Uid="PowerLauncher_OverrideWinRKey"
Margin="{StaticResource SmallTopMargin}"
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.OverrideWinRKey}"/>
<!-- TO DO: Add logic to only allow specific (or combination of) keys as entries -->
<TextBox Header="Copy path location"
Width="320"
HorizontalAlignment="Left"
Margin="{StaticResource SmallTopMargin}"/>
<CheckBox x:Uid="PowerLauncher_OverrideWinSKey"
Margin="{StaticResource SmallTopMargin}"
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.OverrideWinSKey}" />
<!-- 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>

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.
// 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<Tuple<string, string>> SearchResultPreferencesOptions;
ObservableCollection<Tuple<string, string>> SearchTypePreferencesOptions;
public PowerLauncherPage()
{
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;
}
}
}
}
}