mirror of
https://github.com/microsoft/PowerToys.git
synced 2026-02-24 04:00:02 +01:00
Refactoring, commenting and fixing some little lefrover bugs
This commit is contained in:
@@ -21,7 +21,7 @@ namespace ShortcutGuide.IndexYmlGenerator
|
||||
// Todo: Exception handling
|
||||
public static void CreateIndexYmlFile()
|
||||
{
|
||||
string path = ManifestInterpreter.GetPathOfInterpretations();
|
||||
string path = ManifestInterpreter.PathOfManifestFiles;
|
||||
if (File.Exists(Path.Combine(path, "index.yml")))
|
||||
{
|
||||
File.Delete(Path.Combine(path, "index.yml"));
|
||||
|
||||
@@ -9,21 +9,28 @@ namespace ShortcutGuide.Helpers
|
||||
{
|
||||
public static class DisplayHelper
|
||||
{
|
||||
private enum MonitorFromWindowDwFlags
|
||||
{
|
||||
MONITOR_DEFAULTTONEAREST = 2,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the display work area for the monitor that contains the specified window.
|
||||
/// </summary>
|
||||
/// <param name="hwnd">The window handle</param>
|
||||
/// <returns>A <see cref="Rect"/> element containing the display area</returns>
|
||||
public static Rect GetWorkAreaForDisplayWithWindow(nint hwnd)
|
||||
{
|
||||
_foundMonitorIndex = -1;
|
||||
_monitorIndex = 0;
|
||||
var monitor = NativeMethods.MonitorFromWindow(hwnd, (int)MonitorFromWindowDwFlags.MONITOR_DEFAULTTONEAREST);
|
||||
var monitor = NativeMethods.MonitorFromWindow(hwnd, (int)NativeMethods.MonitorFromWindowDwFlags.MONITOR_DEFAULTTONEAREST);
|
||||
NativeMethods.EnumDisplayMonitors(nint.Zero, nint.Zero, MonitorEnumProc, new NativeMethods.LPARAM(monitor));
|
||||
return MonitorInfo.GetDisplayMonitors()[_foundMonitorIndex].RectWork;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The index of the monitor that contains the specified window. -1 indicates that no monitor was found (yet).
|
||||
/// </summary>
|
||||
private static int _foundMonitorIndex = -1;
|
||||
|
||||
/// <summary>
|
||||
/// The index of the monitor in the enumeration. This is used to find the correct monitor in the list of monitors.
|
||||
/// </summary>
|
||||
private static int _monitorIndex;
|
||||
|
||||
private static bool MonitorEnumProc(nint hMonitor, nint hdcMonitor, ref NativeMethods.RECT lprcMonitor, nint dwData)
|
||||
|
||||
@@ -20,13 +20,13 @@ namespace ShortcutGuide.Helpers
|
||||
return (float)dpi / DEFAULT_DPI;
|
||||
}
|
||||
|
||||
public static long GetScreenDPIForWindow(int hwnd, ref int dpi)
|
||||
private static long GetScreenDPIForWindow(int hwnd, ref int dpi)
|
||||
{
|
||||
var targetMonitor = NativeMethods.MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
|
||||
return GetScreenDPIForMonitor(targetMonitor.ToInt32(), ref dpi);
|
||||
}
|
||||
|
||||
public static long GetScreenDPIForMonitor(int targetMonitor, ref int dpi)
|
||||
private static long GetScreenDPIForMonitor(int targetMonitor, ref int dpi)
|
||||
{
|
||||
if (targetMonitor != 0)
|
||||
{
|
||||
|
||||
@@ -15,18 +15,34 @@ using YamlDotNet.Serialization;
|
||||
|
||||
namespace ShortcutGuide.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Helps to interpret the manifest files for the Shortcut Guide.
|
||||
/// </summary>
|
||||
public class ManifestInterpreter
|
||||
{
|
||||
// Todo: Get language from settings or environment variable, default to "en-US"
|
||||
|
||||
/// <summary>
|
||||
/// Gets the language used for the manifest files.
|
||||
/// </summary>
|
||||
public static string Language => "en-US";
|
||||
|
||||
/// <summary>
|
||||
/// Returns the shortcuts for a specific application.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The method should only be called if the application is known to have a shortcuts file.
|
||||
/// </remarks>
|
||||
/// <param name="applicationName">The manifest id.</param>
|
||||
/// <returns>The deserialized shortcuts file.</returns>
|
||||
/// <exception cref="FileNotFoundException">The requested file was not found.</exception>
|
||||
public static ShortcutFile GetShortcutsOfApplication(string applicationName)
|
||||
{
|
||||
string path = GetPathOfInterpretations();
|
||||
string path = PathOfManifestFiles;
|
||||
IEnumerable<string> files = Directory.EnumerateFiles(path, applicationName + ".*.yml") ??
|
||||
throw new FileNotFoundException($"The file for the application '{applicationName}' was not found in '{path}'.");
|
||||
|
||||
IEnumerable<string> filesEnumerable = files as string[] ?? files.ToArray();
|
||||
IEnumerable<string> filesEnumerable = files as string[] ?? [.. files];
|
||||
return filesEnumerable.Any(f => f.EndsWith($".{Language}.yml", StringComparison.InvariantCulture))
|
||||
? YamlToShortcutList(File.ReadAllText(Path.Combine(path, applicationName + $".{Language}.yml")))
|
||||
: filesEnumerable.Any(f => f.EndsWith(".en-US.yml", StringComparison.InvariantCulture))
|
||||
@@ -34,25 +50,38 @@ namespace ShortcutGuide.Helpers
|
||||
: throw new FileNotFoundException($"The file for the application '{applicationName}' was not found in '{path}' with the language '{Language}' or 'en-US'.");
|
||||
}
|
||||
|
||||
public static ShortcutFile YamlToShortcutList(string content)
|
||||
/// <summary>
|
||||
/// Deserializes the content of a YAML file to a <see cref="ShortcutFile"/>.
|
||||
/// </summary>
|
||||
/// <param name="content">The content of the YAML file.</param>
|
||||
/// <returns>A deserialized <see cref="ShortcutFile"/> object.</returns>
|
||||
private static ShortcutFile YamlToShortcutList(string content)
|
||||
{
|
||||
Deserializer deserializer = new();
|
||||
return deserializer.Deserialize<ShortcutFile>(content);
|
||||
}
|
||||
|
||||
public static string GetPathOfInterpretations()
|
||||
{
|
||||
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "WinGet", "KeyboardShortcuts");
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the path to the directory where the manifest files are stored.
|
||||
/// </summary>
|
||||
public static string PathOfManifestFiles => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "WinGet", "KeyboardShortcuts");
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the index YAML file that contains the list of all applications and their shortcuts.
|
||||
/// </summary>
|
||||
/// <returns>A deserialized <see cref="IndexFile"/> object.</returns>
|
||||
public static IndexFile GetIndexYamlFile()
|
||||
{
|
||||
string path = GetPathOfInterpretations();
|
||||
string path = PathOfManifestFiles;
|
||||
string content = File.ReadAllText(Path.Combine(path, "index.yml"));
|
||||
Deserializer deserializer = new();
|
||||
return deserializer.Deserialize<IndexFile>(content);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves all application IDs that should be displayed, based on the foreground window and background processes.
|
||||
/// </summary>
|
||||
/// <returns>An array of all application IDs.</returns>
|
||||
public static string[] GetAllCurrentApplicationIds()
|
||||
{
|
||||
nint handle = NativeMethods.GetForegroundWindow();
|
||||
|
||||
@@ -5,132 +5,147 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using static ShortcutGuide.Helpers.ResourceLoaderInstance;
|
||||
|
||||
namespace ShortcutGuide.Helpers
|
||||
{
|
||||
/// <summary>
|
||||
/// Populates the PowerToys shortcuts in the manifest files.
|
||||
/// </summary>
|
||||
internal sealed partial class PowerToysShortcutsPopulator
|
||||
{
|
||||
/// <summary>
|
||||
/// Populates the PowerToys shortcuts in the manifest files.
|
||||
/// </summary>
|
||||
public static void Populate()
|
||||
{
|
||||
string path = Path.Combine(ManifestInterpreter.GetPathOfInterpretations(), $"Microsoft.PowerToys.{ManifestInterpreter.Language}.yml");
|
||||
string path = Path.Combine(ManifestInterpreter.PathOfManifestFiles, $"Microsoft.PowerToys.{ManifestInterpreter.Language}.yml");
|
||||
|
||||
string content = File.ReadAllText(path);
|
||||
StringBuilder content = new(File.ReadAllText(path));
|
||||
|
||||
const string populateStartString = "# <Populate start>";
|
||||
const string populateEndString = "# <Populate end>";
|
||||
|
||||
content = PopulateRegex().Replace(content, populateStartString + Environment.NewLine);
|
||||
content = new(PopulateRegex().Replace(content.ToString(), populateStartString + Environment.NewLine));
|
||||
|
||||
ISettingsUtils settingsUtils = new SettingsUtils();
|
||||
EnabledModules enabledModules = SettingsRepository<GeneralSettings>.GetInstance(settingsUtils).SettingsConfig.Enabled;
|
||||
if (enabledModules.AdvancedPaste)
|
||||
{
|
||||
AdvancedPasteProperties advancedPasteProperties = SettingsRepository<AdvancedPasteSettings>.GetInstance(settingsUtils).SettingsConfig.Properties;
|
||||
content = HotkeySettingsToYaml(advancedPasteProperties.AdvancedPasteUIShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("AdvancedPasteUI_Shortcut/Header"));
|
||||
content = HotkeySettingsToYaml(advancedPasteProperties.PasteAsPlainTextShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsPlainText_Shortcut/Header"));
|
||||
content = HotkeySettingsToYaml(advancedPasteProperties.PasteAsMarkdownShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsMarkdown_Shortcut/Header"));
|
||||
content = HotkeySettingsToYaml(advancedPasteProperties.PasteAsJsonShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsJson_Shortcut/Header"));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdvancedPasteUIShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("AdvancedPasteUI_Shortcut/Header")));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.PasteAsPlainTextShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsPlainText_Shortcut/Header")));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.PasteAsMarkdownShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsMarkdown_Shortcut/Header")));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.PasteAsJsonShortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsJson_Shortcut/Header")));
|
||||
if (advancedPasteProperties.AdditionalActions.ImageToText.IsShown)
|
||||
{
|
||||
content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.ImageToText.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("ImageToText/Header"));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.ImageToText.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("ImageToText/Header")));
|
||||
}
|
||||
|
||||
if (advancedPasteProperties.AdditionalActions.PasteAsFile.IsShown)
|
||||
{
|
||||
content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsTxtFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsTxtFile/Header"));
|
||||
content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsPngFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsPngFile/Header"));
|
||||
content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsHtmlFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("PasteAsHtmlFile/Header"));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsTxtFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsTxtFile/Header")));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsPngFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsPngFile/Header")));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.PasteAsFile.PasteAsHtmlFile.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("PasteAsHtmlFile/Header")));
|
||||
}
|
||||
|
||||
if (advancedPasteProperties.AdditionalActions.Transcode.IsShown)
|
||||
{
|
||||
content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp3.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("TranscodeToMp3/Header"));
|
||||
content = HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp4.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), content, SettingsResourceLoader.GetString("TranscodeToMp4/Header"));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp3.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("TranscodeToMp3/Header")));
|
||||
content.Append(HotkeySettingsToYaml(advancedPasteProperties.AdditionalActions.Transcode.TranscodeToMp4.Shortcut, SettingsResourceLoader.GetString("AdvancedPaste/ModuleTitle"), SettingsResourceLoader.GetString("TranscodeToMp4/Header")));
|
||||
}
|
||||
}
|
||||
|
||||
if (enabledModules.AlwaysOnTop)
|
||||
{
|
||||
content = HotkeySettingsToYaml(SettingsRepository<AlwaysOnTopSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, SettingsResourceLoader.GetString("AlwaysOnTop/ModuleTitle"), content, SettingsResourceLoader.GetString("AlwaysOnTop_ShortDescription"));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<AlwaysOnTopSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, SettingsResourceLoader.GetString("AlwaysOnTop/ModuleTitle"), SettingsResourceLoader.GetString("AlwaysOnTop_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.ColorPicker)
|
||||
{
|
||||
content = HotkeySettingsToYaml(SettingsRepository<ColorPickerSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("ColorPicker/ModuleTitle"), content, SettingsResourceLoader.GetString("ColorPicker_ShortDescription"));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<ColorPickerSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("ColorPicker/ModuleTitle"), SettingsResourceLoader.GetString("ColorPicker_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.CmdPal)
|
||||
{
|
||||
content = HotkeySettingsToYaml(new CmdPalProperties().Hotkey, SettingsResourceLoader.GetString("CmdPal/ModuleTitle"), content);
|
||||
content.Append(HotkeySettingsToYaml(new CmdPalProperties().Hotkey, SettingsResourceLoader.GetString("CmdPal/ModuleTitle")));
|
||||
}
|
||||
|
||||
if (enabledModules.CropAndLock)
|
||||
{
|
||||
CropAndLockProperties cropAndLockProperties = SettingsRepository<CropAndLockSettings>.GetInstance(settingsUtils).SettingsConfig.Properties;
|
||||
content = HotkeySettingsToYaml(cropAndLockProperties.ThumbnailHotkey, SettingsResourceLoader.GetString("CropAndLock/ModuleTitle"), content, SettingsResourceLoader.GetString("CropAndLock_Thumbnail"));
|
||||
content = HotkeySettingsToYaml(cropAndLockProperties.ReparentHotkey, SettingsResourceLoader.GetString("CropAndLock/ModuleTitle"), content, SettingsResourceLoader.GetString("CropAndLock_Reparent"));
|
||||
content.Append(HotkeySettingsToYaml(cropAndLockProperties.ThumbnailHotkey, SettingsResourceLoader.GetString("CropAndLock/ModuleTitle"), SettingsResourceLoader.GetString("CropAndLock_Thumbnail")));
|
||||
content.Append(HotkeySettingsToYaml(cropAndLockProperties.ReparentHotkey, SettingsResourceLoader.GetString("CropAndLock/ModuleTitle"), SettingsResourceLoader.GetString("CropAndLock_Reparent")));
|
||||
}
|
||||
|
||||
if (enabledModules.FancyZones)
|
||||
{
|
||||
content = HotkeySettingsToYaml(SettingsRepository<FancyZonesSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.FancyzonesEditorHotkey, SettingsResourceLoader.GetString("FancyZones/ModuleTitle"), content, SettingsResourceLoader.GetString("FancyZones_OpenEditor"));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<FancyZonesSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.FancyzonesEditorHotkey, SettingsResourceLoader.GetString("FancyZones/ModuleTitle"), SettingsResourceLoader.GetString("FancyZones_OpenEditor")));
|
||||
}
|
||||
|
||||
if (enabledModules.MouseHighlighter)
|
||||
{
|
||||
content = HotkeySettingsToYaml(SettingsRepository<MouseHighlighterSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MouseHighlighter/Header"), content, SettingsResourceLoader.GetString("MouseHighlighter_ShortDescription"));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<MouseHighlighterSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MouseHighlighter/Header"), SettingsResourceLoader.GetString("MouseHighlighter_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.MouseJump)
|
||||
{
|
||||
content = HotkeySettingsToYaml(SettingsRepository<MouseJumpSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MouseJump/Header"), content, SettingsResourceLoader.GetString("MouseJump_ShortDescription"));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<MouseJumpSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MouseJump/Header"), SettingsResourceLoader.GetString("MouseJump_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.MousePointerCrosshairs)
|
||||
{
|
||||
content = HotkeySettingsToYaml(SettingsRepository<MousePointerCrosshairsSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MousePointerCrosshairs/Header"), content, SettingsResourceLoader.GetString("MouseCrosshairs_ShortDescription"));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<MousePointerCrosshairsSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MouseUtils_MousePointerCrosshairs/Header"), SettingsResourceLoader.GetString("MouseCrosshairs_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.Peek)
|
||||
{
|
||||
content = HotkeySettingsToYaml(SettingsRepository<PeekSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("Peek/ModuleTitle"), content);
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<PeekSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("Peek/ModuleTitle")));
|
||||
}
|
||||
|
||||
if (enabledModules.PowerLauncher)
|
||||
{
|
||||
content = HotkeySettingsToYaml(SettingsRepository<PowerLauncherSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.OpenPowerLauncher, SettingsResourceLoader.GetString("PowerLauncher/ModuleTitle"), content);
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<PowerLauncherSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.OpenPowerLauncher, SettingsResourceLoader.GetString("PowerLauncher/ModuleTitle")));
|
||||
}
|
||||
|
||||
if (enabledModules.MeasureTool)
|
||||
{
|
||||
content = HotkeySettingsToYaml(SettingsRepository<MeasureToolSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MeasureTool/ModuleTitle"), content, SettingsResourceLoader.GetString("ScreenRuler_ShortDescription"));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<MeasureToolSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("MeasureTool/ModuleTitle"), SettingsResourceLoader.GetString("ScreenRuler_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.ShortcutGuide)
|
||||
{
|
||||
content = HotkeySettingsToYaml(SettingsRepository<ShortcutGuideSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.DefaultOpenShortcutGuide, SettingsResourceLoader.GetString("ShortcutGuide/ModuleTitle"), content, SettingsResourceLoader.GetString("ShortcutGuide_ShortDescription"));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<ShortcutGuideSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.DefaultOpenShortcutGuide, SettingsResourceLoader.GetString("ShortcutGuide/ModuleTitle"), SettingsResourceLoader.GetString("ShortcutGuide_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.PowerOcr)
|
||||
{
|
||||
content = HotkeySettingsToYaml(SettingsRepository<PowerOcrSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("TextExtractor/ModuleTitle"), content, SettingsResourceLoader.GetString("PowerOcr_ShortDescription"));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<PowerOcrSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.ActivationShortcut, SettingsResourceLoader.GetString("TextExtractor/ModuleTitle"), SettingsResourceLoader.GetString("PowerOcr_ShortDescription")));
|
||||
}
|
||||
|
||||
if (enabledModules.Workspaces)
|
||||
{
|
||||
content = HotkeySettingsToYaml(SettingsRepository<WorkspacesSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, SettingsResourceLoader.GetString("Workspaces/ModuleTitle"), content, SettingsResourceLoader.GetString("Workspaces_ShortDescription"));
|
||||
content.Append(HotkeySettingsToYaml(SettingsRepository<WorkspacesSettings>.GetInstance(settingsUtils).SettingsConfig.Properties.Hotkey, SettingsResourceLoader.GetString("Workspaces/ModuleTitle"), SettingsResourceLoader.GetString("Workspaces_ShortDescription")));
|
||||
}
|
||||
|
||||
content += populateEndString;
|
||||
content.Append(populateEndString);
|
||||
|
||||
File.WriteAllText(path, content);
|
||||
File.WriteAllText(path, content.ToString());
|
||||
}
|
||||
|
||||
public static string HotkeySettingsToYaml(HotkeySettings hotkeySettings, string moduleName, string content, string? description = null)
|
||||
/// <summary>
|
||||
/// Converts the hotkey settings to a YAML format string for the manifest file.
|
||||
/// </summary>
|
||||
/// <param name="hotkeySettings">Object containing a hotkey from the settings.</param>
|
||||
/// <param name="moduleName">The name of the PowerToys module.</param>
|
||||
/// <param name="description">Description of the action.</param>
|
||||
/// <returns>Yaml code for the manifest file.</returns>
|
||||
private static string HotkeySettingsToYaml(HotkeySettings hotkeySettings, string moduleName, string? description = null)
|
||||
{
|
||||
string content = string.Empty;
|
||||
content += " - Name: " + moduleName + Environment.NewLine;
|
||||
content += " Shortcut: " + Environment.NewLine;
|
||||
content += " - Win: " + hotkeySettings.Win.ToString() + Environment.NewLine;
|
||||
@@ -147,9 +162,10 @@ namespace ShortcutGuide.Helpers
|
||||
return content;
|
||||
}
|
||||
|
||||
public static string HotkeySettingsToYaml(KeyboardKeysProperty keyboardKeys, string moduleName, string content, string? description = null)
|
||||
/// <inheritdoc cref="HotkeySettingsToYaml(HotkeySettings, string, string?)"/>
|
||||
private static string HotkeySettingsToYaml(KeyboardKeysProperty hotkeySettings, string moduleName, string? description = null)
|
||||
{
|
||||
return HotkeySettingsToYaml(keyboardKeys.Value, moduleName, content, description);
|
||||
return HotkeySettingsToYaml(hotkeySettings.Value, moduleName, description);
|
||||
}
|
||||
|
||||
[GeneratedRegex(@"# <Populate start>[\s\S\n\r]*# <Populate end>")]
|
||||
|
||||
@@ -8,8 +8,14 @@ namespace ShortcutGuide.Helpers
|
||||
{
|
||||
internal static class ResourceLoaderInstance
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the resource loader for the Shortcut Guide module.
|
||||
/// </summary>
|
||||
internal static ResourceLoader ResourceLoader { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the resource loader for the Settings module.
|
||||
/// </summary>
|
||||
internal static ResourceLoader SettingsResourceLoader { get; private set; }
|
||||
|
||||
static ResourceLoaderInstance()
|
||||
|
||||
@@ -7,8 +7,15 @@ using TasklistButton = ShortcutGuide.NativeMethods.TasklistButton;
|
||||
|
||||
namespace ShortcutGuide.Helpers
|
||||
{
|
||||
internal sealed class TasklistPositions
|
||||
/// <summary>
|
||||
/// Provides methods to retrieve the positions of taskbar buttons on the current monitor.
|
||||
/// </summary>
|
||||
internal static class TasklistPositions
|
||||
{
|
||||
/// <summary>
|
||||
/// Retrieves the taskbar buttons for the current monitor.
|
||||
/// </summary>
|
||||
/// <returns>An array of the taskbar buttons.</returns>
|
||||
public static TasklistButton[] GetButtons()
|
||||
{
|
||||
var monitor = NativeMethods.MonitorFromWindow(MainWindow.WindowHwnd, 0);
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
// 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.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.PowerToys.Settings.UI.Library.Utilities;
|
||||
using Microsoft.UI.Xaml;
|
||||
@@ -108,31 +110,11 @@ namespace ShortcutGuide.Models
|
||||
{
|
||||
List<StackPanel> shortcutStackPanels = [];
|
||||
|
||||
async void AnimateTextBlock(TextBlock animatedTextBlock, string text, int delay = 500)
|
||||
{
|
||||
try
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
while (!ShortcutView.AnimationCancellationTokenSource.Token.IsCancellationRequested)
|
||||
{
|
||||
animatedTextBlock.Text = text[index].ToString();
|
||||
index = (index + 1) % text.Length;
|
||||
await Task.Delay(delay);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < shortcut.Shortcut.Length; i++)
|
||||
{
|
||||
ShortcutDescription shortcutEntry = shortcut.Shortcut[i];
|
||||
StackPanel shortcutStackPanel = new();
|
||||
StackPanel shortcutStackPanel = new() { Orientation = Orientation.Horizontal };
|
||||
shortcutStackPanels.Add(shortcutStackPanel);
|
||||
shortcutStackPanel.Orientation = Orientation.Horizontal;
|
||||
|
||||
// If any entry is blank, we skip the whole shortcut
|
||||
if (shortcutEntry is { Ctrl: false, Alt: false, Shift: false, Win: false, Keys.Length: 0 })
|
||||
@@ -184,94 +166,7 @@ namespace ShortcutGuide.Models
|
||||
|
||||
foreach (string key in shortcutEntry.Keys)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case "<Copilot>":
|
||||
shortcutStackPanel.Children.Add(new BitmapIcon() { UriSource = new("ms-appx:///Assets/ShortcutGuide/CopilotKey.png") });
|
||||
break;
|
||||
case "<Office>":
|
||||
shortcutStackPanel.Children.Add(new BitmapIcon() { UriSource = new("ms-appx:///Assets/ShortcutGuide/OfficeKey.png"), Height = 20, Width = 20 });
|
||||
break;
|
||||
case "<Left>":
|
||||
AddNewTextToStackPanel("←");
|
||||
break;
|
||||
case "<Right>":
|
||||
AddNewTextToStackPanel("→");
|
||||
break;
|
||||
case "<Up>":
|
||||
AddNewTextToStackPanel("↑");
|
||||
break;
|
||||
case "<Down>":
|
||||
AddNewTextToStackPanel("↓");
|
||||
break;
|
||||
case "<TASKBAR1-9>":
|
||||
AddNewTextToStackPanel("...");
|
||||
break;
|
||||
case "<Underlined letter>":
|
||||
TextBlock animatedTextBlock = new()
|
||||
{
|
||||
Text = "A",
|
||||
Margin = new Thickness(3),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
|
||||
// Use monospaced font to ensure the text doesn't move
|
||||
FontFamily = new("Courier New"),
|
||||
TextDecorations = TextDecorations.Underline,
|
||||
};
|
||||
|
||||
shortcutStackPanel.Children.Add(animatedTextBlock);
|
||||
|
||||
AnimateTextBlock(animatedTextBlock, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
break;
|
||||
case "<Arrow>":
|
||||
TextBlock arrowTextBlock = new()
|
||||
{
|
||||
Text = "→",
|
||||
Margin = new Thickness(3),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
};
|
||||
|
||||
shortcutStackPanel.Children.Add(arrowTextBlock);
|
||||
|
||||
AnimateTextBlock(arrowTextBlock, "→↓←↑", 1000);
|
||||
break;
|
||||
case "<ArrowLR>":
|
||||
TextBlock arrowLRTextBlock = new()
|
||||
{
|
||||
Text = "→",
|
||||
Margin = new Thickness(3),
|
||||
FontFamily = new("Courier New"),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
};
|
||||
shortcutStackPanel.Children.Add(arrowLRTextBlock);
|
||||
AnimateTextBlock(arrowLRTextBlock, "→←", 1000);
|
||||
break;
|
||||
case "<ArrowUD>":
|
||||
TextBlock arrowUDTextBlock = new()
|
||||
{
|
||||
Text = "↑",
|
||||
Margin = new Thickness(3),
|
||||
FontFamily = new("Courier New"),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
};
|
||||
shortcutStackPanel.Children.Add(arrowUDTextBlock);
|
||||
AnimateTextBlock(arrowUDTextBlock, "↑↓", 1000);
|
||||
break;
|
||||
case { } name when name.StartsWith('<') && name.EndsWith('>'):
|
||||
AddNewTextToStackPanel(name[1..^1]);
|
||||
break;
|
||||
case { } num when int.TryParse(num, out int parsedNum):
|
||||
if (parsedNum == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
AddNewTextToStackPanel(Helper.GetKeyName((uint)parsedNum));
|
||||
break;
|
||||
default:
|
||||
AddNewTextToStackPanel(key);
|
||||
break;
|
||||
}
|
||||
AddKeyToStackPanel(key, shortcutStackPanel);
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -291,53 +186,190 @@ namespace ShortcutGuide.Models
|
||||
case <= 1:
|
||||
return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, stackPanelToReturn, shortcut);
|
||||
default:
|
||||
stackPanelToReturn = new StackPanel
|
||||
{
|
||||
{
|
||||
stackPanelToReturn = new StackPanel
|
||||
{
|
||||
Orientation = Orientation.Vertical,
|
||||
};
|
||||
Orientation = Orientation.Vertical,
|
||||
};
|
||||
|
||||
foreach (StackPanel panel in shortcutStackPanels)
|
||||
{
|
||||
panel.Visibility = Visibility.Collapsed;
|
||||
stackPanelToReturn.Children.Add(panel);
|
||||
}
|
||||
|
||||
shortcutStackPanels[0].Visibility = Visibility.Visible;
|
||||
for (int i = 1; i < shortcutStackPanels.Count; i++)
|
||||
{
|
||||
shortcutStackPanels[i].Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
async void AnimateStackPanels(StackPanel[] panels, int delay = 2000)
|
||||
{
|
||||
try
|
||||
{
|
||||
int index = 0;
|
||||
while (!ShortcutView.AnimationCancellationTokenSource.Token.IsCancellationRequested)
|
||||
{
|
||||
foreach (StackPanel panel in panels)
|
||||
{
|
||||
panel.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
panels[index].Visibility = Visibility.Visible;
|
||||
index = (index + 1) % panels.Length;
|
||||
await Task.Delay(delay);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
AnimateStackPanels([.. shortcutStackPanels]);
|
||||
}
|
||||
|
||||
return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, stackPanelToReturn, shortcut);
|
||||
foreach (StackPanel panel in shortcutStackPanels)
|
||||
{
|
||||
panel.Visibility = Visibility.Collapsed;
|
||||
stackPanelToReturn.Children.Add(panel);
|
||||
}
|
||||
|
||||
shortcutStackPanels[0].Visibility = Visibility.Visible;
|
||||
for (int i = 1; i < shortcutStackPanels.Count; i++)
|
||||
{
|
||||
shortcutStackPanels[i].Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
AnimateStackPanels([.. shortcutStackPanels]);
|
||||
|
||||
return new ShortcutTemplateDataObject(shortcut.Name, shortcut.Description ?? string.Empty, stackPanelToReturn, shortcut);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Transforms a key string into a visual representation in the stack panel.
|
||||
/// </summary>
|
||||
/// <param name="key">The string reprensentation of the key.</param>
|
||||
/// <param name="shortcutStackPanel">The stackpanel to add the key to.</param>
|
||||
private static void AddKeyToStackPanel(string key, StackPanel shortcutStackPanel)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case "<Copilot>":
|
||||
shortcutStackPanel.Children.Add(new BitmapIcon() { UriSource = new("ms-appx:///Assets/ShortcutGuide/CopilotKey.png") });
|
||||
break;
|
||||
case "<Office>":
|
||||
shortcutStackPanel.Children.Add(new BitmapIcon() { UriSource = new("ms-appx:///Assets/ShortcutGuide/OfficeKey.png"), Height = 20, Width = 20 });
|
||||
break;
|
||||
case "<Left>":
|
||||
AddNewTextToStackPanel("←");
|
||||
break;
|
||||
case "<Right>":
|
||||
AddNewTextToStackPanel("→");
|
||||
break;
|
||||
case "<Up>":
|
||||
AddNewTextToStackPanel("↑");
|
||||
break;
|
||||
case "<Down>":
|
||||
AddNewTextToStackPanel("↓");
|
||||
break;
|
||||
case "<TASKBAR1-9>":
|
||||
AddNewTextToStackPanel("...");
|
||||
break;
|
||||
case "<Underlined letter>":
|
||||
TextBlock animatedTextBlock = new()
|
||||
{
|
||||
Text = "A",
|
||||
Margin = new Thickness(3),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
|
||||
// Use monospaced font to ensure the text doesn't move
|
||||
FontFamily = new("Courier New"),
|
||||
TextDecorations = TextDecorations.Underline,
|
||||
};
|
||||
|
||||
shortcutStackPanel.Children.Add(animatedTextBlock);
|
||||
|
||||
AnimateTextBlock(animatedTextBlock, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
|
||||
break;
|
||||
case "<Arrow>":
|
||||
TextBlock arrowTextBlock = new()
|
||||
{
|
||||
Text = "→",
|
||||
Margin = new Thickness(3),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
};
|
||||
|
||||
shortcutStackPanel.Children.Add(arrowTextBlock);
|
||||
|
||||
AnimateTextBlock(arrowTextBlock, "→↓←↑", 1000);
|
||||
break;
|
||||
case "<ArrowLR>":
|
||||
TextBlock arrowLRTextBlock = new()
|
||||
{
|
||||
Text = "→",
|
||||
Margin = new Thickness(3),
|
||||
FontFamily = new("Courier New"),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
};
|
||||
shortcutStackPanel.Children.Add(arrowLRTextBlock);
|
||||
AnimateTextBlock(arrowLRTextBlock, "→←", 1000);
|
||||
break;
|
||||
case "<ArrowUD>":
|
||||
TextBlock arrowUDTextBlock = new()
|
||||
{
|
||||
Text = "↑",
|
||||
Margin = new Thickness(3),
|
||||
FontFamily = new("Courier New"),
|
||||
VerticalAlignment = VerticalAlignment.Center,
|
||||
};
|
||||
shortcutStackPanel.Children.Add(arrowUDTextBlock);
|
||||
AnimateTextBlock(arrowUDTextBlock, "↑↓", 1000);
|
||||
break;
|
||||
case { } name when name.StartsWith('<') && name.EndsWith('>'):
|
||||
AddNewTextToStackPanel(name[1..^1]);
|
||||
break;
|
||||
case { } num when int.TryParse(num, out int parsedNum):
|
||||
if (parsedNum == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
AddNewTextToStackPanel(Helper.GetKeyName((uint)parsedNum));
|
||||
break;
|
||||
default:
|
||||
AddNewTextToStackPanel(key);
|
||||
break;
|
||||
}
|
||||
|
||||
void AddNewTextToStackPanel(string text)
|
||||
{
|
||||
shortcutStackPanel.Children.Add(new TextBlock { Text = text, Margin = new Thickness(3), VerticalAlignment = VerticalAlignment.Center });
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Animates the text of a TextBlock by cycling through the characters of a given string.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This function runs asynchronously and will not block the UI thread. Exceptions that occur during the animation will be caught and ignored to prevent crashes.
|
||||
/// </remarks>
|
||||
/// <param name="animatedTextBlock">The textblock to animate.</param>
|
||||
/// <param name="text">The characters to cycle through.</param>
|
||||
/// <param name="delay">The delay to the next animation frame.</param>
|
||||
private static async void AnimateTextBlock(TextBlock animatedTextBlock, string text, int delay = 500)
|
||||
{
|
||||
try
|
||||
{
|
||||
int index = 0;
|
||||
CancellationToken cancellationToken = ShortcutView.AnimationCancellationTokenSource.Token;
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
animatedTextBlock.Text = text[index].ToString();
|
||||
index = (index + 1) % text.Length;
|
||||
await Task.Delay(delay);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Animates the visibility of the stack panels one after another.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This function runs asynchronously and will not block the UI thread. Exceptions that occur during the animation will be caught and ignored to prevent crashes.
|
||||
/// </remarks>
|
||||
/// <param name="panels">The panels to animate.</param>
|
||||
/// <param name="delay">The delay to the next animation frame.</param>
|
||||
private static async void AnimateStackPanels(StackPanel[] panels, int delay = 2000)
|
||||
{
|
||||
try
|
||||
{
|
||||
int index = 0;
|
||||
CancellationToken cancellationToken = ShortcutView.AnimationCancellationTokenSource.Token;
|
||||
|
||||
while (!cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
foreach (StackPanel panel in panels)
|
||||
{
|
||||
panel.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
panels[index].Visibility = Visibility.Visible;
|
||||
index = (index + 1) % panels.Length;
|
||||
await Task.Delay(delay);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,14 +7,29 @@ using System.Collections.Generic;
|
||||
|
||||
namespace ShortcutGuide.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents the parameters for the shortcut page in the Shortcut Guide module.
|
||||
/// </summary>
|
||||
internal struct ShortcutPageParameters
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the content of the search box.
|
||||
/// </summary>
|
||||
public static SearchFilterObservable SearchFilter = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pinned shortcuts for the Shortcut Guide.
|
||||
/// </summary>
|
||||
public static Dictionary<string, List<ShortcutEntry>> PinnedShortcuts = [];
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name of the current page being displayed in the Shortcut Guide.
|
||||
/// </summary>
|
||||
public static string CurrentPageName = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The height of the frame that displays the shortcuts.
|
||||
/// </summary>
|
||||
public static FrameHeightObservable FrameHeight = new();
|
||||
|
||||
internal sealed class SearchFilterObservable
|
||||
|
||||
@@ -119,4 +119,9 @@ internal static partial class NativeMethods
|
||||
|
||||
public int Keynum;
|
||||
}
|
||||
|
||||
public enum MonitorFromWindowDwFlags
|
||||
{
|
||||
MONITOR_DEFAULTTONEAREST = 2,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ using System.Threading;
|
||||
using System.Windows;
|
||||
using ManagedCommon;
|
||||
using Microsoft.UI.Dispatching;
|
||||
using Microsoft.UI.Xaml;
|
||||
using Microsoft.Windows.AppLifecycle;
|
||||
using ShortcutGuide.Helpers;
|
||||
using Application = Microsoft.UI.Xaml.Application;
|
||||
@@ -34,9 +33,9 @@ namespace ShortcutGuide
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Directory.Exists(ManifestInterpreter.GetPathOfInterpretations()))
|
||||
if (!Directory.Exists(ManifestInterpreter.PathOfManifestFiles))
|
||||
{
|
||||
Directory.CreateDirectory(ManifestInterpreter.GetPathOfInterpretations());
|
||||
Directory.CreateDirectory(ManifestInterpreter.PathOfManifestFiles);
|
||||
}
|
||||
|
||||
if (NativeMethods.IsCurrentWindowExcludedFromShortcutGuide())
|
||||
@@ -48,7 +47,7 @@ namespace ShortcutGuide
|
||||
// Todo: Handle error
|
||||
foreach (var file in InbuiltManifestFiles)
|
||||
{
|
||||
File.Copy(Path.GetDirectoryName(Environment.ProcessPath) + "\\Assets\\ShortcutGuide\\" + file, ManifestInterpreter.GetPathOfInterpretations() + "\\" + file, true);
|
||||
File.Copy(Path.GetDirectoryName(Environment.ProcessPath) + "\\Assets\\ShortcutGuide\\" + file, ManifestInterpreter.PathOfManifestFiles + "\\" + file, true);
|
||||
}
|
||||
|
||||
Process indexGeneration = Process.Start(Path.GetDirectoryName(Environment.ProcessPath) + "\\PowerToys.ShortcutGuide.IndexYmlGenerator.exe");
|
||||
@@ -56,7 +55,7 @@ namespace ShortcutGuide
|
||||
if (indexGeneration.ExitCode != 0)
|
||||
{
|
||||
Logger.LogError("Index generation failed with exit code: " + indexGeneration.ExitCode);
|
||||
MessageBox.Show($"Shortcut Guide encountered an error while generating the index file. There is likely a corrupt shortcuts file in \"{ManifestInterpreter.GetPathOfInterpretations()}\". Try deleting this directory.", "Error displaying shortcuts", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
MessageBox.Show($"Shortcut Guide encountered an error while generating the index file. There is likely a corrupt shortcuts file in \"{ManifestInterpreter.PathOfManifestFiles}\". Try deleting this directory.", "Error displaying shortcuts", MessageBoxButton.OK, MessageBoxImage.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
</TeachingTip>
|
||||
<TextBox Margin="0,0,6,0" Grid.Column="2" Grid.Row="0" Height="32" Width="300" HorizontalAlignment="Right" VerticalContentAlignment="Center" x:Uid="SearchBox" x:Name="SearchBox" HorizontalContentAlignment="Right" TextChanged="SearchBox_TextChanged">
|
||||
<TextBox.KeyboardAccelerators>
|
||||
<KeyboardAccelerator Modifiers="Control" Key="F" Invoked="SearchBoy_KeyboardAcceleratorInvoked" />
|
||||
<KeyboardAccelerator Modifiers="Control" Key="F" Invoked="SearchBox_KeyboardAcceleratorInvoked" />
|
||||
</TextBox.KeyboardAccelerators>
|
||||
</TextBox>
|
||||
<Button Margin="0,0,6,0" Grid.Column="3" Grid.Row="0" HorizontalContentAlignment="Center" x:Uid="SettingsButton" Click="SettingsButton_Clicked">
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using Common.UI;
|
||||
using ManagedCommon;
|
||||
using Microsoft.PowerToys.Settings.UI.Library;
|
||||
using Microsoft.UI;
|
||||
using Microsoft.UI.Windowing;
|
||||
@@ -29,12 +30,12 @@ namespace ShortcutGuide
|
||||
public sealed partial class MainWindow
|
||||
{
|
||||
private readonly string[] _currentApplicationIds;
|
||||
/*private readonly bool _isInWindowsKeyMode;*/
|
||||
private readonly bool _firstRun;
|
||||
|
||||
public static nint WindowHwnd { get; set; }
|
||||
|
||||
private AppWindow _appWindow;
|
||||
private bool _setPosition;
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
@@ -42,21 +43,6 @@ namespace ShortcutGuide
|
||||
|
||||
InitializeComponent();
|
||||
|
||||
// Todo: Reimplement holding the Windows key down to show the guide.
|
||||
/*
|
||||
_isInWindowsKeyMode = (GetAsyncKeyState(0x5B) & 0x8000) != 0 || (GetAsyncKeyState(0x5C) & 0x8000) != 0;
|
||||
|
||||
if (_isInWindowsKeyMode)
|
||||
{
|
||||
Current.CoreWindow.KeyUp += (_, e) =>
|
||||
{
|
||||
if (e.VirtualKey is (VirtualKey)0x5B or (VirtualKey)0x5C)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
};
|
||||
}*/
|
||||
|
||||
Title = ResourceLoaderInstance.ResourceLoader.GetString("Title")!;
|
||||
|
||||
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
|
||||
@@ -72,7 +58,7 @@ namespace ShortcutGuide
|
||||
this.SetIsMaximizable(false);
|
||||
IsTitleBarVisible = false;
|
||||
|
||||
// Remove the caption style from the window style. Windows App SDK 1.6 added it, which made the title bar and borders appear for Measure Tool. This code removes it.
|
||||
// Remove the caption style from the window style. Windows App SDK 1.6 added it, which made the title bar and borders appear. This code removes it.
|
||||
var windowStyle = GetWindowLongW(hwnd, GWL_STYLE);
|
||||
windowStyle &= ~WS_CAPTION;
|
||||
_ = SetWindowLongW(hwnd, GWL_STYLE, windowStyle);
|
||||
@@ -117,7 +103,8 @@ namespace ShortcutGuide
|
||||
// Ignore, as the theme will be set by the system.
|
||||
break;
|
||||
default:
|
||||
throw new InvalidDataException("Invalid theme value in settings.");
|
||||
Logger.LogError("Invalid theme value in settings: " + shortcutGuideProperties.Theme.Value);
|
||||
break;
|
||||
}
|
||||
|
||||
_firstRun = shortcutGuideProperties.FirstRun.Value;
|
||||
@@ -136,6 +123,7 @@ namespace ShortcutGuide
|
||||
#endif
|
||||
}
|
||||
|
||||
// The code below sets the position of the window to the center of the monitor, but only if it hasn't been set before.
|
||||
if (!_setPosition)
|
||||
{
|
||||
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
|
||||
@@ -168,6 +156,7 @@ namespace ShortcutGuide
|
||||
};
|
||||
}
|
||||
|
||||
// Populate the window selector with the current application IDs if it is empty.
|
||||
if (WindowSelector.Items.Count == 0)
|
||||
{
|
||||
foreach (var item in _currentApplicationIds)
|
||||
@@ -217,8 +206,6 @@ namespace ShortcutGuide
|
||||
ShortcutPageParameters.FrameHeight.OnFrameHeightChanged(ContentFrame.ActualHeight);
|
||||
}
|
||||
|
||||
private bool _setPosition;
|
||||
|
||||
public void CloseButton_Clicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
ShortcutView.AnimationCancellationTokenSource.Cancel();
|
||||
@@ -230,7 +217,7 @@ namespace ShortcutGuide
|
||||
ShortcutPageParameters.SearchFilter.OnFilterChanged(SearchBox.Text);
|
||||
}
|
||||
|
||||
private void SearchBoy_KeyboardAcceleratorInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
|
||||
private void SearchBox_KeyboardAcceleratorInvoked(KeyboardAccelerator sender, KeyboardAcceleratorInvokedEventArgs args)
|
||||
{
|
||||
SearchBox.Focus(FocusState.Programmatic);
|
||||
}
|
||||
@@ -257,6 +244,9 @@ namespace ShortcutGuide
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds the welcome page to the window selector and opens it.
|
||||
/// </summary>
|
||||
private void CreateAndOpenWelcomePage()
|
||||
{
|
||||
WindowSelector.Items.Insert(0, new SelectorBarItem { Name = "<WELCOME>", Text = ResourceLoaderInstance.ResourceLoader.GetString("Welcome"), Icon = new FontIcon { Glyph = "\uE789" } });
|
||||
|
||||
@@ -23,10 +23,15 @@ namespace ShortcutGuide
|
||||
{
|
||||
public sealed partial class ShortcutView : INotifyPropertyChanged
|
||||
{
|
||||
private readonly DispatcherTimer _taskbarUpdateTimer = new() { Interval = TimeSpan.FromMilliseconds(500) };
|
||||
private readonly bool _showTaskbarShortcuts;
|
||||
private readonly DispatcherTimer _taskbarIconsUpdateTimer = new() { Interval = TimeSpan.FromMilliseconds(500) };
|
||||
private readonly ShortcutFile _shortcutList = ManifestInterpreter.GetShortcutsOfApplication(ShortcutPageParameters.CurrentPageName);
|
||||
private bool _showTaskbarShortcuts;
|
||||
private static CancellationTokenSource _animationCancellationTokenSource = new();
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a cancellation token source for animations in shortcut view.
|
||||
/// When setting a new token source, the previous one is cancelled to stop ongoing animations.
|
||||
/// </summary>
|
||||
public static CancellationTokenSource AnimationCancellationTokenSource
|
||||
{
|
||||
get => _animationCancellationTokenSource;
|
||||
@@ -37,42 +42,17 @@ namespace ShortcutGuide
|
||||
}
|
||||
}
|
||||
|
||||
private readonly ShortcutFile _shortcutList = ManifestInterpreter.GetShortcutsOfApplication(ShortcutPageParameters.CurrentPageName);
|
||||
|
||||
public ShortcutView()
|
||||
{
|
||||
InitializeComponent();
|
||||
ShortcutView.AnimationCancellationTokenSource = new();
|
||||
DataContext = this;
|
||||
|
||||
int i = -1;
|
||||
// Stop any ongoing animations by cancelling the previous token source
|
||||
AnimationCancellationTokenSource = new();
|
||||
|
||||
try
|
||||
{
|
||||
CategorySelector.Items.Add(new SelectorBarItem()
|
||||
{
|
||||
Text = ResourceLoaderInstance.ResourceLoader.GetString("Overview"),
|
||||
Name = i.ToString(CultureInfo.InvariantCulture),
|
||||
});
|
||||
|
||||
i++;
|
||||
|
||||
foreach (var category in _shortcutList.Shortcuts)
|
||||
{
|
||||
switch (category.SectionName)
|
||||
{
|
||||
case { } name when name.StartsWith("<TASKBAR1-9>", StringComparison.Ordinal):
|
||||
_showTaskbarShortcuts = true;
|
||||
break;
|
||||
case { } name when name.StartsWith('<') && name.EndsWith('>'):
|
||||
break;
|
||||
default:
|
||||
CategorySelector.Items.Add(new SelectorBarItem() { Text = category.SectionName, Name = i.ToString(CultureInfo.InvariantCulture) });
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
PopulateCategorySelector();
|
||||
|
||||
CategorySelector.SelectedItem = CategorySelector.Items[0];
|
||||
CategorySelector.SelectionChanged += CategorySelector_SelectionChanged;
|
||||
@@ -93,8 +73,8 @@ namespace ShortcutGuide
|
||||
if (_showTaskbarShortcuts)
|
||||
{
|
||||
TaskbarIndicators.Visibility = Visibility.Visible;
|
||||
_taskbarUpdateTimer.Tick += UpdateTaskbarIndicators;
|
||||
_taskbarUpdateTimer.Start();
|
||||
_taskbarIconsUpdateTimer.Tick += UpdateTaskbarIndicators;
|
||||
_taskbarIconsUpdateTimer.Start();
|
||||
}
|
||||
|
||||
OpenOverview();
|
||||
@@ -108,12 +88,46 @@ namespace ShortcutGuide
|
||||
|
||||
Unloaded += (_, _) =>
|
||||
{
|
||||
AnimationCancellationTokenSource = new();
|
||||
_taskbarUpdateTimer.Tick -= UpdateTaskbarIndicators;
|
||||
_taskbarUpdateTimer.Stop();
|
||||
_taskbarIconsUpdateTimer.Tick -= UpdateTaskbarIndicators;
|
||||
_taskbarIconsUpdateTimer.Stop();
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Populates the <see cref="CategorySelector"/> selector and sets <see cref="_showTaskbarShortcuts"/>.
|
||||
/// </summary>
|
||||
private void PopulateCategorySelector()
|
||||
{
|
||||
int i = -1;
|
||||
CategorySelector.Items.Add(new SelectorBarItem()
|
||||
{
|
||||
Text = ResourceLoaderInstance.ResourceLoader.GetString("Overview"),
|
||||
Name = i.ToString(CultureInfo.InvariantCulture),
|
||||
});
|
||||
|
||||
i++;
|
||||
|
||||
foreach (var category in _shortcutList.Shortcuts)
|
||||
{
|
||||
switch (category.SectionName)
|
||||
{
|
||||
case { } name when name.StartsWith("<TASKBAR1-9>", StringComparison.Ordinal):
|
||||
_showTaskbarShortcuts = true;
|
||||
break;
|
||||
case { } name when name.StartsWith('<') && name.EndsWith('>'):
|
||||
break;
|
||||
default:
|
||||
CategorySelector.Items.Add(new SelectorBarItem() { Text = category.SectionName, Name = i.ToString(CultureInfo.InvariantCulture) });
|
||||
break;
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the taskbar indicators.
|
||||
/// </summary>
|
||||
private void UpdateTaskbarIndicators(object? sender, object? e)
|
||||
{
|
||||
NativeMethods.TasklistButton[] buttons = TasklistPositions.GetButtons();
|
||||
@@ -159,11 +173,11 @@ namespace ShortcutGuide
|
||||
((Rectangle)canvases[i].Children[0]).Height = buttons[i].Height / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32());
|
||||
((TextBlock)canvases[i].Children[1]).Width = buttons[i].Width / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32());
|
||||
((TextBlock)canvases[i].Children[1]).Height = buttons[i].Height / DpiHelper.GetDPIScaleForWindow(MainWindow.WindowHwnd.ToInt32());
|
||||
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
canvases[i].Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
canvases[i].Visibility = Visibility.Collapsed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,15 +216,9 @@ namespace ShortcutGuide
|
||||
PinnedListTitle.Visibility = Visibility.Visible;
|
||||
ShortcutListElement.Visibility = Visibility.Collapsed;
|
||||
|
||||
foreach (var list in _shortcutList.Shortcuts)
|
||||
foreach (var shortcut in _shortcutList.Shortcuts.SelectMany(list => list.Properties.Where(s => s.Recommended)))
|
||||
{
|
||||
foreach (var shortcut in list.Properties)
|
||||
{
|
||||
if (shortcut.Recommended)
|
||||
{
|
||||
RecommendedListElement.Items.Add((ShortcutTemplateDataObject)shortcut);
|
||||
}
|
||||
}
|
||||
RecommendedListElement.Items.Add((ShortcutTemplateDataObject)shortcut);
|
||||
}
|
||||
|
||||
if (RecommendedListElement.Items.Count == 0)
|
||||
@@ -246,13 +254,13 @@ namespace ShortcutGuide
|
||||
{
|
||||
TaskbarLaunchShortcutsListElement.Items.Add((ShortcutTemplateDataObject)item);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
TaskbarLaunchShortcutsListElement.Visibility = Visibility.Collapsed;
|
||||
TaskbarLaunchShortcutsTitle.Visibility = Visibility.Collapsed;
|
||||
TaskbarLaunchShortcutsDescription.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
TaskbarLaunchShortcutsListElement.Visibility = Visibility.Collapsed;
|
||||
TaskbarLaunchShortcutsTitle.Visibility = Visibility.Collapsed;
|
||||
TaskbarLaunchShortcutsDescription.Visibility = Visibility.Collapsed;
|
||||
}
|
||||
|
||||
private string _searchFilter = string.Empty;
|
||||
@@ -278,26 +286,16 @@ namespace ShortcutGuide
|
||||
}
|
||||
|
||||
OverviewStackPanel.Visibility = Visibility.Collapsed;
|
||||
|
||||
foreach (var list in _shortcutList.Shortcuts)
|
||||
foreach (var shortcut in _shortcutList.Shortcuts.SelectMany(list => list.Properties.Where(s => s.Name.Contains(filter, StringComparison.InvariantCultureIgnoreCase))))
|
||||
{
|
||||
foreach (var shortcut in list.Properties)
|
||||
{
|
||||
if (shortcut.Name.Contains(filter, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut);
|
||||
}
|
||||
}
|
||||
ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var shortcut in _shortcutList.Shortcuts[int.Parse(CategorySelector.SelectedItem.Name, CultureInfo.InvariantCulture)].Properties)
|
||||
foreach (var shortcut in _shortcutList.Shortcuts[int.Parse(CategorySelector.SelectedItem.Name, CultureInfo.InvariantCulture)].Properties.Where(s => s.Name.Contains(filter, StringComparison.InvariantCultureIgnoreCase)))
|
||||
{
|
||||
if (shortcut.Name.Contains(filter, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut);
|
||||
}
|
||||
ShortcutListElement.Items.Add((ShortcutTemplateDataObject)shortcut);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user