[General]Reduce installer size by flattening application paths (#27451)

* Flatten everything and succeed build

* Figure out Settings assets

* Remove UseCommonOutputDirectory tag

* Proper settings app path

* [VCM] Fix assets location

* Fix some runtime paths

* [RegistryPreview]Use MRTCore specific pri file

* [Hosts]Use MRTCore specific pri file

* [Settings]Use MRTCore specific pri file

* [Peek]Use MRTCore specific pri file

* [FileLocksmith]Use MRTCore specific pri file

* [ScreenRuler]Use MRTCore specific pri file

* [PowerRename]Use MRTCore specific pri file

* [Peek]Move assets to own folder

* [FileLocksmith] Use own Assets path

* [Hosts]Use own assets folder

* [PowerRename]Use own assets dir

* [MeasureTool] Use its own assets folder

* [ImageResizer]Use its own assets path

* Fix spellcheck

* Fix tab instead of space in project files

* Normalize target frameworks and platforms

* Remove WINRT_NO_MAKE_DETECTION flag. No longer needed?

* Fix AOT and Hosts locations

* Fix Dll version differences on dependency

* Add Common.UI.csproj as refernce to fix dll versions

* Update ControlzEx to normalize dll versions

* Update System.Management version to 7.0.2

* Add GPOWrapper to Registry Preview to fix dll versions

* [PTRun]Reference Microsoft.Extensions.Hosting to fix dll versions

* Fix remaining output paths / dll version conflicts

* [KeyboardManager]Executables still on their own directories

* Fix Monaco paths

* WinAppSDK apps get to play outside again

* Enable VCM settings again

* Fix KBM Editor path again

* [Monaco]Set to own Assets dir

* Fix installer preamble; Fix publish. remove unneeded publishes

* Remove Hardlink functions

* Installer builds again (still needs work to work)

* Readd Monaco to spellcheck excludes

* Fix spellcheck and call publish.cmd again

* [Installer] Remove components that don't need own dirs

* [Installer] Refactor Power Launcher

* [Installer] Refactor Color Picker

* [Installer] Refactor Monaco assets

* [Installer]Generate File script no longer needs to remove files

* [Installer]Refactor FileLocksmith

* [Installer] Refactor Hosts

* [Installer]Refactor Image Resizer

* [Installer]Refactor MouseUtils

* [Installer]Refactor MWB

* [Installer]Refactor MeasureTool

* [Installer]Refactor Peek

* [Installer]Refactor PowerRename and registry fixes

* [Installer]Refactor RegistryPreview

* [Installer]Refactor ShortcutGuide

* [Installer]Refactor Settings

* [Installer]Clean up some unused stuff

* [Installer]Clean up stuff for user install

* [Installer]Fix WinUi3Apps wxs

* [Installer]Fix misplaced folders

* [Installer]Move x86 VCM dll to right path

* Fix monaco language list location

* [Installer]Fix VCM directory reference

* [CI]Fix signing

* [Installer] Fix resources folder for release CI

* [ci]Looks like we still ship NLog on PowerToys Run

* [Settings]Add dependency to avoid dll collision with Experimentation

* [RegistryPreview]Move XAML files to own path

* [RegistryPreview]Fix app icon

* [Hosts]Move XAML files to their own path

* [FileLocksmith]Move XAML files to their own path

* [Peek]Move XAML files to own path

* [ScreenRuler]Move XAML files to its own path

* [Settings]Move XAML to its own path

* [ColorPicker]Move Resources to Assets

* [ShortcutGuide]Move svgs to own Assets path

* [Awake]Move images to assets path

* [Runner]Remove debug checks for PowerToys Run assets

* [PTRun]Move images to its own assets path

* [ImageResizer]Icon for context menu on own assets path

* [PowerRename]Move ico to its own path

* Remove unneeded intermediary directories

* Remove further int dirs

* Move tests to its own output path

* Fix spellcheck

* spellcheck: remove warnings

* [CppAnalyzers]Ignore rule in a tool

* [CI]Check if all deps.json files reference same versions

* fix spellcheck

* [ci]Fix task identation

* [ci]Add script to guard against asset conflicts

* [ci]Add more deps.json audit steps in the release build

* Add xbf to spellcheck expects

* Fix typo in asset conflict check scripts

* Fix some more dependency conflicts

* Downgrade CsWinRT to have the same dll version as sdk

* [ci]Do a recursive check for every deps.json

* Fix spellcheck error inside comment

* [ci]Fix asset script error

* [ci]Name deps.json verify tasks a bit better

* [ci]Improve deps json verify script output

* [ci]Update WinRT version to the same running in CI

* Also upgrade CsWinRT in NOTICE.MD

* [PowerRename]Move XAML files to own path

* [Common]Fix Settings executable path

* [ci]Verify there's no xbf files in app directories

* [installer]Fix firewall path

* [Monaco]Move new files to their proper assets path

* [Monaco]Fix paths for new files after merge

* [Feedback]Removed unneeded build conditions

* [Feedback]Clear vcxproj direct reference to frameworks

* [Feedback]RunPlugins name to hold PTRun plugins

* [Feedback]Remove unneeded foreach

* [Feedback]Shortcut Guide svgs with ** in project file

* [Feedback]Fix spellcheck
This commit is contained in:
Jaime Bernardo
2023-07-20 00:12:46 +01:00
committed by GitHub
parent 1f44085e41
commit 864b862952
762 changed files with 2005 additions and 3118 deletions

View File

@@ -0,0 +1,72 @@
<Application
x:Class="Microsoft.PowerToys.Settings.UI.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
xmlns:labs="using:CommunityToolkit.Labs.WinUI"
xmlns:local="using:Microsoft.PowerToys.Settings.UI">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<XamlControlsResources xmlns="using:Microsoft.UI.Xaml.Controls" />
<ResourceDictionary Source="/SettingsXAML/Controls/KeyVisual/KeyVisual.xaml" />
<ResourceDictionary Source="/SettingsXAML/Controls/IsEnabledTextBlock/IsEnabledTextBlock.xaml" />
<ResourceDictionary Source="/SettingsXAML/Styles/TextBlock.xaml" />
<ResourceDictionary Source="/SettingsXAML/Styles/Button.xaml" />
<ResourceDictionary Source="/SettingsXAML/Themes/Colors.xaml" />
<ResourceDictionary Source="/SettingsXAML/Themes/Generic.xaml" />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
<!-- Converters -->
<converters:BoolToVisibilityConverter
x:Key="ReverseBoolToVisibilityConverter"
FalseValue="Visible"
TrueValue="Collapsed" />
<converters:BoolToVisibilityConverter
x:Key="BoolToVisibilityConverter"
FalseValue="Collapsed"
TrueValue="Visible" />
<converters:BoolToObjectConverter
x:Key="BoolToComboBoxIndexConverter"
FalseValue="0"
TrueValue="1" />
<converters:BoolToObjectConverter
x:Key="ReverseBoolToComboBoxIndexConverter"
FalseValue="1"
TrueValue="0" />
<converters:StringFormatConverter x:Key="StringFormatConverter" />
<converters:BoolNegationConverter x:Key="BoolNegationConverter" />
<!-- Overrides -->
<Thickness x:Key="InfoBarIconMargin">6,16,16,16</Thickness>
<Thickness x:Key="InfoBarContentRootPadding">16,0,0,0</Thickness>
<x:Double x:Key="SettingActionControlMinWidth">240</x:Double>
<Style TargetType="ListViewItem">
<Setter Property="Margin" Value="0,0,0,2" />
<Setter Property="Padding" Value="0,0,0,0" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="IsTabStop" Value="False" />
</Style>
<Style BasedOn="{StaticResource DefaultCheckBoxStyle}" TargetType="controls:CheckBoxWithDescriptionControl" />
<!-- Other app resources here -->
<SolidColorBrush x:Key="WindowCaptionBackground" Color="Transparent" />
<SolidColorBrush x:Key="WindowCaptionBackgroundDisabled" Color="Transparent" />
<TransitionCollection x:Key="SettingsCardsAnimations">
<EntranceThemeTransition FromVerticalOffset="50" />
<!-- Animates cards when loaded -->
<RepositionThemeTransition IsStaggeringEnabled="False" />
<!-- Smoothly animates individual cards upon whenever Expanders are expanded/collapsed -->
</TransitionCollection>
</ResourceDictionary>
</Application.Resources>
</Application>

View File

@@ -0,0 +1,409 @@
// 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.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Threading.Tasks;
using interop;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Xaml;
using Windows.UI.Popups;
using WinRT.Interop;
using WinUIEx;
namespace Microsoft.PowerToys.Settings.UI
{
/// <summary>
/// Provides application-specific behavior to supplement the default Application class.
/// </summary>
public partial class App : Application
{
private enum Arguments
{
PTPipeName = 1,
SettingsPipeName,
PTPid,
Theme, // used in the old settings
ElevatedStatus,
IsUserAdmin,
ShowOobeWindow,
ShowScoobeWindow,
ShowFlyout,
ContainsSettingsWindow,
ContainsFlyoutPosition,
}
// Quantity of arguments
private const int RequiredArgumentsQty = 12;
// Create an instance of the IPC wrapper.
private static TwoWayPipeMessageIPCManaged ipcmanager;
public static bool IsElevated { get; set; }
public static bool IsUserAnAdmin { get; set; }
public static int PowerToysPID { get; set; }
public bool ShowOobe { get; set; }
public bool ShowFlyout { get; set; }
public bool ShowScoobe { get; set; }
public Type StartupPage { get; set; } = typeof(Views.GeneralPage);
public static Action<string> IPCMessageReceivedCallback { get; set; }
private static bool loggedImmersiveDarkException;
/// <summary>
/// Initializes a new instance of the <see cref="App"/> class.
/// Initializes the singleton application object. This is the first line of authored code
/// executed, and as such is the logical equivalent of main() or WinMain().
/// </summary>
public App()
{
Logger.InitializeLogger("\\Settings\\Logs");
this.InitializeComponent();
}
public static void OpenSettingsWindow(Type type = null, bool ensurePageIsSelected = false)
{
if (settingsWindow == null)
{
settingsWindow = new MainWindow(IsDarkTheme());
}
settingsWindow.Activate();
if (type != null)
{
settingsWindow.NavigateToSection(type);
}
if (ensurePageIsSelected)
{
settingsWindow.EnsurePageIsSelected();
}
}
/// <summary>
/// Invoked when the application is launched normally by the end user. Other entry points
/// will be used such as when the application is launched to open a specific file.
/// </summary>
/// <param name="args">Details about the launch request and process.</param>
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
{
var cmdArgs = Environment.GetCommandLineArgs();
var isDark = IsDarkTheme();
if (cmdArgs != null && cmdArgs.Length >= RequiredArgumentsQty)
{
// Skip the first argument which is prepended when launched by explorer
if (cmdArgs[0].EndsWith(".dll", StringComparison.InvariantCultureIgnoreCase) && cmdArgs[1].EndsWith(".exe", StringComparison.InvariantCultureIgnoreCase) && (cmdArgs.Length >= RequiredArgumentsQty + 1))
{
cmdArgs = cmdArgs.Skip(1).ToArray();
}
_ = int.TryParse(cmdArgs[(int)Arguments.PTPid], out int powerToysPID);
PowerToysPID = powerToysPID;
IsElevated = cmdArgs[(int)Arguments.ElevatedStatus] == "true";
IsUserAnAdmin = cmdArgs[(int)Arguments.IsUserAdmin] == "true";
ShowOobe = cmdArgs[(int)Arguments.ShowOobeWindow] == "true";
ShowScoobe = cmdArgs[(int)Arguments.ShowScoobeWindow] == "true";
ShowFlyout = cmdArgs[(int)Arguments.ShowFlyout] == "true";
bool containsSettingsWindow = cmdArgs[(int)Arguments.ContainsSettingsWindow] == "true";
bool containsFlyoutPosition = cmdArgs[(int)Arguments.ContainsFlyoutPosition] == "true";
// To keep track of variable arguments
int currentArgumentIndex = RequiredArgumentsQty;
if (containsSettingsWindow)
{
// Open specific window
StartupPage = GetPage(cmdArgs[currentArgumentIndex]);
currentArgumentIndex++;
}
int flyout_x = 0;
int flyout_y = 0;
if (containsFlyoutPosition)
{
// get the flyout position arguments
_ = int.TryParse(cmdArgs[currentArgumentIndex++], out flyout_x);
_ = int.TryParse(cmdArgs[currentArgumentIndex++], out flyout_y);
}
RunnerHelper.WaitForPowerToysRunner(PowerToysPID, () =>
{
Environment.Exit(0);
});
ipcmanager = new TwoWayPipeMessageIPCManaged(cmdArgs[(int)Arguments.SettingsPipeName], cmdArgs[(int)Arguments.PTPipeName], (string message) =>
{
if (IPCMessageReceivedCallback != null && message.Length > 0)
{
IPCMessageReceivedCallback(message);
}
});
ipcmanager.Start();
if (!ShowOobe && !ShowScoobe && !ShowFlyout)
{
settingsWindow = new MainWindow(isDark);
settingsWindow.Activate();
settingsWindow.ExtendsContentIntoTitleBar = true;
settingsWindow.NavigateToSection(StartupPage);
// https://github.com/microsoft/microsoft-ui-xaml/issues/7595 - Activate doesn't bring window to the foreground
// Need to call SetForegroundWindow to actually gain focus.
Utils.BecomeForegroundWindow(settingsWindow.GetWindowHandle());
}
else
{
// Create the Settings window hidden so that it's fully initialized and
// it will be ready to receive the notification if the user opens
// the Settings from the tray icon.
settingsWindow = new MainWindow(isDark, true);
if (ShowOobe)
{
PowerToysTelemetry.Log.WriteEvent(new OobeStartedEvent());
OobeWindow oobeWindow = new OobeWindow(OOBE.Enums.PowerToysModules.Overview, isDark);
oobeWindow.Activate();
oobeWindow.ExtendsContentIntoTitleBar = true;
SetOobeWindow(oobeWindow);
}
else if (ShowScoobe)
{
PowerToysTelemetry.Log.WriteEvent(new ScoobeStartedEvent());
OobeWindow scoobeWindow = new OobeWindow(OOBE.Enums.PowerToysModules.WhatsNew, isDark);
scoobeWindow.Activate();
scoobeWindow.ExtendsContentIntoTitleBar = true;
SetOobeWindow(scoobeWindow);
}
else if (ShowFlyout)
{
POINT? p = null;
if (containsFlyoutPosition)
{
p = new POINT(flyout_x, flyout_y);
}
ShellPage.OpenFlyoutCallback(p);
}
}
}
else
{
// For debugging purposes
// Window is also needed to show MessageDialog
settingsWindow = new MainWindow(isDark);
settingsWindow.ExtendsContentIntoTitleBar = true;
settingsWindow.Activate();
settingsWindow.NavigateToSection(StartupPage);
#if !DEBUG
ShowMessageDialogAndExit("The application cannot be run as a standalone process. Please start the application through the runner.", "Forbidden");
#else
ShowMessageDialog("The application cannot be run as a standalone process. Please start the application through the runner.", "Forbidden");
#endif
}
}
#if !DEBUG
private async void ShowMessageDialogAndExit(string content, string title = null)
#else
private async void ShowMessageDialog(string content, string title = null)
#endif
{
await ShowDialogAsync(content, title);
#if !DEBUG
this.Exit();
#endif
}
public static Task<IUICommand> ShowDialogAsync(string content, string title = null)
{
var dialog = new MessageDialog(content, title ?? string.Empty);
var handle = NativeMethods.GetActiveWindow();
if (handle == IntPtr.Zero)
{
throw new InvalidOperationException();
}
InitializeWithWindow.Initialize(dialog, handle);
return dialog.ShowAsync().AsTask<IUICommand>();
}
public static TwoWayPipeMessageIPCManaged GetTwoWayIPCManager()
{
return ipcmanager;
}
public static ElementTheme SelectedTheme()
{
switch (SettingsRepository<GeneralSettings>.GetInstance(settingsUtils).SettingsConfig.Theme.ToUpper(CultureInfo.InvariantCulture))
{
case "DARK": return ElementTheme.Dark;
case "LIGHT": return ElementTheme.Light;
default: return ElementTheme.Default;
}
}
public static bool IsDarkTheme()
{
var selectedTheme = SelectedTheme();
return selectedTheme == ElementTheme.Dark || (selectedTheme == ElementTheme.Default && ThemeHelpers.GetAppTheme() == AppTheme.Dark);
}
public static void HandleThemeChange()
{
try
{
bool isDark = IsDarkTheme();
if (settingsWindow != null)
{
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(settingsWindow);
ThemeHelpers.SetImmersiveDarkMode(hWnd, isDark);
SetContentTheme(isDark, settingsWindow);
}
if (oobeWindow != null)
{
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(oobeWindow);
ThemeHelpers.SetImmersiveDarkMode(hWnd, isDark);
SetContentTheme(isDark, oobeWindow);
}
if (SelectedTheme() == ElementTheme.Default)
{
themeListener = new ThemeListener();
themeListener.ThemeChanged += (_) => HandleThemeChange();
}
else if (themeListener != null)
{
themeListener.Dispose();
themeListener = null;
}
}
catch (Exception e)
{
if (!loggedImmersiveDarkException)
{
Logger.LogError($"HandleThemeChange exception. Please install .NET 4.", e);
loggedImmersiveDarkException = true;
}
}
}
public static void SetContentTheme(bool isDark, WindowEx window)
{
var rootGrid = (FrameworkElement)window.Content;
if (rootGrid != null)
{
if (isDark)
{
rootGrid.RequestedTheme = ElementTheme.Dark;
}
else
{
rootGrid.RequestedTheme = ElementTheme.Light;
}
}
}
private static ISettingsUtils settingsUtils = new SettingsUtils();
private static MainWindow settingsWindow;
private static OobeWindow oobeWindow;
private static FlyoutWindow flyoutWindow;
private static ThemeListener themeListener;
public static void ClearSettingsWindow()
{
settingsWindow = null;
}
public static MainWindow GetSettingsWindow()
{
return settingsWindow;
}
public static OobeWindow GetOobeWindow()
{
return oobeWindow;
}
public static FlyoutWindow GetFlyoutWindow()
{
return flyoutWindow;
}
public static void SetOobeWindow(OobeWindow window)
{
oobeWindow = window;
}
public static void SetFlyoutWindow(FlyoutWindow window)
{
flyoutWindow = window;
}
public static void ClearOobeWindow()
{
oobeWindow = null;
}
public static void ClearFlyoutWindow()
{
flyoutWindow = null;
}
public static Type GetPage(string settingWindow)
{
switch (settingWindow)
{
case "Overview": return typeof(GeneralPage);
case "AlwaysOnTop": return typeof(AlwaysOnTopPage);
case "Awake": return typeof(AwakePage);
case "ColorPicker": return typeof(ColorPickerPage);
case "FancyZones": return typeof(FancyZonesPage);
case "FileLocksmith": return typeof(FileLocksmithPage);
case "Run": return typeof(PowerLauncherPage);
case "ImageResizer": return typeof(ImageResizerPage);
case "KBM": return typeof(KeyboardManagerPage);
case "MouseUtils": return typeof(MouseUtilsPage);
case "MouseWithoutBorders": return typeof(MouseWithoutBordersPage);
case "PowerRename": return typeof(PowerRenamePage);
case "QuickAccent": return typeof(PowerAccentPage);
case "FileExplorer": return typeof(PowerPreviewPage);
case "ShortcutGuide": return typeof(ShortcutGuidePage);
case "PowerOCR": return typeof(PowerOcrPage);
case "VideoConference": return typeof(VideoConferencePage);
case "MeasureTool": return typeof(MeasureToolPage);
case "Hosts": return typeof(HostsPage);
case "RegistryPreview": return typeof(RegistryPreviewPage);
case "PastePlain": return typeof(PastePlainPage);
case "Peek": return typeof(PeekPage);
default:
// Fallback to general
Debug.Assert(false, "Unexpected SettingsWindow argument value");
return typeof(GeneralPage);
}
}
}
}

View File

@@ -0,0 +1,76 @@
// 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.ComponentModel;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public class CheckBoxWithDescriptionControl : CheckBox
{
private CheckBoxWithDescriptionControl _checkBoxSubTextControl;
public CheckBoxWithDescriptionControl()
{
_checkBoxSubTextControl = (CheckBoxWithDescriptionControl)this;
this.Loaded += CheckBoxSubTextControl_Loaded;
}
protected override void OnApplyTemplate()
{
Update();
base.OnApplyTemplate();
}
private void Update()
{
if (!string.IsNullOrEmpty(Header))
{
AutomationProperties.SetName(this, Header);
}
}
private void CheckBoxSubTextControl_Loaded(object sender, RoutedEventArgs e)
{
StackPanel panel = new StackPanel() { Orientation = Orientation.Vertical };
panel.Children.Add(new TextBlock() { Text = Header, TextWrapping = TextWrapping.WrapWholeWords });
// Add text box only if the description is not empty. Required for additional plugin options.
if (!string.IsNullOrWhiteSpace(Description))
{
panel.Children.Add(new IsEnabledTextBlock() { Style = (Style)App.Current.Resources["SecondaryIsEnabledTextBlockStyle"], Text = Description });
}
_checkBoxSubTextControl.Content = panel;
}
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
"Header",
typeof(string),
typeof(CheckBoxWithDescriptionControl),
new PropertyMetadata(default(string)));
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
"Description",
typeof(string),
typeof(CheckBoxWithDescriptionControl),
new PropertyMetadata(default(string)));
[Localizable(true)]
public string Header
{
get => (string)GetValue(HeaderProperty);
set => SetValue(HeaderProperty, value);
}
[Localizable(true)]
public string Description
{
get => (string)GetValue(DescriptionProperty);
set => SetValue(DescriptionProperty, value);
}
}
}

View File

@@ -0,0 +1,119 @@
<!-- Copyright (c) Microsoft Corporation. All rights reserved. -->
<!-- Licensed under the MIT License. See LICENSE in the project root for license information. -->
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.Controls.ColorFormatEditor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:CommunityToolkit="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:converters="using:Microsoft.PowerToys.Settings.UI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<UserControl.Resources>
<converters:ColorFormatConverter x:Key="ColorFormatConverter" />
<DataTemplate x:Key="FormatParameterTemplate" x:DataType="local:ColorFormatParameter">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="34" />
<ColumnDefinition Width="110" />
</Grid.ColumnDefinitions>
<TextBlock
FontWeight="SemiBold"
IsTextSelectionEnabled="True"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind Parameter}" />
<TextBlock
Grid.Column="1"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind Description}"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap" />
</Grid>
</DataTemplate>
<DataTemplate x:Key="ColorParameterTemplate" x:DataType="local:ColorFormatParameter">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="18" />
<ColumnDefinition Width="186" />
</Grid.ColumnDefinitions>
<TextBlock
FontWeight="SemiBold"
IsTextSelectionEnabled="True"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind Parameter}" />
<TextBlock
Grid.Column="1"
VerticalAlignment="Center"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind Description}"
TextTrimming="CharacterEllipsis"
TextWrapping="NoWrap" />
</Grid>
</DataTemplate>
<ItemsPanelTemplate x:Key="ItemPanelTemplate">
<CommunityToolkit:WrapPanel
HorizontalSpacing="20"
Orientation="Horizontal"
VerticalSpacing="4" />
</ItemsPanelTemplate>
</UserControl.Resources>
<Grid>
<StackPanel Spacing="12">
<TextBox
x:Name="NewColorName"
x:Uid="NewColorName"
IsSpellCheckEnabled="False"
Text="{Binding Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
TextChanged="NewColorName_TextChanged" />
<TextBox
x:Name="NewColorFormatTextBox"
x:Uid="NewColorFormat"
IsSpellCheckEnabled="False"
Text="{Binding Format, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
TextChanged="NewColorFormatTextBox_TextChanged" />
<TextBlock
Margin="12,0,0,0"
FontWeight="SemiBold"
Foreground="{ThemeResource AccentTextFillColorPrimaryBrush}"
Style="{StaticResource CaptionTextBlockStyle}"
Text="{Binding ElementName=NewColorFormatTextBox, Path=Text, Converter={StaticResource ColorFormatConverter}}" />
<TextBlock
x:Uid="ColorFormatEditorHelpline1"
Margin="0,12,0,0"
Style="{StaticResource CaptionTextBlockStyle}" />
<ItemsControl
x:Name="ParametersItemsControl"
ItemTemplate="{StaticResource FormatParameterTemplate}"
ItemsPanel="{StaticResource ItemPanelTemplate}" />
<TextBlock
x:Uid="ColorFormatEditorHelpline2"
Margin="0,12,0,0"
VerticalAlignment="Bottom"
Style="{StaticResource CaptionTextBlockStyle}" />
<ItemsControl
x:Name="ColorParametersItemsControl"
ItemTemplate="{StaticResource ColorParameterTemplate}"
ItemsPanel="{StaticResource ItemPanelTemplate}" />
<TextBlock
x:Uid="ColorFormatEditorHelpline3"
VerticalAlignment="Bottom"
Style="{StaticResource CaptionTextBlockStyle}" />
</StackPanel>
</Grid>
</UserControl>

View File

@@ -0,0 +1,101 @@
// 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.ComponentModel;
using System.Security.Cryptography;
using System.Windows.Input;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.UI.Xaml.Controls;
using Microsoft.Windows.ApplicationModel.Resources;
using Windows.System;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public sealed partial class ColorFormatEditor : UserControl
{
public ColorFormatEditor()
{
this.InitializeComponent();
LoadParameters();
}
public void LoadParameters()
{
ResourceLoader resourceLoader = ResourceLoaderInstance.ResourceLoader;
ParametersItemsControl.ItemsSource = new List<ColorFormatParameter>
{
new ColorFormatParameter() { Parameter = "%Re", Description = resourceLoader.GetString("Help_red") },
new ColorFormatParameter() { Parameter = "%Gr", Description = resourceLoader.GetString("Help_green") },
new ColorFormatParameter() { Parameter = "%Bl", Description = resourceLoader.GetString("Help_blue") },
new ColorFormatParameter() { Parameter = "%Al", Description = resourceLoader.GetString("Help_alpha") },
new ColorFormatParameter() { Parameter = "%Cy", Description = resourceLoader.GetString("Help_cyan") },
new ColorFormatParameter() { Parameter = "%Ma", Description = resourceLoader.GetString("Help_magenta") },
new ColorFormatParameter() { Parameter = "%Ye", Description = resourceLoader.GetString("Help_yellow") },
new ColorFormatParameter() { Parameter = "%Bk", Description = resourceLoader.GetString("Help_black_key") },
new ColorFormatParameter() { Parameter = "%Hu", Description = resourceLoader.GetString("Help_hue") },
new ColorFormatParameter() { Parameter = "%Si", Description = resourceLoader.GetString("Help_saturationI") },
new ColorFormatParameter() { Parameter = "%Sl", Description = resourceLoader.GetString("Help_saturationL") },
new ColorFormatParameter() { Parameter = "%Sb", Description = resourceLoader.GetString("Help_saturationB") },
new ColorFormatParameter() { Parameter = "%Br", Description = resourceLoader.GetString("Help_brightness") },
new ColorFormatParameter() { Parameter = "%In", Description = resourceLoader.GetString("Help_intensity") },
new ColorFormatParameter() { Parameter = "%Hn", Description = resourceLoader.GetString("Help_hueNat") },
new ColorFormatParameter() { Parameter = "%Ll", Description = resourceLoader.GetString("Help_lightnessNat") },
new ColorFormatParameter() { Parameter = "%Lc", Description = resourceLoader.GetString("Help_lightnessCIE") },
new ColorFormatParameter() { Parameter = "%Va", Description = resourceLoader.GetString("Help_value") },
new ColorFormatParameter() { Parameter = "%Wh", Description = resourceLoader.GetString("Help_whiteness") },
new ColorFormatParameter() { Parameter = "%Bn", Description = resourceLoader.GetString("Help_blackness") },
new ColorFormatParameter() { Parameter = "%Ca", Description = resourceLoader.GetString("Help_chromaticityA") },
new ColorFormatParameter() { Parameter = "%Cb", Description = resourceLoader.GetString("Help_chromaticityB") },
new ColorFormatParameter() { Parameter = "%Xv", Description = resourceLoader.GetString("Help_X_value") },
new ColorFormatParameter() { Parameter = "%Yv", Description = resourceLoader.GetString("Help_Y_value") },
new ColorFormatParameter() { Parameter = "%Zv", Description = resourceLoader.GetString("Help_Z_value") },
new ColorFormatParameter() { Parameter = "%Dv", Description = resourceLoader.GetString("Help_decimal_value_BGR") },
new ColorFormatParameter() { Parameter = "%Dr", Description = resourceLoader.GetString("Help_decimal_value_RGB") },
new ColorFormatParameter() { Parameter = "%Na", Description = resourceLoader.GetString("Help_color_name") },
};
ColorParametersItemsControl.ItemsSource = new List<ColorFormatParameter>
{
new ColorFormatParameter() { Parameter = "b", Description = resourceLoader.GetString("Help_byte") },
new ColorFormatParameter() { Parameter = "h", Description = resourceLoader.GetString("Help_hexL1") },
new ColorFormatParameter() { Parameter = "H", Description = resourceLoader.GetString("Help_hexU1") },
new ColorFormatParameter() { Parameter = "x", Description = resourceLoader.GetString("Help_hexL2") },
new ColorFormatParameter() { Parameter = "X", Description = resourceLoader.GetString("Help_hexU2") },
new ColorFormatParameter() { Parameter = "f", Description = resourceLoader.GetString("Help_floatWith") },
new ColorFormatParameter() { Parameter = "F", Description = resourceLoader.GetString("Help_floatWithout") },
};
}
private void NewColorName_TextChanged(object sender, TextChangedEventArgs e)
{
OnPropertyChanged();
}
private void NewColorFormatTextBox_TextChanged(object sender, TextChangedEventArgs e)
{
OnPropertyChanged();
}
public event EventHandler PropertyChanged;
private void OnPropertyChanged()
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs("PropertyChanged"));
}
}
#pragma warning disable SA1402 // File may only contain a single type
public class ColorFormatParameter
#pragma warning restore SA1402 // File may only contain a single type
{
public string Parameter { get; set; }
public string Description { get; set; }
}
}

View File

@@ -0,0 +1,42 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.Controls.ColorPickerButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
<Grid>
<!--TODO(stefan): ToDisplayName is no longer available in ColorHelper
<DropDownButton Padding="4,4,8,4" AutomationProperties.FullDescription="{x:Bind clr:ColorHelper.ToDisplayName(SelectedColor), Mode=OneWay }">
-->
<DropDownButton Padding="4,4,8,4">
<Border
x:Name="ColorPreviewBorder"
Width="48"
Height="24"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="{ThemeResource ControlCornerRadius}">
<Border.Background>
<SolidColorBrush Color="{x:Bind SelectedColor, Mode=OneWay}" />
</Border.Background>
</Border>
<DropDownButton.Flyout>
<Flyout>
<ColorPicker
IsAlphaEnabled="False"
IsAlphaSliderVisible="False"
IsAlphaTextInputVisible="False"
IsColorChannelTextInputVisible="True"
IsColorSliderVisible="True"
IsHexInputVisible="True"
Color="{x:Bind SelectedColor, Mode=TwoWay}" />
</Flyout>
</DropDownButton.Flyout>
</DropDownButton>
</Grid>
</UserControl>

View File

@@ -0,0 +1,59 @@
// 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.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Windows.UI;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public sealed partial class ColorPickerButton : UserControl
{
private Color _selectedColor;
public Color SelectedColor
{
get
{
return _selectedColor;
}
set
{
if (_selectedColor != value)
{
_selectedColor = value;
SetValue(SelectedColorProperty, value);
}
}
}
public static readonly DependencyProperty SelectedColorProperty = DependencyProperty.Register("SelectedColor", typeof(Color), typeof(ColorPickerButton), new PropertyMetadata(null));
public ColorPickerButton()
{
this.InitializeComponent();
IsEnabledChanged -= ColorPickerButton_IsEnabledChanged;
SetEnabledState();
IsEnabledChanged += ColorPickerButton_IsEnabledChanged;
}
private void ColorPickerButton_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
SetEnabledState();
}
private void SetEnabledState()
{
if (this.IsEnabled)
{
ColorPreviewBorder.Opacity = 1;
}
else
{
ColorPreviewBorder.Opacity = 0.2;
}
}
}
}

View File

@@ -0,0 +1,132 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.Controls.FancyZonesPreviewControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Loaded="FancyZonesPreviewControl_Loaded"
RequestedTheme="Dark"
mc:Ignorable="d">
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush
x:Key="SolidBackgroundBrush"
Color="Black" />
<SolidColorBrush
x:Key="SolidZoneNumberBrush"
Color="White" />
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<SolidColorBrush
x:Key="SolidBackgroundBrush"
Color="White" />
<SolidColorBrush
x:Key="SolidZoneNumberBrush"
Color="Black" />
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush
x:Key="SolidBackgroundBrush"
Color="Black" />
<SolidColorBrush
x:Key="SolidZoneNumberBrush"
Color="White" />
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
<SolidColorBrush
x:Key="DefaultAccentBrush"
Color="{ThemeResource SystemAccentColor}" />
<SolidColorBrush
x:Key="DefaultBorderBrush"
Color="{ThemeResource SystemAccentColor}" />
</ResourceDictionary>
</UserControl.Resources>
<Grid
x:Name="RootGrid"
MinWidth="170"
MinHeight="86"
HorizontalAlignment="Center"
Background="Black"
BorderBrush="Black"
BorderThickness="8"
CornerRadius="12">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Border
Grid.RowSpan="2"
Grid.ColumnSpan="2"
Opacity="0.8"
CornerRadius="4">
<Image
AutomationProperties.AccessibilityView="Raw"
Source="{x:Bind WallpaperPath, Mode=OneWay}"
Stretch="UniformToFill" />
</Border>
<Border
x:Name="Zone1"
Grid.RowSpan="2"
BorderThickness="1"
Margin="4,4,2,4"
CornerRadius="2"
Background="{ThemeResource SystemControlAcrylicElementBrush}">
<TextBlock
x:Name="Zone1Number"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="SemiBold"
Text="1"
Visibility="{x:Bind ShowZoneNumber, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
</Border>
<Border
x:Name="Zone2"
Grid.Column="1"
BorderThickness="1"
Margin="2,4,4,2"
CornerRadius="2"
Background="{ThemeResource SystemControlAcrylicElementBrush}">
<TextBlock
x:Name="Zone2Number"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="SemiBold"
Text="2"
Visibility="{x:Bind ShowZoneNumber, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
</Border>
<Border
x:Name="Zone3"
Grid.Row="1"
Grid.Column="1"
BorderThickness="1"
Margin="2,2,4,4"
CornerRadius="2"
Background="{ThemeResource SystemControlAcrylicElementBrush}">
<TextBlock
x:Name="Zone3Number"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="SemiBold"
Text="3"
Visibility="{x:Bind ShowZoneNumber, Mode=OneWay, Converter={StaticResource BoolToVisibilityConverter}}" />
</Border>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Target="RootGrid.Opacity" Value="0.4" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</UserControl>

View File

@@ -0,0 +1,160 @@
// 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.ComponentModel;
using System.IO;
using System.Text;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media;
using Windows.UI;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public sealed partial class FancyZonesPreviewControl : UserControl
{
public FancyZonesPreviewControl()
{
this.InitializeComponent();
try
{
var wallpaperPathBuilder = new StringBuilder(260);
NativeMethods.SystemParametersInfo(NativeMethods.SPI_GETDESKWALLPAPER, wallpaperPathBuilder.Capacity, wallpaperPathBuilder, 0);
var wallpaperPath = wallpaperPathBuilder.ToString();
if (File.Exists(wallpaperPath))
{
WallpaperPath = wallpaperPath;
}
}
catch (Win32Exception)
{
}
}
private void FancyZonesPreviewControl_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
SetEnabledState();
}
public bool IsSystemTheme
{
get { return (bool)GetValue(IsSystemThemeProperty); }
set { SetValue(IsSystemThemeProperty, value); }
}
public static readonly DependencyProperty IsSystemThemeProperty = DependencyProperty.Register("IsSystemTheme", typeof(bool), typeof(FancyZonesPreviewControl), new PropertyMetadata(default(bool), OnPropertyChanged));
public string WallpaperPath
{
get { return (string)GetValue(WallpaperPathProperty); }
set { SetValue(WallpaperPathProperty, value); }
}
public static readonly DependencyProperty WallpaperPathProperty = DependencyProperty.Register("WallpaperPath", typeof(string), typeof(FancyZonesPreviewControl), new PropertyMetadata("ms-appx:///Assets/Settings/Modules/Wallpaper.png"));
public Color CustomBorderColor
{
get { return (Color)GetValue(CustomBorderColorProperty); }
set { SetValue(CustomBorderColorProperty, value); }
}
public static readonly DependencyProperty CustomBorderColorProperty = DependencyProperty.Register("CustomBorderColor", typeof(Color), typeof(FancyZonesPreviewControl), new PropertyMetadata(null, OnPropertyChanged));
public Color CustomInActiveColor
{
get { return (Color)GetValue(CustomInActiveColorProperty); }
set { SetValue(CustomInActiveColorProperty, value); }
}
public static readonly DependencyProperty CustomInActiveColorProperty = DependencyProperty.Register("CustomInActiveColor", typeof(Color), typeof(FancyZonesPreviewControl), new PropertyMetadata(null, OnPropertyChanged));
public Color CustomHighlightColor
{
get { return (Color)GetValue(CustomHighlightColorProperty); }
set { SetValue(CustomHighlightColorProperty, value); }
}
public static readonly DependencyProperty CustomHighlightColorProperty = DependencyProperty.Register("CustomHighlightColor", typeof(Color), typeof(FancyZonesPreviewControl), new PropertyMetadata(null, OnPropertyChanged));
public Color CustomNumberColor
{
get { return (Color)GetValue(CustomNumberColorProperty); }
set { SetValue(CustomNumberColorProperty, value); }
}
public static readonly DependencyProperty CustomNumberColorProperty = DependencyProperty.Register("CustomNumberColor", typeof(Color), typeof(FancyZonesPreviewControl), new PropertyMetadata(null, OnPropertyChanged));
public bool ShowZoneNumber
{
get { return (bool)GetValue(ShowZoneNumberProperty); }
set { SetValue(ShowZoneNumberProperty, value); }
}
public static readonly DependencyProperty ShowZoneNumberProperty = DependencyProperty.Register("ShowZoneNumber", typeof(bool), typeof(FancyZonesPreviewControl), new PropertyMetadata(default(bool), OnPropertyChanged));
public double HighlightOpacity
{
get { return (double)GetValue(HighlightOpacityProperty); }
set { SetValue(HighlightOpacityProperty, value); }
}
public static readonly DependencyProperty HighlightOpacityProperty = DependencyProperty.Register("CustomHighlightColor", typeof(double), typeof(FancyZonesPreviewControl), new PropertyMetadata(1.0, OnPropertyChanged));
private static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((FancyZonesPreviewControl)d).Update();
}
private SolidColorBrush highlightBrush;
private SolidColorBrush inActiveBrush;
private SolidColorBrush borderBrush;
private SolidColorBrush numberBrush;
private void Update()
{
if (!IsSystemTheme)
{
highlightBrush = new SolidColorBrush(CustomHighlightColor);
inActiveBrush = new SolidColorBrush(CustomInActiveColor);
borderBrush = new SolidColorBrush(CustomBorderColor);
numberBrush = new SolidColorBrush(CustomNumberColor);
}
else
{
highlightBrush = (SolidColorBrush)this.Resources["DefaultAccentBrush"];
inActiveBrush = (SolidColorBrush)this.Resources["SolidBackgroundBrush"];
borderBrush = (SolidColorBrush)this.Resources["DefaultBorderBrush"];
numberBrush = (SolidColorBrush)this.Resources["SolidZoneNumberBrush"];
}
highlightBrush.Opacity = HighlightOpacity / 100;
inActiveBrush.Opacity = HighlightOpacity / 100;
Zone1.Background = highlightBrush;
Zone2.Background = inActiveBrush;
Zone3.Background = inActiveBrush;
Zone1.BorderBrush = borderBrush;
Zone2.BorderBrush = borderBrush;
Zone3.BorderBrush = borderBrush;
Zone1Number.Foreground = numberBrush;
Zone2Number.Foreground = numberBrush;
Zone3Number.Foreground = numberBrush;
}
private void SetEnabledState()
{
VisualStateManager.GoToState(this, IsEnabled ? "Normal" : "Disabled", true);
}
private void FancyZonesPreviewControl_Loaded(object sender, RoutedEventArgs e)
{
IsEnabledChanged -= FancyZonesPreviewControl_IsEnabledChanged;
SetEnabledState();
IsEnabledChanged += FancyZonesPreviewControl_IsEnabledChanged;
}
}
}

View File

@@ -0,0 +1,43 @@
// 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 CommunityToolkit.Labs.WinUI;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Controls.Primitives;
using WinUIEx;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public partial class FlyoutMenuButton : Button
{
/// <summary>
/// The backing <see cref="DependencyProperty"/> for the <see cref="Icon"/> property.
/// </summary>
public static readonly DependencyProperty IconProperty = DependencyProperty.Register(
nameof(Icon),
typeof(object),
typeof(FlyoutMenuButton),
new PropertyMetadata(defaultValue: null));
/// <summary>
/// Gets or sets the icon.
/// </summary>
public object Icon
{
get => (object)GetValue(IconProperty);
set => SetValue(IconProperty, value);
}
public FlyoutMenuButton()
{
this.DefaultStyleKey = typeof(FlyoutMenuButton);
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
}
}
}

View File

@@ -0,0 +1,104 @@
<!-- Copyright (c) Microsoft Corporation and Contributors. -->
<!-- Licensed under the MIT License. -->
<ResourceDictionary
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">
<Style BasedOn="{StaticResource DefaultFlyoutMenuButtonStyle}" TargetType="local:FlyoutMenuButton" />
<Style x:Key="DefaultFlyoutMenuButtonStyle" TargetType="local:FlyoutMenuButton">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="Width" Value="116" />
<Setter Property="Height" Value="84" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="FocusVisualMargin" Value="-3" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:FlyoutMenuButton">
<Grid
x:Name="RootGrid"
Width="{TemplateBinding Width}"
Height="{TemplateBinding Height}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Background="Transparent"
BackgroundSizing="InnerBorderEdge"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid.BackgroundTransition>
<BrushTransition Duration="0:0:0.083" />
</Grid.BackgroundTransition>
<ContentPresenter
x:Name="ContentPresenter"
Margin="0,52,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Content="{TemplateBinding Content}" />
<ContentPresenter
x:Name="IconPresenter"
Width="32"
Margin="0,12,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Top"
Content="{TemplateBinding Icon}"
RenderTransformOrigin="0.5, 0.5">
<ContentPresenter.RenderTransform>
<CompositeTransform />
</ContentPresenter.RenderTransform>
</ContentPresenter>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ControlFillColorDefaultBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="IconPresenter" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleX)">
<SplineDoubleKeyFrame
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFastAnimationDuration}"
Value="0.86" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="IconPresenter" Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.ScaleY)">
<SplineDoubleKeyFrame
KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFastAnimationDuration}"
Value="0.86" />
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="RootGrid" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ControlFillColorDefaultBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource ButtonForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,51 @@
// 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.ComponentModel;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
[TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
public class IsEnabledTextBlock : Control
{
public IsEnabledTextBlock()
{
this.DefaultStyleKey = typeof(IsEnabledTextBlock);
}
protected override void OnApplyTemplate()
{
IsEnabledChanged -= IsEnabledTextBlock_IsEnabledChanged;
SetEnabledState();
IsEnabledChanged += IsEnabledTextBlock_IsEnabledChanged;
base.OnApplyTemplate();
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register(
"Text",
typeof(string),
typeof(IsEnabledTextBlock),
null);
[Localizable(true)]
public string Text
{
get => (string)GetValue(TextProperty);
set => SetValue(TextProperty, value);
}
private void IsEnabledTextBlock_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
SetEnabledState();
}
private void SetEnabledState()
{
VisualStateManager.GoToState(this, IsEnabled ? "Normal" : "Disabled", true);
}
}
}

View File

@@ -0,0 +1,42 @@
<ResourceDictionary
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">
<Style TargetType="local:IsEnabledTextBlock">
<Setter Property="Foreground" Value="{ThemeResource DefaultTextForegroundThemeBrush}" />
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:IsEnabledTextBlock">
<Grid>
<TextBlock
x:Name="Label"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
Foreground="{TemplateBinding Foreground}"
Text="{TemplateBinding Text}"
TextWrapping="WrapWholeWords" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Target="Label.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style
x:Key="SecondaryIsEnabledTextBlockStyle"
TargetType="local:IsEnabledTextBlock">
<Setter Property="Foreground" Value="{ThemeResource TextFillColorSecondaryBrush}" />
<Setter Property="FontSize" Value="{StaticResource SecondaryTextFontSize}" />
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,186 @@
// 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.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Markup;
using Windows.System;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
[TemplatePart(Name = KeyPresenter, Type = typeof(ContentPresenter))]
[TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Default", GroupName = "StateStates")]
[TemplateVisualState(Name = "Error", GroupName = "StateStates")]
public sealed class KeyVisual : Control
{
private const string KeyPresenter = "KeyPresenter";
private KeyVisual _keyVisual;
private ContentPresenter _keyPresenter;
public object Content
{
get => (object)GetValue(ContentProperty);
set => SetValue(ContentProperty, value);
}
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register("Content", typeof(object), typeof(KeyVisual), new PropertyMetadata(default(string), OnContentChanged));
public VisualType VisualType
{
get => (VisualType)GetValue(VisualTypeProperty);
set => SetValue(VisualTypeProperty, value);
}
public static readonly DependencyProperty VisualTypeProperty = DependencyProperty.Register("VisualType", typeof(VisualType), typeof(KeyVisual), new PropertyMetadata(default(VisualType), OnSizeChanged));
public bool IsError
{
get => (bool)GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, value);
}
public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register("IsError", typeof(bool), typeof(KeyVisual), new PropertyMetadata(false, OnIsErrorChanged));
public KeyVisual()
{
this.DefaultStyleKey = typeof(KeyVisual);
this.Style = GetStyleSize("TextKeyVisualStyle");
}
protected override void OnApplyTemplate()
{
IsEnabledChanged -= KeyVisual_IsEnabledChanged;
_keyVisual = (KeyVisual)this;
_keyPresenter = (ContentPresenter)_keyVisual.GetTemplateChild(KeyPresenter);
Update();
SetEnabledState();
SetErrorState();
IsEnabledChanged += KeyVisual_IsEnabledChanged;
base.OnApplyTemplate();
}
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((KeyVisual)d).Update();
}
private static void OnSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((KeyVisual)d).Update();
}
private static void OnIsErrorChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((KeyVisual)d).SetErrorState();
}
private void Update()
{
if (_keyVisual == null)
{
return;
}
if (_keyVisual.Content != null)
{
if (_keyVisual.Content.GetType() == typeof(string))
{
_keyVisual.Style = GetStyleSize("TextKeyVisualStyle");
_keyVisual._keyPresenter.Content = _keyVisual.Content;
}
else
{
_keyVisual.Style = GetStyleSize("IconKeyVisualStyle");
switch ((int)_keyVisual.Content)
{
/* We can enable other glyphs in the future
case 13: // The Enter key or button.
_keyVisual._keyPresenter.Content = "\uE751"; break;
case 8: // The Back key or button.
_keyVisual._keyPresenter.Content = "\uE750"; break;
case 16: // The right Shift key or button.
case 160: // The left Shift key or button.
case 161: // The Shift key or button.
_keyVisual._keyPresenter.Content = "\uE752"; break; */
case 38: _keyVisual._keyPresenter.Content = "\uE0E4"; break; // The Up Arrow key or button.
case 40: _keyVisual._keyPresenter.Content = "\uE0E5"; break; // The Down Arrow key or button.
case 37: _keyVisual._keyPresenter.Content = "\uE0E2"; break; // The Left Arrow key or button.
case 39: _keyVisual._keyPresenter.Content = "\uE0E3"; break; // The Right Arrow key or button.
case 91: // The left Windows key
case 92: // The right Windows key
PathIcon winIcon = XamlReader.Load(@"<PathIcon xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" Data=""M9,17V9h8v8ZM0,17V9H8v8ZM9,8V0h8V8ZM0,8V0H8V8Z"" />") as PathIcon;
Viewbox winIconContainer = new Viewbox();
winIconContainer.Child = winIcon;
winIconContainer.HorizontalAlignment = HorizontalAlignment.Center;
winIconContainer.VerticalAlignment = VerticalAlignment.Center;
double iconDimensions = GetIconSize();
winIconContainer.Height = iconDimensions;
winIconContainer.Width = iconDimensions;
_keyVisual._keyPresenter.Content = winIconContainer;
break;
default: _keyVisual._keyPresenter.Content = ((VirtualKey)_keyVisual.Content).ToString(); break;
}
}
}
}
public Style GetStyleSize(string styleName)
{
if (VisualType == VisualType.Small)
{
return (Style)App.Current.Resources["Small" + styleName];
}
else if (VisualType == VisualType.SmallOutline)
{
return (Style)App.Current.Resources["SmallOutline" + styleName];
}
else
{
return (Style)App.Current.Resources["Default" + styleName];
}
}
public double GetIconSize()
{
if (VisualType == VisualType.Small || VisualType == VisualType.SmallOutline)
{
return (double)App.Current.Resources["SmallIconSize"];
}
else
{
return (double)App.Current.Resources["DefaultIconSize"];
}
}
private void KeyVisual_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
SetEnabledState();
}
private void SetErrorState()
{
VisualStateManager.GoToState(this, IsError ? "Error" : "Default", true);
}
private void SetEnabledState()
{
VisualStateManager.GoToState(this, IsEnabled ? "Normal" : "Disabled", true);
}
}
public enum VisualType
{
Small,
SmallOutline,
Large,
}
}

View File

@@ -0,0 +1,144 @@
<ResourceDictionary
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">
<x:Double x:Key="DefaultIconSize">16</x:Double>
<x:Double x:Key="SmallIconSize">12</x:Double>
<Style
x:Key="DefaultTextKeyVisualStyle"
TargetType="local:KeyVisual">
<Setter Property="MinWidth" Value="56" />
<Setter Property="MinHeight" Value="48" />
<Setter Property="Background" Value="{ThemeResource AccentButtonBackground}" />
<Setter Property="Foreground" Value="{ThemeResource AccentButtonForeground}" />
<Setter Property="BorderBrush" Value="{ThemeResource AccentButtonBorderBrush}" />
<Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}" />
<Setter Property="Padding" Value="16,8,16,8" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="FontSize" Value="18" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:KeyVisual">
<Grid>
<Grid>
<Rectangle
x:Name="ContentHolder"
Height="{TemplateBinding Height}"
MinWidth="{TemplateBinding MinWidth}"
Fill="{TemplateBinding Background}"
RadiusX="4"
RadiusY="4"
Stroke="{TemplateBinding BorderBrush}"
StrokeThickness="{TemplateBinding BorderThickness}" />
<ContentPresenter
x:Name="KeyPresenter"
Margin="{TemplateBinding Padding}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="Center"
Content="{TemplateBinding Content}"
FontSize="{TemplateBinding FontSize}"
FontWeight="{TemplateBinding FontWeight}"
Foreground="{TemplateBinding Foreground}" />
</Grid>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Target="ContentHolder.Fill" Value="{ThemeResource AccentButtonBackgroundDisabled}" />
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource AccentButtonForegroundDisabled}" />
<Setter Target="ContentHolder.Stroke" Value="{ThemeResource AccentButtonBorderBrushDisabled}" />
<!--<Setter Target="ContentHolder.StrokeThickness" Value="{TemplateBinding BorderThickness}" />-->
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="StateStates">
<VisualState x:Name="Default" />
<VisualState x:Name="Error">
<VisualState.Setters>
<Setter Target="ContentHolder.Fill" Value="{ThemeResource InfoBarErrorSeverityBackgroundBrush}" />
<Setter Target="KeyPresenter.Foreground" Value="{ThemeResource InfoBarErrorSeverityIconBackground}" />
<Setter Target="ContentHolder.Stroke" Value="{ThemeResource InfoBarErrorSeverityIconBackground}" />
<Setter Target="ContentHolder.StrokeThickness" Value="2" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style
x:Key="SmallTextKeyVisualStyle"
BasedOn="{StaticResource DefaultTextKeyVisualStyle}"
TargetType="local:KeyVisual">
<Setter Property="MinWidth" Value="40" />
<Setter Property="Height" Value="36" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Padding" Value="12,0,12,2" />
<Setter Property="FontSize" Value="14" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style
x:Key="SmallOutlineTextKeyVisualStyle"
BasedOn="{StaticResource DefaultTextKeyVisualStyle}"
TargetType="local:KeyVisual">
<Setter Property="MinWidth" Value="40" />
<Setter Property="Background" Value="{ThemeResource ButtonBackground}" />
<Setter Property="Foreground" Value="{ThemeResource ButtonForeground}" />
<Setter Property="BorderBrush" Value="{ThemeResource ButtonBorderBrush}" />
<Setter Property="Height" Value="36" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Padding" Value="8,0,8,2" />
<Setter Property="FontSize" Value="13" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style
x:Key="DefaultIconKeyVisualStyle"
BasedOn="{StaticResource DefaultTextKeyVisualStyle}"
TargetType="local:KeyVisual">
<Setter Property="MinWidth" Value="56" />
<Setter Property="MinHeight" Value="48" />
<Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}" />
<Setter Property="Padding" Value="16,8,16,8" />
<Setter Property="FontSize" Value="14" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style
x:Key="SmallIconKeyVisualStyle"
BasedOn="{StaticResource DefaultTextKeyVisualStyle}"
TargetType="local:KeyVisual">
<Setter Property="MinWidth" Value="40" />
<Setter Property="Height" Value="36" />
<Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="Padding" Value="0" />
<Setter Property="FontSize" Value="10" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
<Style
x:Key="SmallOutlineIconKeyVisualStyle"
BasedOn="{StaticResource DefaultTextKeyVisualStyle}"
TargetType="local:KeyVisual">
<Setter Property="MinWidth" Value="40" />
<Setter Property="Background" Value="{ThemeResource ButtonBackground}" />
<Setter Property="Foreground" Value="{ThemeResource ButtonForeground}" />
<Setter Property="BorderBrush" Value="{ThemeResource ButtonBorderBrush}" />
<Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}" />
<Setter Property="Height" Value="36" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="Padding" Value="0" />
<Setter Property="FontSize" Value="9" />
<Setter Property="HorizontalContentAlignment" Value="Center" />
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,51 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.Controls.OOBEPageControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Image
x:Name="HeaderImage"
Height="{x:Bind HeroImageHeight}"
Source="{x:Bind HeroImage}"
Stretch="UniformToFill" />
<ScrollViewer
Grid.Row="1"
Padding="32,24,32,24"
VerticalScrollBarVisibility="Auto">
<StackPanel VerticalAlignment="Top" Orientation="Vertical">
<TextBlock
x:Name="TitleTxt"
AutomationProperties.HeadingLevel="Level1"
Style="{StaticResource TitleTextBlockStyle}"
Text="{x:Bind Title}" />
<TextBlock
x:Name="DescriptionTxt"
Margin="0,8,0,0"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind Description}"
TextWrapping="Wrap" />
<ContentPresenter
x:Name="ModuleContentPresenter"
Margin="0,12,0,0"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch"
Content="{x:Bind PageContent}" />
</StackPanel>
</ScrollViewer>
</Grid>
</UserControl>

View File

@@ -0,0 +1,53 @@
// 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.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public sealed partial class OOBEPageControl : UserControl
{
public OOBEPageControl()
{
this.InitializeComponent();
}
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
public string Description
{
get => (string)GetValue(DescriptionProperty);
set => SetValue(DescriptionProperty, value);
}
public string HeroImage
{
get => (string)GetValue(HeroImageProperty);
set => SetValue(HeroImageProperty, value);
}
public double HeroImageHeight
{
get { return (double)GetValue(HeroImageHeightProperty); }
set { SetValue(HeroImageHeightProperty, value); }
}
public object PageContent
{
get { return (object)GetValue(PageContentProperty); }
set { SetValue(PageContentProperty, value); }
}
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(SettingsPageControl), new PropertyMetadata(default(string)));
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register("Description", typeof(string), typeof(SettingsPageControl), new PropertyMetadata(default(string)));
public static readonly DependencyProperty HeroImageProperty = DependencyProperty.Register("HeroImage", typeof(string), typeof(SettingsPageControl), new PropertyMetadata(default(string)));
public static readonly DependencyProperty PageContentProperty = DependencyProperty.Register("PageContent", typeof(object), typeof(SettingsPageControl), new PropertyMetadata(new Grid()));
public static readonly DependencyProperty HeroImageHeightProperty = DependencyProperty.Register("HeroImageHeight", typeof(double), typeof(SettingsPageControl), new PropertyMetadata(280.0));
}
}

View File

@@ -0,0 +1,48 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.Controls.PowerAccentShortcutControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ItemsControl
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
IsTabStop="False"
ItemsSource="{x:Bind Keys}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel
Orientation="Horizontal"
Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:KeyVisual
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
Content="{Binding}"
IsTabStop="False"
VisualType="SmallOutline" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<toolkitcontrols:MarkdownTextBlock
Grid.Column="1"
Margin="8,0,0,0"
VerticalAlignment="Center"
Background="Transparent"
Text="{x:Bind Text}" />
</Grid>
</UserControl>

View File

@@ -0,0 +1,34 @@
// 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.Collections.Generic;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public sealed partial class PowerAccentShortcutControl : UserControl
{
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(PowerAccentShortcutControl), new PropertyMetadata(default(string)));
public List<object> Keys
{
get { return (List<object>)GetValue(KeysProperty); }
set { SetValue(KeysProperty, value); }
}
public static readonly DependencyProperty KeysProperty = DependencyProperty.Register("Keys", typeof(List<object>), typeof(PowerAccentShortcutControl), new PropertyMetadata(default(string)));
public PowerAccentShortcutControl()
{
this.InitializeComponent();
}
}
}

View File

@@ -0,0 +1,102 @@
// 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.ComponentModel;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation.Peers;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
/// <summary>
/// Represents a control that can contain multiple settings (or other) controls
/// </summary>
[TemplateVisualState(Name = "Normal", GroupName = "CommonStates")]
[TemplateVisualState(Name = "Disabled", GroupName = "CommonStates")]
[TemplatePart(Name = PartDescriptionPresenter, Type = typeof(ContentPresenter))]
public partial class SettingsGroup : ItemsControl
{
private const string PartDescriptionPresenter = "DescriptionPresenter";
private ContentPresenter _descriptionPresenter;
private SettingsGroup _settingsGroup;
public SettingsGroup()
{
DefaultStyleKey = typeof(SettingsGroup);
}
[Localizable(true)]
public string Header
{
get => (string)GetValue(HeaderProperty);
set => SetValue(HeaderProperty, value);
}
public static readonly DependencyProperty HeaderProperty = DependencyProperty.Register(
"Header",
typeof(string),
typeof(SettingsGroup),
new PropertyMetadata(default(string)));
[Localizable(true)]
public object Description
{
get => (object)GetValue(DescriptionProperty);
set => SetValue(DescriptionProperty, value);
}
public static readonly DependencyProperty DescriptionProperty = DependencyProperty.Register(
"Description",
typeof(object),
typeof(SettingsGroup),
new PropertyMetadata(null, OnDescriptionChanged));
protected override void OnApplyTemplate()
{
IsEnabledChanged -= SettingsGroup_IsEnabledChanged;
_settingsGroup = (SettingsGroup)this;
_descriptionPresenter = (ContentPresenter)_settingsGroup.GetTemplateChild(PartDescriptionPresenter);
SetEnabledState();
IsEnabledChanged += SettingsGroup_IsEnabledChanged;
base.OnApplyTemplate();
}
private static void OnDescriptionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
((SettingsGroup)d).Update();
}
private void SettingsGroup_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
SetEnabledState();
}
private void SetEnabledState()
{
VisualStateManager.GoToState(this, IsEnabled ? "Normal" : "Disabled", true);
}
private void Update()
{
if (_settingsGroup == null)
{
return;
}
if (_settingsGroup.Description == null)
{
_settingsGroup._descriptionPresenter.Visibility = Visibility.Collapsed;
}
else
{
_settingsGroup._descriptionPresenter.Visibility = Visibility.Visible;
}
}
protected override AutomationPeer OnCreateAutomationPeer()
{
return new SettingsGroupAutomationPeer(this);
}
}
}

View File

@@ -0,0 +1,74 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls">
<Style TargetType="controls:SettingsGroup">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel
ChildrenTransitions="{StaticResource SettingsCardsAnimations}"
Orientation="Vertical"
Spacing="2" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="IsTabStop" Value="False" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:SettingsGroup">
<Grid HorizontalAlignment="Stretch">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock
x:Name="HeaderPresenter"
Grid.Row="0"
Margin="1,32,0,0"
AutomationProperties.HeadingLevel="Level2"
Style="{ThemeResource BodyStrongTextBlockStyle}"
Text="{TemplateBinding Header}" />
<ContentPresenter
x:Name="DescriptionPresenter"
Grid.Row="1"
Margin="1,0,0,0"
Content="{TemplateBinding Description}"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
TextWrapping="WrapWholeWords">
<ContentPresenter.Resources>
<Style BasedOn="{StaticResource CaptionTextBlockStyle}" TargetType="TextBlock">
<Style.Setters>
<Setter Property="TextWrapping" Value="WrapWholeWords" />
</Style.Setters>
</Style>
<Style BasedOn="{StaticResource TextButtonStyle}" TargetType="HyperlinkButton">
<Style.Setters>
<Setter Property="Padding" Value="0,0,0,0" />
</Style.Setters>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
<ItemsPresenter Grid.Row="2" Margin="0,8,0,0" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="Disabled">
<VisualState.Setters>
<Setter Target="HeaderPresenter.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
<Setter Target="DescriptionPresenter.Foreground" Value="{ThemeResource TextFillColorDisabledBrush}" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,22 @@
// 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.UI.Xaml.Automation.Peers;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public class SettingsGroupAutomationPeer : FrameworkElementAutomationPeer
{
public SettingsGroupAutomationPeer(SettingsGroup owner)
: base(owner)
{
}
protected override string GetNameCore()
{
var selectedSettingsGroup = (SettingsGroup)Owner;
return selectedSettingsGroup.Header;
}
}
}

View File

@@ -0,0 +1,15 @@
// 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;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public class PageLink
{
public string Text { get; set; }
public Uri Link { get; set; }
}
}

View File

@@ -0,0 +1,161 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.Controls.SettingsPageControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:converters="using:CommunityToolkit.WinUI.UI.Converters"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Loaded="UserControl_Loaded"
mc:Ignorable="d">
<UserControl.Resources>
<x:Double x:Key="PageMaxWidth">1000</x:Double>
<converters:DoubleToVisibilityConverter
x:Name="doubleToVisibilityConverter"
FalseValue="Collapsed"
GreaterThan="0"
TrueValue="Visible" />
</UserControl.Resources>
<Grid Padding="20,0,0,0" RowSpacing="24">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="480" />
</VisualState.StateTriggers>
</VisualState>
<VisualState>
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="DescriptionPanel.(Grid.Row)" Value="1" />
<Setter Target="DescriptionPanel.(Grid.Column)" Value="0" />
<Setter Target="DescriptionPanel.(Grid.ColumnSpan)" Value="2" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<TextBlock
x:Name="Header"
MaxWidth="{StaticResource PageMaxWidth}"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
AutomationProperties.HeadingLevel="1"
Style="{StaticResource TitleTextBlockStyle}"
Text="{x:Bind ModuleTitle}" />
<ScrollViewer Grid.Row="1">
<Grid
Padding="0,0,20,48"
ChildrenTransitions="{StaticResource SettingsCardsAnimations}"
RowSpacing="24">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<!-- Top panel -->
<Grid
MaxWidth="{StaticResource PageMaxWidth}"
ColumnSpacing="16"
RowSpacing="16">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Border
MaxWidth="160"
HorizontalAlignment="Left"
VerticalAlignment="Top"
CornerRadius="4">
<Image AutomationProperties.AccessibilityView="Raw">
<Image.Source>
<BitmapImage UriSource="{x:Bind ModuleImageSource}" />
</Image.Source>
</Image>
</Border>
<StackPanel x:Name="DescriptionPanel" Grid.Column="1">
<TextBlock
x:Name="AboutDescription"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="{x:Bind ModuleDescription}"
TextWrapping="Wrap" />
<ItemsControl
x:Name="PrimaryLinksControl"
Margin="0,8,0,0"
IsTabStop="False"
ItemsSource="{x:Bind PrimaryLinks}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="local:PageLink">
<HyperlinkButton NavigateUri="{x:Bind Link}" Style="{StaticResource TextButtonStyle}">
<TextBlock Text="{x:Bind Text}" TextWrapping="Wrap" />
</HyperlinkButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<controls:WrapPanel HorizontalSpacing="24" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</Grid>
<!-- Content panel -->
<ContentPresenter
x:Name="ModuleContentPresenter"
Grid.Row="1"
MaxWidth="{StaticResource PageMaxWidth}"
Margin="0,12,0,0"
Content="{x:Bind ModuleContent}" />
<!-- Bottom panel -->
<StackPanel
x:Name="SecondaryLinksPanel"
Grid.Row="2"
MaxWidth="{StaticResource PageMaxWidth}"
Orientation="Vertical"
Visibility="{x:Bind SecondaryLinks.Count, Converter={StaticResource doubleToVisibilityConverter}}">
<TextBlock
Margin="2,8,0,0"
AutomationProperties.HeadingLevel="Level2"
Style="{ThemeResource BodyStrongTextBlockStyle}"
Text="{x:Bind SecondaryLinksHeader}" />
<ItemsControl
x:Name="SecondaryLinksItemControl"
Margin="2,0,0,0"
IsTabStop="False"
ItemsSource="{x:Bind SecondaryLinks}">
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="local:PageLink">
<HyperlinkButton NavigateUri="{x:Bind Link}" Style="{StaticResource TextButtonStyle}">
<TextBlock Text="{x:Bind Text}" TextWrapping="Wrap" />
</HyperlinkButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<controls:WrapPanel HorizontalSpacing="24" Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</StackPanel>
</Grid>
</ScrollViewer>
</Grid>
</UserControl>

View File

@@ -0,0 +1,75 @@
// 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.Collections.ObjectModel;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public sealed partial class SettingsPageControl : UserControl
{
public SettingsPageControl()
{
this.InitializeComponent();
PrimaryLinks = new ObservableCollection<PageLink>();
SecondaryLinks = new ObservableCollection<PageLink>();
}
public string ModuleTitle
{
get { return (string)GetValue(ModuleTitleProperty); }
set { SetValue(ModuleTitleProperty, value); }
}
public string ModuleDescription
{
get => (string)GetValue(ModuleDescriptionProperty);
set => SetValue(ModuleDescriptionProperty, value);
}
public string ModuleImageSource
{
get => (string)GetValue(ModuleImageSourceProperty);
set => SetValue(ModuleImageSourceProperty, value);
}
public ObservableCollection<PageLink> PrimaryLinks
{
get => (ObservableCollection<PageLink>)GetValue(PrimaryLinksProperty);
set => SetValue(PrimaryLinksProperty, value);
}
public string SecondaryLinksHeader
{
get { return (string)GetValue(SecondaryLinksHeaderProperty); }
set { SetValue(SecondaryLinksHeaderProperty, value); }
}
public ObservableCollection<PageLink> SecondaryLinks
{
get => (ObservableCollection<PageLink>)GetValue(SecondaryLinksProperty);
set => SetValue(SecondaryLinksProperty, value);
}
public object ModuleContent
{
get { return (object)GetValue(ModuleContentProperty); }
set { SetValue(ModuleContentProperty, value); }
}
public static readonly DependencyProperty ModuleTitleProperty = DependencyProperty.Register("ModuleTitle", typeof(string), typeof(SettingsPageControl), new PropertyMetadata(default(string)));
public static readonly DependencyProperty ModuleDescriptionProperty = DependencyProperty.Register("ModuleDescription", typeof(string), typeof(SettingsPageControl), new PropertyMetadata(default(string)));
public static readonly DependencyProperty ModuleImageSourceProperty = DependencyProperty.Register("ModuleImageSource", typeof(string), typeof(SettingsPageControl), new PropertyMetadata(default(string)));
public static readonly DependencyProperty PrimaryLinksProperty = DependencyProperty.Register("PrimaryLinks", typeof(ObservableCollection<PageLink>), typeof(SettingsPageControl), new PropertyMetadata(new ObservableCollection<PageLink>()));
public static readonly DependencyProperty SecondaryLinksHeaderProperty = DependencyProperty.Register("SecondaryLinksHeader", typeof(string), typeof(SettingsPageControl), new PropertyMetadata(default(string)));
public static readonly DependencyProperty SecondaryLinksProperty = DependencyProperty.Register("SecondaryLinks", typeof(ObservableCollection<PageLink>), typeof(SettingsPageControl), new PropertyMetadata(new ObservableCollection<PageLink>()));
public static readonly DependencyProperty ModuleContentProperty = DependencyProperty.Register("ModuleContent", typeof(object), typeof(SettingsPageControl), new PropertyMetadata(new Grid()));
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
PrimaryLinksControl.Focus(FocusState.Programmatic);
}
}
}

View File

@@ -0,0 +1,53 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.Controls.ShortcutControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
x:Name="LayoutRoot"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
<Grid HorizontalAlignment="Right">
<StackPanel Orientation="Horizontal">
<Button
x:Name="EditButton"
Padding="0"
Click="OpenDialogButton_Click"
CornerRadius="8">
<StackPanel
Margin="12,6,12,6"
Orientation="Horizontal"
Spacing="16">
<ItemsControl
x:Name="PreviewKeysControl"
VerticalAlignment="Center"
IsEnabled="{Binding ElementName=EditButton, Path=IsEnabled}"
IsTabStop="False">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:KeyVisual
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
Content="{Binding}"
IsTabStop="False"
VisualType="Small" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<FontIcon
FontFamily="{ThemeResource SymbolThemeFontFamily}"
FontSize="16"
Glyph="&#xE70F;" />
</StackPanel>
</Button>
</StackPanel>
</Grid>
</UserControl>

View File

@@ -0,0 +1,442 @@
// 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 Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Automation;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Input;
using Windows.System;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public sealed partial class ShortcutControl : UserControl, IDisposable
{
private readonly UIntPtr ignoreKeyEventFlag = (UIntPtr)0x5555;
private bool _shiftKeyDownOnEntering;
private bool _shiftToggled;
private bool _enabled;
private HotkeySettings hotkeySettings;
private HotkeySettings internalSettings;
private HotkeySettings lastValidSettings;
private HotkeySettingsControlHook hook;
private bool _isActive;
private bool disposedValue;
public string Header { get; set; }
public string Keys { get; set; }
public static readonly DependencyProperty IsActiveProperty = DependencyProperty.Register("Enabled", typeof(bool), typeof(ShortcutControl), null);
public static readonly DependencyProperty HotkeySettingsProperty = DependencyProperty.Register("HotkeySettings", typeof(HotkeySettings), typeof(ShortcutControl), null);
private ShortcutDialogContentControl c = new ShortcutDialogContentControl();
private ContentDialog shortcutDialog;
public bool Enabled
{
get
{
return _enabled;
}
set
{
SetValue(IsActiveProperty, value);
_enabled = value;
if (value)
{
EditButton.IsEnabled = true;
}
else
{
EditButton.IsEnabled = false;
}
}
}
public HotkeySettings HotkeySettings
{
get
{
return hotkeySettings;
}
set
{
if (hotkeySettings != value)
{
hotkeySettings = value;
SetValue(HotkeySettingsProperty, value);
PreviewKeysControl.ItemsSource = HotkeySettings.GetKeysList();
AutomationProperties.SetHelpText(EditButton, HotkeySettings.ToString());
c.Keys = HotkeySettings.GetKeysList();
}
}
}
public ShortcutControl()
{
InitializeComponent();
internalSettings = new HotkeySettings();
this.Unloaded += ShortcutControl_Unloaded;
hook = new HotkeySettingsControlHook(Hotkey_KeyDown, Hotkey_KeyUp, Hotkey_IsActive, FilterAccessibleKeyboardEvents);
var resourceLoader = Helpers.ResourceLoaderInstance.ResourceLoader;
if (App.GetSettingsWindow() != null)
{
App.GetSettingsWindow().Activated += ShortcutDialog_SettingsWindow_Activated;
}
// We create the Dialog in C# because doing it in XAML is giving WinUI/XAML Island bugs when using dark theme.
shortcutDialog = new ContentDialog
{
XamlRoot = this.XamlRoot,
Title = resourceLoader.GetString("Activation_Shortcut_Title"),
Content = c,
PrimaryButtonText = resourceLoader.GetString("Activation_Shortcut_Save"),
SecondaryButtonText = resourceLoader.GetString("Activation_Shortcut_Reset"),
CloseButtonText = resourceLoader.GetString("Activation_Shortcut_Cancel"),
DefaultButton = ContentDialogButton.Primary,
};
shortcutDialog.PrimaryButtonClick += ShortcutDialog_PrimaryButtonClick;
shortcutDialog.SecondaryButtonClick += ShortcutDialog_Reset;
shortcutDialog.Opened += ShortcutDialog_Opened;
shortcutDialog.Closing += ShortcutDialog_Closing;
AutomationProperties.SetName(EditButton, resourceLoader.GetString("Activation_Shortcut_Title"));
}
private void ShortcutControl_Unloaded(object sender, RoutedEventArgs e)
{
shortcutDialog.PrimaryButtonClick -= ShortcutDialog_PrimaryButtonClick;
shortcutDialog.Opened -= ShortcutDialog_Opened;
shortcutDialog.Closing -= ShortcutDialog_Closing;
if (App.GetSettingsWindow() != null)
{
App.GetSettingsWindow().Activated -= ShortcutDialog_SettingsWindow_Activated;
}
// Dispose the HotkeySettingsControlHook object to terminate the hook threads when the textbox is unloaded
if (hook != null)
{
hook.Dispose();
}
hook = null;
}
private void KeyEventHandler(int key, bool matchValue, int matchValueCode)
{
switch ((VirtualKey)key)
{
case VirtualKey.LeftWindows:
case VirtualKey.RightWindows:
internalSettings.Win = matchValue;
break;
case VirtualKey.Control:
case VirtualKey.LeftControl:
case VirtualKey.RightControl:
internalSettings.Ctrl = matchValue;
break;
case VirtualKey.Menu:
case VirtualKey.LeftMenu:
case VirtualKey.RightMenu:
internalSettings.Alt = matchValue;
break;
case VirtualKey.Shift:
case VirtualKey.LeftShift:
case VirtualKey.RightShift:
_shiftToggled = true;
internalSettings.Shift = matchValue;
break;
case VirtualKey.Escape:
internalSettings = new HotkeySettings();
shortcutDialog.IsPrimaryButtonEnabled = false;
return;
default:
internalSettings.Code = matchValueCode;
break;
}
}
// Function to send a single key event to the system which would be ignored by the hotkey control.
private void SendSingleKeyboardInput(short keyCode, uint keyStatus)
{
NativeKeyboardHelper.INPUT inputShift = new NativeKeyboardHelper.INPUT
{
type = NativeKeyboardHelper.INPUTTYPE.INPUT_KEYBOARD,
data = new NativeKeyboardHelper.InputUnion
{
ki = new NativeKeyboardHelper.KEYBDINPUT
{
wVk = keyCode,
dwFlags = keyStatus,
// Any keyevent with the extraInfo set to this value will be ignored by the keyboard hook and sent to the system instead.
dwExtraInfo = ignoreKeyEventFlag,
},
},
};
NativeKeyboardHelper.INPUT[] inputs = new NativeKeyboardHelper.INPUT[] { inputShift };
_ = NativeMethods.SendInput(1, inputs, NativeKeyboardHelper.INPUT.Size);
}
private bool FilterAccessibleKeyboardEvents(int key, UIntPtr extraInfo)
{
// A keyboard event sent with this value in the extra Information field should be ignored by the hook so that it can be captured by the system instead.
if (extraInfo == ignoreKeyEventFlag)
{
return false;
}
// If the current key press is tab, based on the other keys ignore the key press so as to shift focus out of the hotkey control.
if ((VirtualKey)key == VirtualKey.Tab)
{
// Shift was not pressed while entering and Shift is not pressed while leaving the hotkey control, treat it as a normal tab key press.
if (!internalSettings.Shift && !_shiftKeyDownOnEntering && !internalSettings.Win && !internalSettings.Alt && !internalSettings.Ctrl)
{
return false;
}
// Shift was not pressed while entering but it was pressed while leaving the hotkey, therefore simulate a shift key press as the system does not know about shift being pressed in the hotkey.
else if (internalSettings.Shift && !_shiftKeyDownOnEntering && !internalSettings.Win && !internalSettings.Alt && !internalSettings.Ctrl)
{
// This is to reset the shift key press within the control as it was not used within the control but rather was used to leave the hotkey.
internalSettings.Shift = false;
SendSingleKeyboardInput((short)VirtualKey.Shift, (uint)NativeKeyboardHelper.KeyEventF.KeyDown);
return false;
}
// Shift was pressed on entering and remained pressed, therefore only ignore the tab key so that it can be passed to the system.
// As the shift key is already assumed to be pressed by the system while it entered the hotkey control, shift would still remain pressed, hence ignoring the tab input would simulate a Shift+Tab key press.
else if (!internalSettings.Shift && _shiftKeyDownOnEntering && !_shiftToggled && !internalSettings.Win && !internalSettings.Alt && !internalSettings.Ctrl)
{
return false;
}
// Shift was pressed on entering but it was released and later pressed again.
// Ignore the tab key and the system already has the shift key pressed, therefore this would simulate Shift+Tab.
// However, since the last shift key was only used to move out of the control, reset the status of shift within the control.
else if (internalSettings.Shift && _shiftKeyDownOnEntering && _shiftToggled && !internalSettings.Win && !internalSettings.Alt && !internalSettings.Ctrl)
{
internalSettings.Shift = false;
return false;
}
// Shift was pressed on entering and was later released.
// The system still has shift in the key pressed status, therefore pass a Shift KeyUp message to the system, to release the shift key, therefore simulating only the Tab key press.
else if (!internalSettings.Shift && _shiftKeyDownOnEntering && _shiftToggled && !internalSettings.Win && !internalSettings.Alt && !internalSettings.Ctrl)
{
SendSingleKeyboardInput((short)VirtualKey.Shift, (uint)NativeKeyboardHelper.KeyEventF.KeyUp);
return false;
}
}
// Either the cancel or save button has keyboard focus.
if (FocusManager.GetFocusedElement(LayoutRoot.XamlRoot).GetType() == typeof(Button))
{
return false;
}
return true;
}
private void Hotkey_KeyDown(int key)
{
KeyEventHandler(key, true, key);
c.Keys = internalSettings.GetKeysList();
if (internalSettings.GetKeysList().Count == 0)
{
// Empty, disable save button
shortcutDialog.IsPrimaryButtonEnabled = false;
}
else if (internalSettings.GetKeysList().Count == 1)
{
// 1 key, disable save button
shortcutDialog.IsPrimaryButtonEnabled = false;
// Check if the one key is a hotkey
if (internalSettings.Shift || internalSettings.Win || internalSettings.Alt || internalSettings.Ctrl)
{
c.IsError = false;
}
else
{
c.IsError = true;
}
}
// Tab and Shift+Tab are accessible keys and should not be displayed in the hotkey control.
if (internalSettings.Code > 0 && !internalSettings.IsAccessibleShortcut())
{
lastValidSettings = internalSettings.Clone();
if (!ComboIsValid(lastValidSettings))
{
DisableKeys();
}
else
{
EnableKeys();
}
}
}
private void EnableKeys()
{
shortcutDialog.IsPrimaryButtonEnabled = true;
c.IsError = false;
// WarningLabel.Style = (Style)App.Current.Resources["SecondaryTextStyle"];
}
private void DisableKeys()
{
shortcutDialog.IsPrimaryButtonEnabled = false;
c.IsError = true;
// WarningLabel.Style = (Style)App.Current.Resources["SecondaryWarningTextStyle"];
}
private void Hotkey_KeyUp(int key)
{
KeyEventHandler(key, false, 0);
}
private bool Hotkey_IsActive()
{
return _isActive;
}
private void ShortcutDialog_Opened(ContentDialog sender, ContentDialogOpenedEventArgs args)
{
if (!ComboIsValid(hotkeySettings))
{
DisableKeys();
}
else
{
EnableKeys();
}
// Reset the status on entering the hotkey each time.
_shiftKeyDownOnEntering = false;
_shiftToggled = false;
// To keep track of the shift key, whether it was pressed on entering.
if ((NativeMethods.GetAsyncKeyState((int)VirtualKey.Shift) & 0x8000) != 0)
{
_shiftKeyDownOnEntering = true;
}
_isActive = true;
}
private async void OpenDialogButton_Click(object sender, RoutedEventArgs e)
{
c.Keys = null;
c.Keys = HotkeySettings.GetKeysList();
shortcutDialog.XamlRoot = this.XamlRoot;
shortcutDialog.RequestedTheme = this.ActualTheme;
await shortcutDialog.ShowAsync();
}
private void ShortcutDialog_Reset(ContentDialog sender, ContentDialogButtonClickEventArgs args)
{
hotkeySettings = null;
SetValue(HotkeySettingsProperty, hotkeySettings);
PreviewKeysControl.ItemsSource = HotkeySettings.GetKeysList();
lastValidSettings = hotkeySettings;
AutomationProperties.SetHelpText(EditButton, HotkeySettings.ToString());
shortcutDialog.Hide();
}
private void ShortcutDialog_PrimaryButtonClick(ContentDialog sender, ContentDialogButtonClickEventArgs args)
{
if (ComboIsValid(lastValidSettings))
{
HotkeySettings = lastValidSettings.Clone();
}
PreviewKeysControl.ItemsSource = hotkeySettings.GetKeysList();
AutomationProperties.SetHelpText(EditButton, HotkeySettings.ToString());
shortcutDialog.Hide();
}
private static bool ComboIsValid(HotkeySettings settings)
{
if (settings != null && (settings.IsValid() || settings.IsEmpty()))
{
return true;
}
else
{
return false;
}
}
private void ShortcutDialog_SettingsWindow_Activated(object sender, WindowActivatedEventArgs args)
{
args.Handled = true;
if (args.WindowActivationState != WindowActivationState.Deactivated && (hook == null || hook.GetDisposedState() == true))
{
// If the PT settings window gets focussed/activated again, we enable the keyboard hook to catch the keyboard input.
hook = new HotkeySettingsControlHook(Hotkey_KeyDown, Hotkey_KeyUp, Hotkey_IsActive, FilterAccessibleKeyboardEvents);
}
else if (args.WindowActivationState == WindowActivationState.Deactivated && hook != null && hook.GetDisposedState() == false)
{
// If the PT settings window lost focus/activation, we disable the keyboard hook to allow keyboard input on other windows.
hook.Dispose();
hook = null;
}
}
private void ShortcutDialog_Closing(ContentDialog sender, ContentDialogClosingEventArgs args)
{
_isActive = false;
}
private void Dispose(bool disposing)
{
if (!disposedValue)
{
if (disposing)
{
if (hook != null)
{
hook.Dispose();
}
hook = null;
}
disposedValue = true;
}
}
public void Dispose()
{
// Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
Dispose(disposing: true);
GC.SuppressFinalize(this);
}
}
}

View File

@@ -0,0 +1,75 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.Controls.ShortcutDialogContentControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
x:Name="ShortcutContentControl"
mc:Ignorable="d">
<Grid
MinWidth="498"
MinHeight="220">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition MinHeight="110" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock
x:Uid="Activation_Shortcut_Description"
Grid.Row="0" />
<ItemsControl
x:Name="KeysControl"
Grid.Row="1"
Height="56"
Margin="0,64,0,0"
HorizontalAlignment="Center"
VerticalAlignment="Top"
HorizontalContentAlignment="Center"
ItemsSource="{x:Bind Keys, Mode=OneWay}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel
Orientation="Horizontal"
Spacing="8" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:KeyVisual
Height="56"
AutomationProperties.AccessibilityView="Raw"
Content="{Binding}"
IsError="{Binding ElementName=ShortcutContentControl, Path=IsError, Mode=OneWay}"
IsTabStop="False"
VisualType="Large" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<StackPanel
Grid.Row="2"
Margin="0,24,0,0"
VerticalAlignment="Top"
Orientation="Vertical"
Spacing="8">
<Grid Height="62">
<InfoBar x:Uid="InvalidShortcut"
IsClosable="False"
IsOpen="{Binding ElementName=ShortcutContentControl, Path=IsError, Mode=OneWay}"
IsTabStop="{Binding ElementName=ShortcutContentControl, Path=IsError, Mode=OneWay}"
Severity="Error" />
</Grid>
<toolkitcontrols:MarkdownTextBlock
x:Uid="InvalidShortcutWarningLabel"
Background="Transparent"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}" />
</StackPanel>
</Grid>
</UserControl>

View File

@@ -0,0 +1,34 @@
// 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.Collections.Generic;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public sealed partial class ShortcutDialogContentControl : UserControl
{
public ShortcutDialogContentControl()
{
this.InitializeComponent();
}
public List<object> Keys
{
get { return (List<object>)GetValue(KeysProperty); }
set { SetValue(KeysProperty, value); }
}
public static readonly DependencyProperty KeysProperty = DependencyProperty.Register("Keys", typeof(List<object>), typeof(SettingsPageControl), new PropertyMetadata(default(string)));
public bool IsError
{
get => (bool)GetValue(IsErrorProperty);
set => SetValue(IsErrorProperty, value);
}
public static readonly DependencyProperty IsErrorProperty = DependencyProperty.Register("IsError", typeof(bool), typeof(ShortcutDialogContentControl), new PropertyMetadata(false));
}
}

View File

@@ -0,0 +1,49 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.Controls.ShortcutWithTextLabelControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ItemsControl
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
IsTabStop="False"
ItemsSource="{x:Bind Keys}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel
Orientation="Horizontal"
Spacing="4" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<controls:KeyVisual
VerticalAlignment="Center"
AutomationProperties.AccessibilityView="Raw"
Content="{Binding}"
IsTabStop="False"
VisualType="SmallOutline" />
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<toolkitcontrols:MarkdownTextBlock
Grid.Column="1"
Margin="8,0,0,0"
VerticalAlignment="Center"
Background="Transparent"
Text="{x:Bind Text}" />
</Grid>
</UserControl>

View File

@@ -0,0 +1,34 @@
// 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.Collections.Generic;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.Controls
{
public sealed partial class ShortcutWithTextLabelControl : UserControl
{
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
public static readonly DependencyProperty TextProperty = DependencyProperty.Register("Text", typeof(string), typeof(ShortcutWithTextLabelControl), new PropertyMetadata(default(string)));
public List<object> Keys
{
get { return (List<object>)GetValue(KeysProperty); }
set { SetValue(KeysProperty, value); }
}
public static readonly DependencyProperty KeysProperty = DependencyProperty.Register("Keys", typeof(List<object>), typeof(ShortcutWithTextLabelControl), new PropertyMetadata(default(string)));
public ShortcutWithTextLabelControl()
{
this.InitializeComponent();
}
}
}

View File

@@ -0,0 +1,89 @@
<!-- Copyright (c) Microsoft Corporation and Contributors. -->
<!-- Licensed under the MIT License. -->
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Flyout.AppsListPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Flyout"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:viewmodels="using:Microsoft.PowerToys.Settings.UI.ViewModels"
mc:Ignorable="d">
<Grid Background="{ThemeResource LayerOnAcrylicFillColorDefaultBrush}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Padding="24,32,24,0">
<TextBlock
x:Uid="AllAppsTxt"
VerticalAlignment="Center"
Style="{StaticResource BodyStrongTextBlockStyle}" />
<Button
x:Uid="BackBtn"
Padding="8,4,8,4"
HorizontalAlignment="Right"
VerticalAlignment="Center"
Click="BackButton_Click">
<Button.Content>
<StackPanel
VerticalAlignment="Center"
Orientation="Horizontal"
Spacing="12">
<FontIcon
Margin="0,2,0,0"
FontSize="12"
Glyph="&#xe76b;" />
<TextBlock x:Uid="BackLabel" Style="{StaticResource CaptionTextBlockStyle}" />
</StackPanel>
</Button.Content>
</Button>
</Grid>
<ListView
Grid.Row="1"
Margin="0,16,0,0"
ItemsSource="{x:Bind ViewModel.FlyoutMenuItems}"
SelectionMode="None">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Padding="0,0,0,16" Orientation="Vertical" />
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListView.ItemTemplate>
<DataTemplate x:DataType="viewmodels:FlyoutMenuItem">
<Grid Height="40" Padding="24,0,24,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!--<ViewBox VerticalAlignment="Center">-->
<Image
Width="20"
Margin="0,0,16,0">
<Image.Source>
<BitmapImage UriSource="{x:Bind Icon, Mode=OneWay}" />
</Image.Source>
</Image>
<!--</ViewBox>-->
<TextBlock
Grid.Column="1"
VerticalAlignment="Center"
Text="{x:Bind Label, Mode=OneWay}"
TextTrimming="CharacterEllipsis" />
<ToggleSwitch
Grid.Column="2"
Margin="0,0,0,0"
HorizontalAlignment="Right"
AutomationProperties.Name="{x:Bind Label, Mode=OneWay}"
IsOn="{x:Bind IsEnabled, Mode=TwoWay}"
Style="{StaticResource RightAlignedCompactToggleSwitchStyle}" />
</Grid>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>

View File

@@ -0,0 +1,36 @@
// 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.ObjectModel;
using System.Threading;
using global::Windows.System;
using interop;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Animation;
namespace Microsoft.PowerToys.Settings.UI.Flyout
{
public sealed partial class AppsListPage : Page
{
private AllAppsViewModel ViewModel { get; set; }
public AppsListPage()
{
this.InitializeComponent();
var settingsUtils = new SettingsUtils();
ViewModel = new AllAppsViewModel(SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), Views.ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
}
private void BackButton_Click(object sender, RoutedEventArgs e)
{
Frame.Navigate(typeof(LaunchPage), null, new SlideNavigationTransitionInfo() { Effect = SlideNavigationTransitionEffect.FromLeft });
}
}
}

View File

@@ -0,0 +1,166 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Flyout.LaunchPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:animatedVisuals="using:Microsoft.UI.Xaml.Controls.AnimatedVisuals"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Flyout"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitControls="using:CommunityToolkit.WinUI.UI.Controls"
xmlns:viewModels="using:Microsoft.PowerToys.Settings.UI.ViewModels"
mc:Ignorable="d">
<Page.Resources>
<Style
x:Key="FlyoutButtonStyle"
BasedOn="{StaticResource SubtleButtonStyle}"
TargetType="Button">
<Setter Property="Padding" Value="6" />
<Setter Property="Width" Value="32" />
<Setter Property="Height" Value="32" />
<Setter Property="FontFamily" Value="{ThemeResource SymbolThemeFontFamily}" />
</Style>
</Page.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="48" />
</Grid.RowDefinitions>
<Grid
Background="{ThemeResource LayerOnAcrylicFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="0,0,0,1">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Grid Padding="36,32,36,0">
<TextBlock
VerticalAlignment="Center"
Style="{StaticResource BodyStrongTextBlockStyle}"
x:Uid="ShortcutsTxt" />
<Button
Padding="8,4,8,4"
HorizontalAlignment="Right"
VerticalAlignment="Center"
x:Uid="MoreBtn"
Click="AllAppButton_Click">
<Button.Content>
<StackPanel
VerticalAlignment="Center"
Orientation="Horizontal"
Spacing="12">
<TextBlock Style="{StaticResource CaptionTextBlockStyle}" x:Uid="MoreLabel" />
<FontIcon
Margin="0,2,0,0"
FontSize="12"
Glyph="&#xe76c;" />
</StackPanel>
</Button.Content>
</Button>
</Grid>
<Grid Grid.Row="1">
<ItemsControl
Margin="12,26,12,24"
HorizontalAlignment="Center"
VerticalAlignment="Top"
ItemsSource="{x:Bind ViewModel.FlyoutMenuItems}"
TabNavigation="Local">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<toolkitControls:WrapPanel VerticalSpacing="12" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate x:DataType="viewModels:FlyoutMenuItem">
<controls:FlyoutMenuButton
Click="ModuleButton_Click"
Tag="{x:Bind Tag}"
AutomationProperties.Name="{x:Bind Label}"
ToolTipService.ToolTip="{x:Bind ToolTip}"
Visibility="{x:Bind Visible, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource BoolToVisibilityConverter}}">
<controls:FlyoutMenuButton.Content>
<TextBlock
Style="{StaticResource CaptionTextBlockStyle}"
Text="{x:Bind Label}"
TextAlignment="Center"
TextWrapping="Wrap" />
</controls:FlyoutMenuButton.Content>
<controls:FlyoutMenuButton.Icon>
<Image>
<Image.Source>
<BitmapImage UriSource="{x:Bind Icon, Mode=OneWay}" />
</Image.Source>
</Image>
</controls:FlyoutMenuButton.Icon>
</controls:FlyoutMenuButton>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</Grid>
</Grid>
<Grid Grid.Row="2">
<InfoBar
x:Uid="UpdateAvailable"
IsClosable="False"
IsOpen="{x:Bind ViewModel.IsUpdateAvailable, Mode=OneWay}"
Severity="Success" />
<StackPanel
Grid.Row="1"
Margin="0,0,12,0"
HorizontalAlignment="Right"
Orientation="Horizontal"
Spacing="8">
<Button
x:Name="DocsBtn"
x:Uid="DocsBtn"
Click="DocsBtn_Click"
Style="{StaticResource FlyoutButtonStyle}">
<ToolTipService.ToolTip>
<TextBlock x:Uid="DocsTooltip"/>
</ToolTipService.ToolTip>
<FontIcon FontSize="16" Glyph="&#xE8A5;" />
</Button>
<Button
x:Name="ReportBugBtn"
x:Uid="BugReportBtn"
Click="ReportBugBtn_Click"
Style="{StaticResource FlyoutButtonStyle}">
<ToolTipService.ToolTip>
<TextBlock x:Uid="BugReportTooltip"/>
</ToolTipService.ToolTip>
<FontIcon FontSize="16" Glyph="&#xebe8;" />
</Button>
<Button
x:Name="SettingsBtn"
Padding="8"
x:Uid="SettingsBtn"
Click="SettingsBtn_Click"
Style="{StaticResource FlyoutButtonStyle}">
<ToolTipService.ToolTip>
<TextBlock x:Uid="SettingsTooltip"/>
</ToolTipService.ToolTip>
<AnimatedIcon x:Name="SearchAnimatedIcon">
<AnimatedIcon.Source>
<animatedVisuals:AnimatedSettingsVisualSource />
</AnimatedIcon.Source>
<AnimatedIcon.FallbackIconSource>
<SymbolIconSource Symbol="Setting" />
</AnimatedIcon.FallbackIconSource>
</AnimatedIcon>
</Button>
<!--<AppBarSeparator />
<Button
x:Name="QuitBtn"
Style="{StaticResource FlyoutButtonStyle}"
ToolTipService.ToolTip="Quit"
Click="QuitButton_Click">
<FontIcon FontSize="16" Glyph="&#xe894;" />
</Button>-->
</StackPanel>
</Grid>
</Grid>
</Page>

View File

@@ -0,0 +1,146 @@
// 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.Threading;
using global::Windows.System;
using interop;
using Microsoft.PowerToys.Settings.UI.Controls;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events;
using Microsoft.PowerToys.Settings.UI.ViewModels;
using Microsoft.PowerToys.Telemetry;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Animation;
namespace Microsoft.PowerToys.Settings.UI.Flyout
{
public sealed partial class LaunchPage : Page
{
private LauncherViewModel ViewModel { get; set; }
public LaunchPage()
{
this.InitializeComponent();
var settingsUtils = new SettingsUtils();
ViewModel = new LauncherViewModel(SettingsRepository<GeneralSettings>.GetInstance(settingsUtils), Views.ShellPage.SendDefaultIPCMessage);
DataContext = ViewModel;
}
private void ModuleButton_Click(object sender, RoutedEventArgs e)
{
FlyoutMenuButton selectedModuleBtn = sender as FlyoutMenuButton;
bool moduleRun = true;
switch ((string)selectedModuleBtn.Tag)
{
case "ColorPicker": // Launch ColorPicker
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowColorPickerSharedEvent()))
{
eventHandle.Set();
}
break;
case "FancyZones": // Launch FancyZones Editor
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.FZEToggleEvent()))
{
eventHandle.Set();
}
break;
case "Hosts": // Launch Hosts
{
bool launchAdmin = SettingsRepository<HostsSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.LaunchAdministrator;
string eventName = !App.IsElevated && launchAdmin
? Constants.ShowHostsAdminSharedEvent()
: Constants.ShowHostsSharedEvent();
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName))
{
eventHandle.Set();
}
}
break;
case "RegistryPreview": // Launch Registry Preview
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.RegistryPreviewTriggerEvent()))
{
eventHandle.Set();
}
break;
case "MeasureTool": // Launch Screen Ruler
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.MeasureToolTriggerEvent()))
{
eventHandle.Set();
}
break;
case "PowerLauncher": // Launch Run
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.PowerLauncherSharedEvent()))
{
eventHandle.Set();
}
break;
case "PowerOCR": // Launch Text Extractor
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShowPowerOCRSharedEvent()))
{
eventHandle.Set();
}
break;
case "ShortcutGuide": // Launch Shortcut Guide
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.ShortcutGuideTriggerEvent()))
{
eventHandle.Set();
}
break;
default:
moduleRun = false;
break;
}
if (moduleRun)
{
PowerToysTelemetry.Log.WriteEvent(new TrayFlyoutModuleRunEvent() { ModuleName = (string)selectedModuleBtn.Tag });
}
}
private void SettingsBtn_Click(object sender, RoutedEventArgs e)
{
App.OpenSettingsWindow(null, true);
}
private async void DocsBtn_Click(object sender, RoutedEventArgs e)
{
await Launcher.LaunchUriAsync(new Uri("https://aka.ms/PowerToysOverview"));
}
private void AllAppButton_Click(object sender, RoutedEventArgs e)
{
Frame.Navigate(typeof(AppsListPage), null, new SlideNavigationTransitionInfo() { Effect = SlideNavigationTransitionEffect.FromRight });
}
private void QuitButton_Click(object sender, RoutedEventArgs e)
{
ViewModel.KillRunner();
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
{
Application.Current.Exit();
});
}
private void ReportBugBtn_Click(object sender, RoutedEventArgs e)
{
ViewModel.StartBugReport();
}
}
}

View File

@@ -0,0 +1,14 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Flyout.ShellPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Flyout"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Loaded="Page_Loaded"
mc:Ignorable="d">
<Grid>
<Frame x:Name="ContentFrame" />
</Grid>
</Page>

View File

@@ -0,0 +1,30 @@
// 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.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Media.Animation;
namespace Microsoft.PowerToys.Settings.UI.Flyout
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class ShellPage : Page
{
public ShellPage()
{
this.InitializeComponent();
}
internal void SwitchToLaunchPage()
{
ContentFrame.Navigate(typeof(LaunchPage), null, new SuppressNavigationTransitionInfo());
}
private void Page_Loaded(object sender, RoutedEventArgs e)
{
SwitchToLaunchPage();
}
}
}

View File

@@ -0,0 +1,49 @@
<winuiex:WindowEx
x:Class="Microsoft.PowerToys.Settings.UI.FlyoutWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:flyout="using:Microsoft.PowerToys.Settings.UI.Flyout"
xmlns:local="using:Microsoft.PowerToys.Settings.UI"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:winuiex="using:WinUIEx"
xmlns:i="using:Microsoft.Xaml.Interactivity"
xmlns:ic="using:Microsoft.Xaml.Interactions.Core"
Title="PowerToys Settings"
IsAlwaysOnTop="True"
IsMaximizable="False"
IsMinimizable="False"
IsResizable="False"
IsShownInSwitchers="False"
IsTitleBarVisible="False"
mc:Ignorable="d">
<winuiex:WindowEx.Backdrop>
<winuiex:AcrylicSystemBackdrop
DarkFallbackColor="#1c1c1c"
DarkLuminosityOpacity="0.96"
DarkTintColor="#202020"
DarkTintOpacity="0.5"
LightFallbackColor="#EEEEEE"
LightLuminosityOpacity="0.90"
LightTintColor="#F3F3F3"
LightTintOpacity="0" />
</winuiex:WindowEx.Backdrop>
<Grid>
<!-- HACK: https://github.com/microsoft/microsoft-ui-xaml/issues/7629 -->
<!-- W11 grey border, W10: no border -->
<i:Interaction.Behaviors>
<ic:DataTriggerBehavior
Binding="{x:Bind ViewModel.Windows10}"
ComparisonCondition="Equal"
Value="True">
<ic:ChangePropertyAction
PropertyName="BorderThickness"
Value="1" />
<ic:ChangePropertyAction
PropertyName="BorderBrush"
Value="{ThemeResource SurfaceStrokeColorDefaultBrush}" />
</ic:DataTriggerBehavior>
</i:Interaction.Behaviors>
<flyout:ShellPage x:Name="FlyoutShellPage" />
</Grid>
</winuiex:WindowEx>

View File

@@ -0,0 +1,95 @@
// 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.Helpers;
using Microsoft.PowerToys.Settings.UI.Library.Telemetry.Events;
using Microsoft.PowerToys.Settings.UI.ViewModels.Flyout;
using Microsoft.PowerToys.Telemetry;
using Microsoft.UI;
using Microsoft.UI.Windowing;
using Windows.Graphics;
using WinUIEx;
namespace Microsoft.PowerToys.Settings.UI
{
/// <summary>
/// An empty window that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class FlyoutWindow : WindowEx
{
private const int WindowWidth = 386;
private const int WindowHeight = 486;
private const int WindowMargin = 12;
public FlyoutViewModel ViewModel { get; set; }
public POINT? FlyoutAppearPosition { get; set; }
public FlyoutWindow(POINT? initialPosition)
{
this.InitializeComponent();
this.Activated += FlyoutWindow_Activated;
FlyoutAppearPosition = initialPosition;
ViewModel = new FlyoutViewModel();
}
private void FlyoutWindow_Activated(object sender, Microsoft.UI.Xaml.WindowActivatedEventArgs args)
{
PowerToysTelemetry.Log.WriteEvent(new TrayFlyoutActivatedEvent());
if (args.WindowActivationState == Microsoft.UI.Xaml.WindowActivationState.CodeActivated)
{
var hwnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
WindowId windowId = Win32Interop.GetWindowIdFromWindow(hwnd);
if (!FlyoutAppearPosition.HasValue)
{
DisplayArea displayArea = DisplayArea.GetFromWindowId(windowId, DisplayAreaFallback.Nearest);
double dpiScale = (float)this.GetDpiForWindow() / 96;
double x = displayArea.WorkArea.Width - (dpiScale * (WindowWidth + WindowMargin));
double y = displayArea.WorkArea.Height - (dpiScale * (WindowHeight + WindowMargin));
this.MoveAndResize(x, y, WindowWidth, WindowHeight);
}
else
{
DisplayArea displayArea = DisplayArea.GetFromPoint(new PointInt32(FlyoutAppearPosition.Value.X, FlyoutAppearPosition.Value.Y), DisplayAreaFallback.Nearest);
// Move the window to the correct screen as a little blob, so we can get the accurate dpi for the screen to calculate the best position to show it.
this.MoveAndResize(FlyoutAppearPosition.Value.X, FlyoutAppearPosition.Value.Y, 1, 1);
double dpiScale = (float)this.GetDpiForWindow() / 96;
// Position the window so that it's inside the display are closest to the point.
POINT newPosition = new POINT(FlyoutAppearPosition.Value.X - (int)(dpiScale * WindowWidth / 2), FlyoutAppearPosition.Value.Y - (int)(dpiScale * WindowHeight / 2));
if (newPosition.X < displayArea.WorkArea.X)
{
newPosition.X = displayArea.WorkArea.X;
}
if (newPosition.Y < displayArea.WorkArea.Y)
{
newPosition.Y = displayArea.WorkArea.Y;
}
if (newPosition.X + (dpiScale * WindowWidth) > displayArea.WorkArea.X + displayArea.WorkArea.Width)
{
newPosition.X = (int)(displayArea.WorkArea.X + displayArea.WorkArea.Width - (dpiScale * WindowWidth));
}
if (newPosition.Y + (dpiScale * WindowHeight) > displayArea.WorkArea.Y + displayArea.WorkArea.Height)
{
newPosition.Y = (int)(displayArea.WorkArea.Y + displayArea.WorkArea.Height - (dpiScale * WindowHeight));
}
this.MoveAndResize(newPosition.X, newPosition.Y, WindowWidth, WindowHeight);
}
}
if (args.WindowActivationState == Microsoft.UI.Xaml.WindowActivationState.Deactivated)
{
if (ViewModel.CanHide)
{
FlyoutShellPage.SwitchToLaunchPage();
this.Hide();
}
}
}
}
}

View File

@@ -0,0 +1,17 @@
<winuiex:WindowEx
x:Class="Microsoft.PowerToys.Settings.UI.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:winuiex="using:WinUIEx"
MinWidth="480"
MinHeight="480"
Closed="Window_Closed"
mc:Ignorable="d">
<Window.SystemBackdrop>
<MicaBackdrop/>
</Window.SystemBackdrop>
<local:ShellPage x:Name="shellPage" />
</winuiex:WindowEx>

View File

@@ -0,0 +1,289 @@
// 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 ManagedCommon;
using Microsoft.PowerLauncher.Telemetry;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.PowerToys.Telemetry;
using Microsoft.UI;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Windows.Data.Json;
using WinUIEx;
namespace Microsoft.PowerToys.Settings.UI
{
/// <summary>
/// An empty window that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainWindow : WindowEx
{
public MainWindow(bool isDark, bool createHidden = false)
{
var bootTime = new System.Diagnostics.Stopwatch();
bootTime.Start();
ShellPage.SetElevationStatus(App.IsElevated);
ShellPage.SetIsUserAnAdmin(App.IsUserAnAdmin);
// Set window icon
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
WindowId windowId = Win32Interop.GetWindowIdFromWindow(hWnd);
AppWindow appWindow = AppWindow.GetFromWindowId(windowId);
appWindow.SetIcon("Assets\\Settings\\icon.ico");
// Passed by parameter, as it needs to be evaluated ASAP, otherwise there is a white flash
if (isDark)
{
ThemeHelpers.SetImmersiveDarkMode(hWnd, isDark);
}
var placement = Utils.DeserializePlacementOrDefault(hWnd);
if (createHidden)
{
placement.ShowCmd = NativeMethods.SW_HIDE;
}
NativeMethods.SetWindowPlacement(hWnd, ref placement);
var loader = Helpers.ResourceLoaderInstance.ResourceLoader;
Title = loader.GetString("SettingsWindow_Title");
// send IPC Message
ShellPage.SetDefaultSndMessageCallback(msg =>
{
// IPC Manager is null when launching runner directly
App.GetTwoWayIPCManager()?.Send(msg);
});
// send IPC Message
ShellPage.SetRestartAdminSndMessageCallback(msg =>
{
App.GetTwoWayIPCManager()?.Send(msg);
Environment.Exit(0); // close application
});
// send IPC Message
ShellPage.SetCheckForUpdatesMessageCallback(msg =>
{
App.GetTwoWayIPCManager()?.Send(msg);
});
// open main window
ShellPage.SetOpenMainWindowCallback(type =>
{
DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
App.OpenSettingsWindow(type));
});
// open main window
ShellPage.SetUpdatingGeneralSettingsCallback((string module, bool isEnabled) =>
{
SettingsRepository<GeneralSettings> repository = SettingsRepository<GeneralSettings>.GetInstance(new SettingsUtils());
GeneralSettings generalSettingsConfig = repository.SettingsConfig;
bool needToUpdate = false;
switch (module)
{
case "AlwaysOnTop":
needToUpdate = generalSettingsConfig.Enabled.AlwaysOnTop != isEnabled;
generalSettingsConfig.Enabled.AlwaysOnTop = isEnabled; break;
case "Awake":
needToUpdate = generalSettingsConfig.Enabled.Awake != isEnabled;
generalSettingsConfig.Enabled.Awake = isEnabled; break;
case "ColorPicker":
needToUpdate = generalSettingsConfig.Enabled.ColorPicker != isEnabled;
generalSettingsConfig.Enabled.ColorPicker = isEnabled; break;
case "FancyZones":
needToUpdate = generalSettingsConfig.Enabled.FancyZones != isEnabled;
generalSettingsConfig.Enabled.FancyZones = isEnabled; break;
case "FileLocksmith":
needToUpdate = generalSettingsConfig.Enabled.FileLocksmith != isEnabled;
generalSettingsConfig.Enabled.FileLocksmith = isEnabled; break;
case "FindMyMouse":
needToUpdate = generalSettingsConfig.Enabled.FindMyMouse != isEnabled;
generalSettingsConfig.Enabled.FindMyMouse = isEnabled; break;
case "Hosts":
needToUpdate = generalSettingsConfig.Enabled.Hosts != isEnabled;
generalSettingsConfig.Enabled.Hosts = isEnabled; break;
case "ImageResizer":
needToUpdate = generalSettingsConfig.Enabled.ImageResizer != isEnabled;
generalSettingsConfig.Enabled.ImageResizer = isEnabled; break;
case "KeyboardManager":
needToUpdate = generalSettingsConfig.Enabled.KeyboardManager != isEnabled;
generalSettingsConfig.Enabled.KeyboardManager = isEnabled; break;
case "MouseHighlighter":
needToUpdate = generalSettingsConfig.Enabled.MouseHighlighter != isEnabled;
generalSettingsConfig.Enabled.MouseHighlighter = isEnabled; break;
case "MouseJump":
needToUpdate = generalSettingsConfig.Enabled.MouseJump != isEnabled;
generalSettingsConfig.Enabled.MouseJump = isEnabled; break;
case "MousePointerCrosshairs":
needToUpdate = generalSettingsConfig.Enabled.MousePointerCrosshairs != isEnabled;
generalSettingsConfig.Enabled.MousePointerCrosshairs = isEnabled; break;
case "MouseWithoutBorders":
needToUpdate = generalSettingsConfig.Enabled.MouseWithoutBorders != isEnabled;
generalSettingsConfig.Enabled.MouseWithoutBorders = isEnabled; break;
case "PastePlain":
needToUpdate = generalSettingsConfig.Enabled.PastePlain != isEnabled;
generalSettingsConfig.Enabled.PastePlain = isEnabled; break;
case "Peek":
needToUpdate = generalSettingsConfig.Enabled.Peek != isEnabled;
generalSettingsConfig.Enabled.Peek = isEnabled; break;
case "PowerRename":
needToUpdate = generalSettingsConfig.Enabled.PowerRename != isEnabled;
generalSettingsConfig.Enabled.PowerRename = isEnabled; break;
case "PowerLauncher":
needToUpdate = generalSettingsConfig.Enabled.PowerLauncher != isEnabled;
generalSettingsConfig.Enabled.PowerLauncher = isEnabled; break;
case "PowerAccent":
needToUpdate = generalSettingsConfig.Enabled.PowerAccent != isEnabled;
generalSettingsConfig.Enabled.PowerAccent = isEnabled; break;
case "RegistryPreview":
needToUpdate = generalSettingsConfig.Enabled.RegistryPreview != isEnabled;
generalSettingsConfig.Enabled.RegistryPreview = isEnabled; break;
case "MeasureTool":
needToUpdate = generalSettingsConfig.Enabled.MeasureTool != isEnabled;
generalSettingsConfig.Enabled.MeasureTool = isEnabled; break;
case "ShortcutGuide":
needToUpdate = generalSettingsConfig.Enabled.ShortcutGuide != isEnabled;
generalSettingsConfig.Enabled.ShortcutGuide = isEnabled; break;
case "PowerOCR":
needToUpdate = generalSettingsConfig.Enabled.PowerOCR != isEnabled;
generalSettingsConfig.Enabled.PowerOCR = isEnabled; break;
case "VideoConference":
needToUpdate = generalSettingsConfig.Enabled.VideoConference != isEnabled;
generalSettingsConfig.Enabled.VideoConference = isEnabled; break;
}
if (needToUpdate)
{
var outgoing = new OutGoingGeneralSettings(generalSettingsConfig);
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
{
ShellPage.SendDefaultIPCMessage(outgoing.ToString());
ShellPage.ShellHandler?.SignalGeneralDataUpdate();
});
}
return needToUpdate;
});
// open oobe
ShellPage.SetOpenOobeCallback(() =>
{
if (App.GetOobeWindow() == null)
{
App.SetOobeWindow(new OobeWindow(Microsoft.PowerToys.Settings.UI.OOBE.Enums.PowerToysModules.Overview, App.IsDarkTheme()));
}
App.GetOobeWindow().Activate();
});
// open flyout
ShellPage.SetOpenFlyoutCallback((POINT? p) =>
{
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
{
if (App.GetFlyoutWindow() == null)
{
App.SetFlyoutWindow(new FlyoutWindow(p));
}
FlyoutWindow flyout = App.GetFlyoutWindow();
flyout.FlyoutAppearPosition = p;
flyout.Activate();
// https://github.com/microsoft/microsoft-ui-xaml/issues/7595 - Activate doesn't bring window to the foreground
// Need to call SetForegroundWindow to actually gain focus.
Utils.BecomeForegroundWindow(flyout.GetWindowHandle());
});
});
// disable flyout hiding
ShellPage.SetDisableFlyoutHidingCallback(() =>
{
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
{
if (App.GetFlyoutWindow() == null)
{
App.SetFlyoutWindow(new FlyoutWindow(null));
}
App.GetFlyoutWindow().ViewModel.DisableHiding();
});
});
this.InitializeComponent();
SetTheme(isDark);
// receive IPC Message
App.IPCMessageReceivedCallback = (string msg) =>
{
if (ShellPage.ShellHandler.IPCResponseHandleList != null)
{
var success = JsonObject.TryParse(msg, out JsonObject json);
if (success)
{
foreach (Action<JsonObject> handle in ShellPage.ShellHandler.IPCResponseHandleList)
{
handle(json);
}
}
else
{
Logger.LogError("Failed to parse JSON from IPC message.");
}
}
};
bootTime.Stop();
PowerToysTelemetry.Log.WriteEvent(new SettingsBootEvent() { BootTimeMs = bootTime.ElapsedMilliseconds });
}
public void NavigateToSection(System.Type type)
{
ShellPage.Navigate(type);
}
public void CloseHiddenWindow()
{
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
if (!NativeMethods.IsWindowVisible(hWnd))
{
Close();
}
}
private void Window_Closed(object sender, WindowEventArgs args)
{
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
Utils.SerializePlacement(hWnd);
if (App.GetOobeWindow() == null)
{
App.ClearSettingsWindow();
}
else
{
args.Handled = true;
NativeMethods.ShowWindow(hWnd, NativeMethods.SW_HIDE);
}
}
internal void EnsurePageIsSelected()
{
ShellPage.EnsurePageIsSelected();
}
private void SetTheme(bool isDark)
{
shellPage.RequestedTheme = isDark ? ElementTheme.Dark : ElementTheme.Light;
}
}
}

View File

@@ -0,0 +1,51 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeAlwaysOnTop"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_AlwaysOnTop"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/AlwaysOnTop.png">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<controls:ShortcutWithTextLabelControl
x:Name="HotkeyControl"
x:Uid="Oobe_AlwaysOnTop_HowToUse" />
<TextBlock
x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_AlwaysOnTop_TipsAndTricks"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_AlwaysOnTop"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_AlwaysOnTop"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,46 @@
// 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.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobeAlwaysOnTop : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeAlwaysOnTop()
{
InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.AlwaysOnTop]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(AlwaysOnTopPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
HotkeyControl.Keys = SettingsRepository<AlwaysOnTopSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.Hotkey.Value.GetKeysList();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,51 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeAwake"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_Awake"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/Awake.png">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_Awake_HowToUse"
Background="Transparent" />
<TextBlock
x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_Awake_TipsAndTricks"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_Awake"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_Awake"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,44 @@
// 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.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobeAwake : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeAwake()
{
InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.Awake]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(AwakePage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,56 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeColorPicker"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_ColorPicker"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/ColorPicker.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<controls:ShortcutWithTextLabelControl
x:Name="HotkeyControl"
x:Uid="Oobe_ColorPicker_HowToUse" />
<TextBlock
x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_ColorPicker_TipsAndTricks"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="Launch_ColorPicker"
Click="Start_ColorPicker_Click"
Style="{StaticResource AccentButtonStyle}" />
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_ColorPicker"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_ColorPicker"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,62 @@
// 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.Threading;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobeColorPicker : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeColorPicker()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.ColorPicker]);
DataContext = ViewModel;
}
private void Start_ColorPicker_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.ColorPickerSharedEventCallback != null)
{
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, OobeShellPage.ColorPickerSharedEventCallback()))
{
eventHandle.Set();
}
}
ViewModel.LogRunningModuleEvent();
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(ColorPickerPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
ColorPickerSettings settings = new SettingsUtils().GetSettingsOrDefault<ColorPickerSettings, ColorPickerSettingsVersion1>(ColorPickerSettings.ModuleName, settingsUpgrader: ColorPickerSettings.UpgradeSettings);
HotkeyControl.Keys = settings.Properties.ActivationShortcut.GetKeysList();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,54 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeFancyZones"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_FancyZones"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/FancyZones.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_FancyZones_HowToUse"
Background="Transparent" />
<controls:ShortcutWithTextLabelControl
x:Name="HotkeyControl"
x:Uid="Oobe_FancyZones_HowToUse_Shortcut" />
<TextBlock
x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_FancyZones_TipsAndTricks"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_FancyZones"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_FancyZones"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,46 @@
// 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.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobeFancyZones : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeFancyZones()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.FancyZones]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(FancyZonesPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
HotkeyControl.Keys = SettingsRepository<FancyZonesSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.FancyzonesEditorHotkey.Value.GetKeysList();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,44 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeFileExplorer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_FileExplorer"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/FileExplorer.png">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToEnable"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_FileExplorer_HowToEnable"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_FileExplorerAddOns"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_PowerPreview"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,47 @@
// 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.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class OobeFileExplorer : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeFileExplorer()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.FileExplorer]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(PowerPreviewPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,52 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeFileLocksmith"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_FileLocksmith"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/FileLocksmith.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_FileLocksmith_HowToUse"
Background="Transparent" />
<TextBlock
x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_FileLocksmith_TipsAndTricks"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_FileLocksmith"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_FileLocksmith"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,47 @@
// 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.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class OobeFileLocksmith : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeFileLocksmith()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.FileLocksmith]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(FileLocksmithPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,39 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeHosts"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_Hosts"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/HostsFileEditor.png">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="Launch_Hosts"
Click="Launch_Hosts_Click"
Style="{StaticResource AccentButtonStyle}" />
<Button
x:Uid="OOBE_Settings"
Click="Launch_Settings_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_HostsFileEditor"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_Hosts"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,60 @@
// 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.Threading;
using interop;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobeHosts : Page
{
public OobePowerToysModule ViewModel { get; }
public OobeHosts()
{
InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.Hosts]);
DataContext = ViewModel;
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
private void Launch_Hosts_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
bool launchAdmin = SettingsRepository<HostsSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.LaunchAdministrator;
string eventName = !App.IsElevated && launchAdmin
? Constants.ShowHostsAdminSharedEvent()
: Constants.ShowHostsSharedEvent();
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName))
{
eventHandle.Set();
}
}
private void Launch_Settings_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(HostsPage));
}
ViewModel.LogOpeningSettingsEvent();
}
}
}

View File

@@ -0,0 +1,52 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeImageResizer"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_ImageResizer"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/ImageResizer.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToLaunch"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_ImageResizer_HowToLaunch"
Background="Transparent" />
<TextBlock
x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_ImageResizer_TipsAndTricks"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_ImageResizer"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_ImageResizer"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,47 @@
// 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.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class OobeImageResizer : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeImageResizer()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.ImageResizer]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(ImageResizerPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,51 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeKBM"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_KBM"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/KBM.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToCreateMappings"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_KBM_HowToCreateMappings"
Background="Transparent" />
<TextBlock
x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_KBM_TipsAndTricks"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_KeyboardManager"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_KBM"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,47 @@
// 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.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class OobeKBM : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeKBM()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.KBM]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(KeyboardManagerPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,48 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeMeasureTool"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_MeasureTool"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/ScreenRuler.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToLaunch"
Style="{ThemeResource OobeSubtitleStyle}" />
<controls:ShortcutWithTextLabelControl
x:Name="HotkeyActivation"
x:Uid="Oobe_MeasureTool_Activation" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_MeasureTool_HowToLaunch"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_ScreenRuler"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_MeasureTool"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,49 @@
// 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.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class OobeMeasureTool : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeMeasureTool()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.MeasureTool]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(MeasureToolPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
HotkeyActivation.Keys = SettingsRepository<MeasureToolSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.GetKeysList();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,64 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeMouseUtils"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_MouseUtils"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/MouseUtils.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_MouseUtils_FindMyMouse"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_MouseUtils_FindMyMouse_Description"
Background="Transparent" />
<TextBlock
x:Uid="Oobe_MouseUtils_MouseHighlighter"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_MouseUtils_MouseHighlighter_Description"
Background="Transparent" />
<TextBlock
x:Uid="Oobe_MouseUtils_MousePointerCrosshairs"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_MouseUtils_MousePointerCrosshairs_Description"
Background="Transparent" />
<TextBlock
x:Uid="Oobe_MouseUtils_MouseJump"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_MouseUtils_MouseJump_Description"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_MouseUtilities"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_MouseUtils"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,44 @@
// 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.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobeMouseUtils : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeMouseUtils()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.MouseUtils]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(MouseUtilsPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,52 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeMouseWithoutBorders"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_MouseWithoutBorders"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/MouseWithoutBorders.png">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_MouseWithoutBorders_HowToUse"
Background="Transparent" />
<TextBlock
x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_MouseWithoutBorders_TipsAndTricks"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_MouseWithoutBorders"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_MouseWithoutBorders"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,47 @@
// 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.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class OobeMouseWithoutBorders : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeMouseWithoutBorders()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.MouseWithoutBorders]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(MouseWithoutBordersPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,40 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeOverview"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_Overview"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/OOBEPTHero.png">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="Oobe_Overview_DescriptionLinkText"
TextWrapping="Wrap" />
</HyperlinkButton>
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,44 @@
// 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.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobeOverview : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeOverview()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.Overview]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(GeneralPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,193 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeOverviewAlternate"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_Overview"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/OOBEPTHeroShort.png"
HeroImageHeight="120">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Alternate_OOBE_Description"
Margin="0,24,0,12"
FontWeight="SemiBold" />
<GridView Margin="-8,0,0,0" SelectionMode="None">
<GridViewItem>
<Grid
Width="280"
Margin="8"
Padding="16,16,16,10"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="8"
RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image
Width="36"
HorizontalAlignment="Left"
Source="ms-appx:///Assets/Settings/FluentIcons/FluentIconsFancyZones.png" />
<TextBlock
x:Uid="Alternate_OOBE_FancyZones_Title"
Grid.Row="1"
Margin="0,12,0,6"
HorizontalAlignment="Left"
FontSize="16"
FontWeight="SemiBold"
TextWrapping="Wrap" />
<TextBlock
x:Uid="Alternate_OOBE_FancyZones_Description"
Grid.Row="2"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
TextWrapping="Wrap" />
<controls:ShortcutWithTextLabelControl
x:Name="FancyZonesHotkeyControl"
Grid.Row="3"
Margin="0,8,0,0" />
</Grid>
</GridViewItem>
<GridViewItem>
<Grid
Width="280"
Padding="16,16,16,10"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="8"
RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image
Width="36"
HorizontalAlignment="Left"
Source="ms-appx:///Assets/Settings/FluentIcons/FluentIconsPowerToysRun.png" />
<TextBlock
x:Uid="Alternate_OOBE_Run_Title"
Grid.Row="1"
Margin="0,12,0,6"
HorizontalAlignment="Left"
FontSize="16"
FontWeight="SemiBold"
TextWrapping="Wrap" />
<TextBlock
x:Uid="Alternate_OOBE_Run_Description"
Grid.Row="2"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
TextWrapping="Wrap" />
<controls:ShortcutWithTextLabelControl
x:Name="RunHotkeyControl"
Grid.Row="3"
Margin="0,8,0,0" />
</Grid>
</GridViewItem>
<GridViewItem>
<Grid
Width="280"
Padding="16,16,16,10"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="8"
RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image
Width="36"
HorizontalAlignment="Left"
Source="ms-appx:///Assets/Settings/FluentIcons/FluentIconsColorPicker.png" />
<TextBlock
x:Uid="Alternate_OOBE_ColorPicker_Title"
Grid.Row="1"
Margin="0,12,0,6"
HorizontalAlignment="Left"
FontSize="16"
FontWeight="SemiBold"
TextWrapping="Wrap" />
<TextBlock
x:Uid="Alternate_OOBE_ColorPicker_Description"
Grid.Row="2"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
Text="To pick a color:"
TextWrapping="Wrap" />
<controls:ShortcutWithTextLabelControl
x:Name="ColorPickerHotkeyControl"
Grid.Row="3"
Margin="0,8,0,0" />
</Grid>
</GridViewItem>
<GridViewItem>
<Grid
Width="280"
Padding="16,16,16,10"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="8"
RowSpacing="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Image
Width="36"
HorizontalAlignment="Left"
Source="ms-appx:///Assets/Settings/FluentIcons/FluentIconsAlwaysOnTop.png" />
<TextBlock
x:Uid="Alternate_OOBE_AlwaysOnTop_Title"
Grid.Row="1"
Margin="0,12,0,6"
HorizontalAlignment="Left"
FontSize="16"
FontWeight="SemiBold"
TextWrapping="Wrap" />
<TextBlock
x:Uid="Alternate_OOBE_AlwaysOnTop_Description"
Grid.Row="2"
FontSize="12"
Foreground="{ThemeResource TextFillColorSecondaryBrush}"
TextWrapping="Wrap" />
<controls:ShortcutWithTextLabelControl
x:Name="AlwaysOnTopHotkeyControl"
Grid.Row="3"
Margin="0,8,0,0" />
</Grid>
</GridViewItem>
</GridView>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,50 @@
// 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.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobeOverviewAlternate : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeOverviewAlternate()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.Overview]);
DataContext = ViewModel;
FancyZonesHotkeyControl.Keys = SettingsRepository<FancyZonesSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.FancyzonesEditorHotkey.Value.GetKeysList();
RunHotkeyControl.Keys = SettingsRepository<PowerLauncherSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.OpenPowerLauncher.GetKeysList();
ColorPickerHotkeyControl.Keys = SettingsRepository<ColorPickerSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.GetKeysList();
AlwaysOnTopHotkeyControl.Keys = SettingsRepository<AlwaysOnTopSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.Hotkey.Value.GetKeysList();
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(GeneralPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,23 @@
<!-- Copyright (c) Microsoft Corporation. All rights reserved. -->
<!-- Licensed under the MIT License. See LICENSE in the project root for license information. -->
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeOverviewPlaceholder"
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.OOBE.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Loaded="Page_Loaded"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid Margin="0,24,0,0">
<ProgressRing
x:Name="LoadingProgressRing"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsIndeterminate="True"
Visibility="Visible" />
</Grid>
</Page>

View File

@@ -0,0 +1,73 @@
// 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.Threading.Tasks;
using AllExperiments;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Services;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobeOverviewPlaceholder : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeOverviewPlaceholder()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.Overview]);
DataContext = ViewModel;
}
private static async Task<bool> GetIsExperiment()
{
Experiments landingPageExp = new Experiments();
var experimentEnabled = await landingPageExp.EnableLandingPageExperimentAsync();
return experimentEnabled;
}
private async void Reload()
{
var isExperiment = await GetIsExperiment();
if (isExperiment)
{
this.Frame.Navigate(typeof(OobeOverviewAlternate));
}
else
{
this.Frame.Navigate(typeof(OobeOverview));
}
}
private void Page_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
Reload();
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(GeneralPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,44 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobePastePlain"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_PastePlain"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/PastePlain.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<controls:ShortcutWithTextLabelControl
x:Name="HotkeyControl"
x:Uid="Oobe_PastePlain_HowToUse" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_PastePlain"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_PastePlain"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,46 @@
// 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.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobePastePlain : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobePastePlain()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.PastePlain]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(PastePlainPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
HotkeyControl.Keys = SettingsRepository<PastePlainSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.GetKeysList();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,48 @@
<!-- Copyright (c) Microsoft Corporation and Contributors. -->
<!-- Licensed under the MIT License. -->
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobePeek"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<controls:OOBEPageControl
x:Uid="Oobe_Peek"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/Peek.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<controls:ShortcutWithTextLabelControl
x:Name="HotkeyControl"
x:Uid="Oobe_Peek_HowToUse" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_Peek"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_Peek"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,49 @@
// 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.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class OobePeek : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobePeek()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.Peek]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(PeekPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
HotkeyControl.Keys = SettingsRepository<PeekSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.GetKeysList();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,44 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobePowerAccent"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_QuickAccent"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/PowerAccent.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_QuickAccent_HowToUse"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_QuickAccent"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_QuickAccent"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,44 @@
// 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.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobePowerAccent : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobePowerAccent()
{
InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.QuickAccent]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(PowerAccentPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,52 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobePowerOCR"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_TextExtractor"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/PowerOCR.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<controls:ShortcutWithTextLabelControl
x:Name="HotkeyControl"
x:Uid="Oobe_TextExtractor_HowToUse" />
<TextBlock
x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_TextExtractor_TipsAndTricks"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_TextExtractor"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_TextExtractor"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,46 @@
// 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.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobePowerOCR : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobePowerOCR()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.TextExtractor]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(PowerOcrPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
HotkeyControl.Keys = SettingsRepository<PowerOcrSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.ActivationShortcut.GetKeysList();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,52 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobePowerRename"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_PowerRename"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/PowerRename.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_PowerRename_HowToUse"
Background="Transparent" />
<TextBlock
x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_PowerRename_TipsAndTricks"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_PowerRename"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_PowerRename"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,47 @@
// 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.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class OobePowerRename : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobePowerRename()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.PowerRename]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(PowerRenamePage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,56 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeRegistryPreview"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_RegistryPreview"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/RegistryPreview.png">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToUse"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_RegistryPreview_HowToUse"
Background="Transparent" />
<TextBlock
x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_RegistryPreview_TipsAndTricks"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="Launch_RegistryPreview"
Click="Launch_RegistryPreview_Click"
Style="{StaticResource AccentButtonStyle}" />
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_RegistryPreview"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_RegistryPreview"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,53 @@
// 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.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class OobeRegistryPreview : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeRegistryPreview()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.RegistryPreview]);
DataContext = ViewModel;
}
private void Launch_RegistryPreview_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
ShellPage.SendDefaultIPCMessage("{\"action\":{\"RegistryPreview\":{\"action_name\":\"Launch\", \"value\":\"\"}}}");
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(RegistryPreviewPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,56 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeRun"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_Run"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/Run.gif">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToLaunch"
Style="{ThemeResource OobeSubtitleStyle}" />
<controls:ShortcutWithTextLabelControl
x:Name="HotkeyControl"
x:Uid="Oobe_Run_HowToLaunch" />
<TextBlock
x:Uid="Oobe_TipsAndTricks"
Style="{ThemeResource OobeSubtitleStyle}" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_Run_TipsAndTricks"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="Launch_Run"
Click="Start_Run_Click"
Style="{StaticResource AccentButtonStyle}" />
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_PowerToysRun"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_Run"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,64 @@
// 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.Threading;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class OobeRun : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeRun()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.Run]);
DataContext = ViewModel;
}
private void Start_Run_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.RunSharedEventCallback != null)
{
using (var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, OobeShellPage.RunSharedEventCallback()))
{
eventHandle.Set();
}
}
ViewModel.LogRunningModuleEvent();
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(PowerLauncherPage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
HotkeyControl.Keys = SettingsRepository<PowerLauncherSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.OpenPowerLauncher.GetKeysList();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,179 @@
<UserControl
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeShellPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:animations="using:CommunityToolkit.WinUI.UI.Animations"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="using:CommunityToolkit.WinUI.UI"
HighContrastAdjustment="None"
Loaded="ShellPage_Loaded"
mc:Ignorable="d">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="48" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="LayoutVisualStates">
<VisualState x:Name="WideLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="720" />
</VisualState.StateTriggers>
</VisualState>
<VisualState x:Name="SmallLayout">
<VisualState.StateTriggers>
<AdaptiveTrigger MinWindowWidth="600" />
<AdaptiveTrigger MinWindowWidth="0" />
</VisualState.StateTriggers>
<VisualState.Setters>
<Setter Target="navigationView.PaneDisplayMode" Value="LeftMinimal" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Button
x:Name="PaneToggleBtn"
Width="48"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Click="PaneToggleBtn_Click"
Style="{StaticResource PaneToggleButtonStyle}" />
<Grid
x:Name="AppTitleBar"
Height="{Binding ElementName=navigationView, Path=CompactPaneLength}"
Margin="48,0,0,0"
VerticalAlignment="Top"
IsHitTestVisible="True">
<animations:Implicit.Animations>
<animations:OffsetAnimation Duration="0:0:0.3" />
</animations:Implicit.Animations>
<StackPanel Orientation="Horizontal">
<Image
Width="16"
Height="16"
HorizontalAlignment="Left"
Source="/Assets/Settings/icon.ico" />
<TextBlock
x:Name="AppTitleBarText"
x:Uid="OobeWindow_TitleTxt"
Margin="12,0,0,0"
VerticalAlignment="Center"
Style="{StaticResource CaptionTextBlockStyle}"
TextWrapping="NoWrap" />
</StackPanel>
</Grid>
<NavigationView
Grid.Row="1"
x:Name="navigationView"
IsBackButtonVisible="Collapsed"
IsPaneOpen="True"
DisplayModeChanged="NavigationView_DisplayModeChanged"
IsPaneToggleButtonVisible="False"
IsSettingsVisible="False"
OpenPaneLength="296"
PaneDisplayMode="Left"
SelectionChanged="NavigationView_SelectionChanged">
<NavigationView.MenuItems>
<NavigationViewItem
x:Uid="Shell_General"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsPowerToys.png}"
Tag="Overview" />
<NavigationViewItem
x:Uid="Shell_AlwaysOnTop"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsAlwaysOnTop.png}"
Tag="AlwaysOnTop" />
<NavigationViewItem
x:Uid="Shell_Awake"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsAwake.png}"
Tag="Awake" />
<NavigationViewItem
x:Uid="Shell_ColorPicker"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsColorPicker.png}"
Tag="ColorPicker" />
<NavigationViewItem
x:Uid="Shell_FancyZones"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsFancyZones.png}"
Tag="FancyZones" />
<NavigationViewItem
x:Uid="Shell_FileLocksmith"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsFileLocksmith.png}"
Tag="FileLocksmith" />
<NavigationViewItem
x:Uid="Shell_PowerPreview"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsFileExplorerPreview.png}"
Tag="FileExplorer" />
<NavigationViewItem
x:Uid="Shell_Hosts"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsHosts.png}"
Tag="Hosts" />
<NavigationViewItem
x:Uid="Shell_ImageResizer"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsImageResizer.png}"
Tag="ImageResizer" />
<NavigationViewItem
x:Uid="Shell_KeyboardManager"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsKeyboardManager.png}"
Tag="KBM" />
<NavigationViewItem
x:Uid="Shell_MouseUtilities"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsMouseUtils.png}"
Tag="MouseUtils" />
<NavigationViewItem
x:Uid="Shell_MouseWithoutBorders"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsMouseWithoutBorders.png}"
Tag="MouseWithoutBorders" />
<NavigationViewItem
x:Uid="Shell_PastePlain"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsPastePlain.png}"
Tag="PastePlain" />
<NavigationViewItem
x:Uid="Shell_Peek"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsPeek.png}"
Tag="Peek" />
<NavigationViewItem
x:Uid="Shell_PowerRename"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsPowerRename.png}"
Tag="PowerRename" />
<NavigationViewItem
x:Uid="Shell_PowerLauncher"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsPowerToysRun.png}"
Tag="Run" />
<NavigationViewItem
x:Uid="Shell_QuickAccent"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsPowerAccent.png}"
Tag="QuickAccent" />
<NavigationViewItem
x:Uid="Shell_RegistryPreview"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsRegistryPreview.png}"
Tag="RegistryPreview" />
<NavigationViewItem
x:Uid="Shell_MeasureTool"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsScreenRuler.png}"
Tag="MeasureTool" />
<NavigationViewItem
x:Uid="Shell_ShortcutGuide"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsShortcutGuide.png}"
Tag="ShortcutGuide" />
<NavigationViewItem
x:Uid="Shell_TextExtractor"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsPowerOCR.png}"
Tag="TextExtractor" />
<NavigationViewItem
x:Uid="Shell_VideoConference"
Icon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsVideoConferenceMute.png}"
Tag="VideoConference" />
</NavigationView.MenuItems>
<NavigationView.FooterMenuItems>
<NavigationViewItem
x:Uid="Shell_WhatsNew"
Icon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
Glyph=&#xF133;}"
Tag="WhatsNew" />
</NavigationView.FooterMenuItems>
<NavigationView.Content>
<Frame x:Name="NavigationFrame" />
</NavigationView.Content>
</NavigationView>
</Grid>
</UserControl>

View File

@@ -0,0 +1,304 @@
// 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.ObjectModel;
using System.Globalization;
using AllExperiments;
using global::PowerToys.GPOWrapper;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Controls;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobeShellPage : UserControl
{
public static Func<string> RunSharedEventCallback { get; set; }
public static void SetRunSharedEventCallback(Func<string> implementation)
{
RunSharedEventCallback = implementation;
}
public static Func<string> ColorPickerSharedEventCallback { get; set; }
public static void SetColorPickerSharedEventCallback(Func<string> implementation)
{
ColorPickerSharedEventCallback = implementation;
}
public static Action<Type> OpenMainWindowCallback { get; set; }
public static void SetOpenMainWindowCallback(Action<Type> implementation)
{
OpenMainWindowCallback = implementation;
}
/// <summary>
/// Gets view model.
/// </summary>
public OobeShellViewModel ViewModel { get; } = new OobeShellViewModel();
/// <summary>
/// Gets or sets a shell handler to be used to update contents of the shell dynamically from page within the frame.
/// </summary>
public static OobeShellPage OobeShellHandler { get; set; }
public ObservableCollection<OobePowerToysModule> Modules { get; }
private static ISettingsUtils settingsUtils = new SettingsUtils();
private bool ExperimentationToggleSwitchEnabled { get; set; } = true;
public OobeShellPage()
{
InitializeComponent();
ExperimentationToggleSwitchEnabled = SettingsRepository<GeneralSettings>.GetInstance(settingsUtils).SettingsConfig.EnableExperimentation;
SetTitleBar();
DataContext = ViewModel;
OobeShellHandler = this;
Modules = new ObservableCollection<OobePowerToysModule>();
Modules.Insert((int)PowerToysModules.Overview, new OobePowerToysModule()
{
ModuleName = "Overview",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.AlwaysOnTop, new OobePowerToysModule()
{
ModuleName = "AlwaysOnTop",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.Awake, new OobePowerToysModule()
{
ModuleName = "Awake",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.ColorPicker, new OobePowerToysModule()
{
ModuleName = "ColorPicker",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.FancyZones, new OobePowerToysModule()
{
ModuleName = "FancyZones",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.FileLocksmith, new OobePowerToysModule()
{
ModuleName = "FileLocksmith",
IsNew = true,
});
Modules.Insert((int)PowerToysModules.FileExplorer, new OobePowerToysModule()
{
ModuleName = "FileExplorer",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.ImageResizer, new OobePowerToysModule()
{
ModuleName = "ImageResizer",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.KBM, new OobePowerToysModule()
{
ModuleName = "KBM",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.MouseUtils, new OobePowerToysModule()
{
ModuleName = "MouseUtils",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.MouseWithoutBorders, new OobePowerToysModule()
{
ModuleName = "MouseWithoutBorders",
IsNew = true,
});
Modules.Insert((int)PowerToysModules.Peek, new OobePowerToysModule()
{
ModuleName = "Peek",
IsNew = true,
});
Modules.Insert((int)PowerToysModules.PowerRename, new OobePowerToysModule()
{
ModuleName = "PowerRename",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.Run, new OobePowerToysModule()
{
ModuleName = "Run",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.QuickAccent, new OobePowerToysModule()
{
ModuleName = "QuickAccent",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.ShortcutGuide, new OobePowerToysModule()
{
ModuleName = "ShortcutGuide",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.TextExtractor, new OobePowerToysModule()
{
ModuleName = "TextExtractor",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.VideoConference, new OobePowerToysModule()
{
ModuleName = "VideoConference",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.MeasureTool, new OobePowerToysModule()
{
ModuleName = "MeasureTool",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.Hosts, new OobePowerToysModule()
{
ModuleName = "Hosts",
IsNew = true,
});
Modules.Insert((int)PowerToysModules.PastePlain, new OobePowerToysModule()
{
ModuleName = "PastePlain",
IsNew = true,
});
Modules.Insert((int)PowerToysModules.WhatsNew, new OobePowerToysModule()
{
ModuleName = "WhatsNew",
IsNew = false,
});
Modules.Insert((int)PowerToysModules.RegistryPreview, new OobePowerToysModule()
{
ModuleName = "RegistryPreview",
IsNew = true,
});
}
public void OnClosing()
{
Microsoft.UI.Xaml.Controls.NavigationViewItem selectedItem = this.navigationView.SelectedItem as Microsoft.UI.Xaml.Controls.NavigationViewItem;
if (selectedItem != null)
{
Modules[(int)(PowerToysModules)Enum.Parse(typeof(PowerToysModules), (string)selectedItem.Tag, true)].LogClosingModuleEvent();
}
}
public void NavigateToModule(PowerToysModules selectedModule)
{
if (selectedModule == PowerToysModules.WhatsNew)
{
navigationView.SelectedItem = navigationView.FooterMenuItems[0];
}
else
{
navigationView.SelectedItem = navigationView.MenuItems[(int)selectedModule];
}
}
private void NavigationView_SelectionChanged(Microsoft.UI.Xaml.Controls.NavigationView sender, Microsoft.UI.Xaml.Controls.NavigationViewSelectionChangedEventArgs args)
{
Microsoft.UI.Xaml.Controls.NavigationViewItem selectedItem = args.SelectedItem as Microsoft.UI.Xaml.Controls.NavigationViewItem;
if (selectedItem != null)
{
switch (selectedItem.Tag)
{
case "Overview":
if (ExperimentationToggleSwitchEnabled && GPOWrapper.GetAllowExperimentationValue() != GpoRuleConfigured.Disabled)
{
switch (AllExperiments.Experiments.LandingPageExperiment)
{
case Experiments.ExperimentState.Enabled:
NavigationFrame.Navigate(typeof(OobeOverviewAlternate)); break;
case Experiments.ExperimentState.Disabled:
NavigationFrame.Navigate(typeof(OobeOverview)); break;
case Experiments.ExperimentState.NotLoaded:
NavigationFrame.Navigate(typeof(OobeOverviewPlaceholder)); break;
}
break;
}
else
{
NavigationFrame.Navigate(typeof(OobeOverview));
break;
}
case "WhatsNew": NavigationFrame.Navigate(typeof(OobeWhatsNew)); break;
case "AlwaysOnTop": NavigationFrame.Navigate(typeof(OobeAlwaysOnTop)); break;
case "Awake": NavigationFrame.Navigate(typeof(OobeAwake)); break;
case "ColorPicker": NavigationFrame.Navigate(typeof(OobeColorPicker)); break;
case "FancyZones": NavigationFrame.Navigate(typeof(OobeFancyZones)); break;
case "FileLocksmith": NavigationFrame.Navigate(typeof(OobeFileLocksmith)); break;
case "Run": NavigationFrame.Navigate(typeof(OobeRun)); break;
case "ImageResizer": NavigationFrame.Navigate(typeof(OobeImageResizer)); break;
case "KBM": NavigationFrame.Navigate(typeof(OobeKBM)); break;
case "PowerRename": NavigationFrame.Navigate(typeof(OobePowerRename)); break;
case "QuickAccent": NavigationFrame.Navigate(typeof(OobePowerAccent)); break;
case "FileExplorer": NavigationFrame.Navigate(typeof(OobeFileExplorer)); break;
case "ShortcutGuide": NavigationFrame.Navigate(typeof(OobeShortcutGuide)); break;
case "TextExtractor": NavigationFrame.Navigate(typeof(OobePowerOCR)); break;
case "VideoConference": NavigationFrame.Navigate(typeof(OobeVideoConference)); break;
case "MouseUtils": NavigationFrame.Navigate(typeof(OobeMouseUtils)); break;
case "MouseWithoutBorders": NavigationFrame.Navigate(typeof(OobeMouseWithoutBorders)); break;
case "MeasureTool": NavigationFrame.Navigate(typeof(OobeMeasureTool)); break;
case "Hosts": NavigationFrame.Navigate(typeof(OobeHosts)); break;
case "RegistryPreview": NavigationFrame.Navigate(typeof(OobeRegistryPreview)); break;
case "PastePlain": NavigationFrame.Navigate(typeof(OobePastePlain)); break;
case "Peek": NavigationFrame.Navigate(typeof(OobePeek)); break;
}
}
}
private void SetTitleBar()
{
var u = App.GetOobeWindow();
if (u != null)
{
// A custom title bar is required for full window theme and Mica support.
// https://docs.microsoft.com/windows/apps/develop/title-bar?tabs=winui3#full-customization
u.ExtendsContentIntoTitleBar = true;
u.SetTitleBar(AppTitleBar);
}
}
private void ShellPage_Loaded(object sender, RoutedEventArgs e)
{
SetTitleBar();
}
private void NavigationView_DisplayModeChanged(NavigationView sender, NavigationViewDisplayModeChangedEventArgs args)
{
if (args.DisplayMode == NavigationViewDisplayMode.Compact || args.DisplayMode == NavigationViewDisplayMode.Minimal)
{
PaneToggleBtn.Visibility = Visibility.Visible;
AppTitleBar.Margin = new Thickness(48, 0, 0, 0);
AppTitleBarText.Margin = new Thickness(12, 0, 0, 0);
}
else
{
PaneToggleBtn.Visibility = Visibility.Collapsed;
AppTitleBar.Margin = new Thickness(16, 0, 0, 0);
AppTitleBarText.Margin = new Thickness(16, 0, 0, 0);
}
}
private void PaneToggleBtn_Click(object sender, RoutedEventArgs e)
{
navigationView.IsPaneOpen = !navigationView.IsPaneOpen;
}
}
}

View File

@@ -0,0 +1,46 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeShortcutGuide"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_ShortcutGuide"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/OOBEShortcutGuide.png">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToLaunch"
Style="{ThemeResource OobeSubtitleStyle}" />
<controls:ShortcutWithTextLabelControl
x:Name="HotkeyControl"
x:Uid="Oobe_ShortcutGuide_HowToLaunch" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="Launch_ShortcutGuide"
Click="Start_ShortcutGuide_Click"
Style="{StaticResource AccentButtonStyle}" />
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_ShortcutGuide"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_ShortcutGuide"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,75 @@
// 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.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using Microsoft.PowerToys.Settings.UI.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class OobeShortcutGuide : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeShortcutGuide()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.ShortcutGuide]);
DataContext = ViewModel;
}
private void Start_ShortcutGuide_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
var executablePath = Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"PowerToys.ShortcutGuide.exe");
var id = System.Environment.ProcessId.ToString(CultureInfo.InvariantCulture);
var p = Process.Start(executablePath, id);
if (p != null)
{
p.Close();
}
ViewModel.LogRunningModuleEvent();
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(ShortcutGuidePage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
var settingsProperties = SettingsRepository<ShortcutGuideSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties;
if ((bool)settingsProperties.UseLegacyPressWinKeyBehavior.Value)
{
HotkeyControl.Keys = new List<object> { 92 };
}
else
{
HotkeyControl.Keys = settingsProperties.OpenShortcutGuide.GetKeysList();
}
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,57 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeVideoConference"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
mc:Ignorable="d">
<controls:OOBEPageControl
x:Uid="Oobe_VideoConference"
HeroImage="ms-appx:///Assets/Settings/Modules/OOBE/VideoConferenceMute.png">
<controls:OOBEPageControl.PageContent>
<StackPanel Orientation="Vertical">
<TextBlock
x:Uid="Oobe_HowToLaunch"
Style="{ThemeResource OobeSubtitleStyle}" />
<controls:ShortcutWithTextLabelControl
x:Name="HotkeyMicVidControl"
x:Uid="Oobe_VideoConference_ToggleMicVid" />
<controls:ShortcutWithTextLabelControl
x:Name="HotkeyMicControl"
x:Uid="Oobe_VideoConference_ToggleMic" />
<controls:ShortcutWithTextLabelControl
x:Name="HotkeyPushToTalkControl"
x:Uid="Oobe_VideoConference_PushToTalkMic" />
<controls:ShortcutWithTextLabelControl
x:Name="HotkeyVidControl"
x:Uid="Oobe_VideoConference_ToggleVid" />
<toolkitcontrols:MarkdownTextBlock
x:Uid="Oobe_VideoConference_HowToLaunch"
Background="Transparent" />
<StackPanel
Margin="0,24,0,0"
Orientation="Horizontal"
Spacing="12">
<Button
x:Uid="OOBE_Settings"
Click="SettingsLaunchButton_Click" />
<HyperlinkButton
NavigateUri="https://aka.ms/PowerToysOverview_VideoConference"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="LearnMore_VCM"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
</StackPanel>
</controls:OOBEPageControl.PageContent>
</controls:OOBEPageControl>
</Page>

View File

@@ -0,0 +1,52 @@
// 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.Library;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.PowerToys.Settings.UI.Views;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class OobeVideoConference : Page
{
public OobePowerToysModule ViewModel { get; set; }
public OobeVideoConference()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.VideoConference]);
DataContext = ViewModel;
}
private void SettingsLaunchButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
if (OobeShellPage.OpenMainWindowCallback != null)
{
OobeShellPage.OpenMainWindowCallback(typeof(VideoConferencePage));
}
ViewModel.LogOpeningSettingsEvent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
HotkeyMicVidControl.Keys = SettingsRepository<VideoConferenceSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.MuteCameraAndMicrophoneHotkey.Value.GetKeysList();
HotkeyMicControl.Keys = SettingsRepository<VideoConferenceSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.MuteMicrophoneHotkey.Value.GetKeysList();
HotkeyPushToTalkControl.Keys = SettingsRepository<VideoConferenceSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.PushToTalkMicrophoneHotkey.Value.GetKeysList();
HotkeyVidControl.Keys = SettingsRepository<VideoConferenceSettings>.GetInstance(new SettingsUtils()).SettingsConfig.Properties.MuteCameraHotkey.Value.GetKeysList();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
}
}

View File

@@ -0,0 +1,84 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.OOBE.Views.OobeWhatsNew"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:toolkitcontrols="using:CommunityToolkit.WinUI.UI.Controls"
Loaded="Page_Loaded"
mc:Ignorable="d">
<Grid Margin="0,24,0,0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<StackPanel
Grid.Row="0"
Margin="32,0,0,0"
VerticalAlignment="Top"
Orientation="Vertical">
<TextBlock
x:Uid="Oobe_WhatsNew"
AutomationProperties.HeadingLevel="Level1"
Style="{StaticResource TitleTextBlockStyle}" />
<HyperlinkButton
Margin="0,0,0,16"
NavigateUri="https://github.com/microsoft/PowerToys/releases"
Style="{StaticResource TextButtonStyle}">
<TextBlock
x:Uid="Oobe_WhatsNew_DetailedReleaseNotesLink"
TextWrapping="Wrap" />
</HyperlinkButton>
</StackPanel>
<InfoBar
x:Name="ErrorInfoBar"
x:Uid="Oobe_WhatsNew_LoadingError"
Grid.Row="1"
VerticalAlignment="Top"
IsClosable="False"
IsOpen="False"
IsTabStop="True"
Severity="Error" />
<InfoBar
x:Name="ProxyWarningInfoBar"
x:Uid="Oobe_WhatsNew_ProxyAuthenticationWarning"
Grid.Row="1"
VerticalAlignment="Top"
IsClosable="False"
IsOpen="False"
IsTabStop="True"
Severity="Warning" />
<ScrollViewer
Grid.Row="1"
VerticalScrollBarVisibility="Auto">
<Grid Margin="32,24,32,24">
<ProgressRing
x:Name="LoadingProgressRing"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsIndeterminate="True"
Visibility="Visible" />
<toolkitcontrols:MarkdownTextBlock
x:Name="ReleaseNotesMarkdown"
VerticalAlignment="Top"
Background="Transparent"
Header1FontSize="20"
Header1Margin="0,16,0,0"
Header2FontSize="17"
Header2FontWeight="SemiBold"
Header4FontSize="14"
Header4FontWeight="SemiBold"
HorizontalRuleMargin="24"
LinkClicked="ReleaseNotesMarkdown_LinkClicked"
ParagraphMargin="0,0,0,0"
TableMargin="24"
Visibility="Collapsed" />
</Grid>
</ScrollViewer>
</Grid>
</Page>

View File

@@ -0,0 +1,169 @@
// 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.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using CommunityToolkit.WinUI.UI.Controls;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.ViewModel;
using Microsoft.UI.Xaml.Controls;
using Microsoft.UI.Xaml.Navigation;
namespace Microsoft.PowerToys.Settings.UI.OOBE.Views
{
public sealed partial class OobeWhatsNew : Page
{
// Contains information for a release. Used to deserialize release JSON info from GitHub.
private sealed class PowerToysReleaseInfo
{
[JsonPropertyName("published_at")]
public DateTimeOffset PublishedDate { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
[JsonPropertyName("tag_name")]
public string TagName { get; set; }
[JsonPropertyName("body")]
public string ReleaseNotes { get; set; }
}
public OobePowerToysModule ViewModel { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="OobeWhatsNew"/> class.
/// </summary>
public OobeWhatsNew()
{
this.InitializeComponent();
ViewModel = new OobePowerToysModule(OobeShellPage.OobeShellHandler.Modules[(int)PowerToysModules.WhatsNew]);
DataContext = ViewModel;
}
/// <summary>
/// Regex to remove installer hash sections from the release notes.
/// </summary>
private const string RemoveInstallerHashesRegex = @"(\r\n)+## Installer Hashes(\r\n.*)+## Highlights";
private const string RemoveHotFixInstallerHashesRegex = @"(\r\n)+## Installer Hashes(\r\n.*)+$";
private const RegexOptions RemoveInstallerHashesRegexOptions = RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant;
private static async Task<string> GetReleaseNotesMarkdown()
{
string releaseNotesJSON = string.Empty;
// Let's use system proxy
using var proxyClientHandler = new HttpClientHandler
{
DefaultProxyCredentials = CredentialCache.DefaultCredentials,
Proxy = WebRequest.GetSystemWebProxy(),
PreAuthenticate = true,
};
using var getReleaseInfoClient = new HttpClient(proxyClientHandler);
// GitHub APIs require sending an user agent
// https://docs.github.com/rest/overview/resources-in-the-rest-api#user-agent-required
getReleaseInfoClient.DefaultRequestHeaders.TryAddWithoutValidation("User-Agent", "PowerToys");
releaseNotesJSON = await getReleaseInfoClient.GetStringAsync("https://api.github.com/repos/microsoft/PowerToys/releases");
IList<PowerToysReleaseInfo> releases = JsonSerializer.Deserialize<IList<PowerToysReleaseInfo>>(releaseNotesJSON);
// Get the latest releases
var latestReleases = releases.OrderByDescending(release => release.PublishedDate).Take(5);
StringBuilder releaseNotesHtmlBuilder = new StringBuilder(string.Empty);
// Regex to remove installer hash sections from the release notes.
Regex removeHashRegex = new Regex(RemoveInstallerHashesRegex, RemoveInstallerHashesRegexOptions);
// Regex to remove installer hash sections from the release notes, since there'll be no Highlights section for hotfix releases.
Regex removeHotfixHashRegex = new Regex(RemoveHotFixInstallerHashesRegex, RemoveInstallerHashesRegexOptions);
foreach (var release in latestReleases)
{
releaseNotesHtmlBuilder.AppendLine("# " + release.Name);
var notes = removeHashRegex.Replace(release.ReleaseNotes, "\r\n## Highlights");
notes = removeHotfixHashRegex.Replace(notes, string.Empty);
releaseNotesHtmlBuilder.AppendLine(notes);
releaseNotesHtmlBuilder.AppendLine("&nbsp;");
}
return releaseNotesHtmlBuilder.ToString();
}
private async Task Reload()
{
try
{
string releaseNotesMarkdown = await GetReleaseNotesMarkdown();
ProxyWarningInfoBar.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed;
ErrorInfoBar.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed;
ReleaseNotesMarkdown.Text = releaseNotesMarkdown;
ReleaseNotesMarkdown.Visibility = Microsoft.UI.Xaml.Visibility.Visible;
LoadingProgressRing.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed;
}
catch (HttpRequestException httpEx)
{
Logger.LogError("Exception when loading the release notes", httpEx);
if (httpEx.Message.Contains("407", StringComparison.CurrentCulture))
{
ProxyWarningInfoBar.Visibility = Microsoft.UI.Xaml.Visibility.Visible;
}
else
{
ErrorInfoBar.Visibility = Microsoft.UI.Xaml.Visibility.Visible;
}
}
catch (Exception ex)
{
Logger.LogError("Exception when loading the release notes", ex);
ErrorInfoBar.Visibility = Microsoft.UI.Xaml.Visibility.Visible;
}
finally
{
LoadingProgressRing.Visibility = Microsoft.UI.Xaml.Visibility.Collapsed;
}
}
private async void Page_Loaded(object sender, Microsoft.UI.Xaml.RoutedEventArgs e)
{
await Reload();
}
/// <inheritdoc/>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
ViewModel.LogOpeningModuleEvent();
}
/// <inheritdoc/>
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
ViewModel.LogClosingModuleEvent();
}
private void ReleaseNotesMarkdown_LinkClicked(object sender, LinkClickedEventArgs e)
{
if (Uri.TryCreate(e.Link, UriKind.Absolute, out Uri link))
{
this.DispatcherQueue.TryEnqueue(Microsoft.UI.Dispatching.DispatcherQueuePriority.Normal, () =>
{
Process.Start(new ProcessStartInfo(link.ToString()) { UseShellExecute = true });
});
}
}
}
}

View File

@@ -0,0 +1,17 @@
<winuiex:WindowEx
x:Class="Microsoft.PowerToys.Settings.UI.OobeWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.PowerToys.Settings.UI.OOBE.Views"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:winuiex="using:WinUIEx"
MinWidth="480"
MinHeight="480"
Closed="Window_Closed"
mc:Ignorable="d">
<Window.SystemBackdrop>
<MicaBackdrop />
</Window.SystemBackdrop>
<local:OobeShellPage x:Name="shellPage" />
</winuiex:WindowEx>

View File

@@ -0,0 +1,128 @@
// 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 interop;
using ManagedCommon;
using Microsoft.PowerToys.Settings.UI.Helpers;
using Microsoft.PowerToys.Settings.UI.OOBE.Enums;
using Microsoft.PowerToys.Settings.UI.OOBE.Views;
using Microsoft.UI;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Windows.Graphics;
using WinUIEx;
namespace Microsoft.PowerToys.Settings.UI
{
/// <summary>
/// An empty window that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class OobeWindow : WindowEx
{
private PowerToysModules initialModule;
private const int ExpectedWidth = 1100;
private const int ExpectedHeight = 700;
private const int DefaultDPI = 96;
private int _currentDPI;
private WindowId _windowId;
private IntPtr _hWnd;
private AppWindow _appWindow;
public OobeWindow(PowerToysModules initialModule, bool isDark)
{
this.InitializeComponent();
// Set window icon
_hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);
_windowId = Win32Interop.GetWindowIdFromWindow(_hWnd);
_appWindow = AppWindow.GetFromWindowId(_windowId);
_appWindow.SetIcon("Assets\\Settings\\icon.ico");
// Passed by parameter, as it needs to be evaluated ASAP, otherwise there is a white flash
if (isDark)
{
ThemeHelpers.SetImmersiveDarkMode(_hWnd, isDark);
}
SetTheme(isDark);
OverlappedPresenter presenter = _appWindow.Presenter as OverlappedPresenter;
presenter.IsMinimizable = false;
presenter.IsMaximizable = false;
var dpi = NativeMethods.GetDpiForWindow(_hWnd);
_currentDPI = dpi;
float scalingFactor = (float)dpi / DefaultDPI;
int width = (int)(ExpectedWidth * scalingFactor);
int height = (int)(ExpectedHeight * scalingFactor);
SizeInt32 size;
size.Width = width;
size.Height = height;
_appWindow.Resize(size);
this.initialModule = initialModule;
this.SizeChanged += OobeWindow_SizeChanged;
var loader = Helpers.ResourceLoaderInstance.ResourceLoader;
Title = loader.GetString("OobeWindow_Title");
if (shellPage != null)
{
shellPage.NavigateToModule(this.initialModule);
}
OobeShellPage.SetRunSharedEventCallback(() =>
{
return Constants.PowerLauncherSharedEvent();
});
OobeShellPage.SetColorPickerSharedEventCallback(() =>
{
return Constants.ShowColorPickerSharedEvent();
});
OobeShellPage.SetOpenMainWindowCallback((Type type) =>
{
App.OpenSettingsWindow(type);
});
}
private void OobeWindow_SizeChanged(object sender, WindowSizeChangedEventArgs args)
{
var dpi = NativeMethods.GetDpiForWindow(_hWnd);
if (_currentDPI != dpi)
{
// Reacting to a DPI change. Should not cause a resize -> sizeChanged loop.
_currentDPI = dpi;
float scalingFactor = (float)dpi / DefaultDPI;
int width = (int)(ExpectedWidth * scalingFactor);
int height = (int)(ExpectedHeight * scalingFactor);
SizeInt32 size;
size.Width = width;
size.Height = height;
_appWindow.Resize(size);
}
}
private void Window_Closed(object sender, WindowEventArgs args)
{
App.ClearOobeWindow();
var mainWindow = App.GetSettingsWindow();
if (mainWindow != null)
{
mainWindow.CloseHiddenWindow();
}
}
private void SetTheme(bool isDark)
{
shellPage.RequestedTheme = isDark ? ElementTheme.Dark : ElementTheme.Light;
}
}
}

View File

@@ -0,0 +1,802 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<SolidColorBrush x:Key="SubtleButtonBackground" Color="{ThemeResource SubtleFillColorTransparent}" />
<SolidColorBrush x:Key="SubtleButtonBackgroundPointerOver" Color="{ThemeResource SubtleFillColorSecondary}" />
<SolidColorBrush x:Key="SubtleButtonBackgroundPressed" Color="{ThemeResource SubtleFillColorTertiary}" />
<SolidColorBrush x:Key="SubtleButtonBackgroundDisabled" Color="{ThemeResource SubtleFillColorTransparent}" />
<SolidColorBrush x:Key="SubtleButtonForeground" Color="{ThemeResource TextFillColorPrimary}" />
<SolidColorBrush x:Key="SubtleButtonForegroundPointerOver" Color="{ThemeResource TextFillColorPrimary}" />
<SolidColorBrush x:Key="SubtleButtonForegroundPressed" Color="{ThemeResource TextFillColorSecondary}" />
<SolidColorBrush x:Key="SubtleButtonForegroundDisabled" Color="{ThemeResource TextFillColorDisabled}" />
<Style x:Key="SubtleButtonStyle" TargetType="Button">
<Setter Property="Background" Value="{ThemeResource SubtleButtonBackground}" />
<Setter Property="BackgroundSizing" Value="InnerBorderEdge" />
<Setter Property="Foreground" Value="{ThemeResource SubtleButtonForeground}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Width" Value="36" />
<Setter Property="Padding" Value="0" />
<Setter Property="Height" Value="36" />
<Setter Property="Padding" Value="{StaticResource ButtonPadding}" />
<Setter Property="HorizontalAlignment" Value="Left" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontWeight" Value="Normal" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="FocusVisualMargin" Value="-3" />
<Setter Property="CornerRadius" Value="{ThemeResource ControlCornerRadius}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<ContentPresenter
x:Name="ContentPresenter"
Padding="{TemplateBinding Padding}"
HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
AnimatedIcon.State="Normal"
AutomationProperties.AccessibilityView="Raw"
Background="{TemplateBinding Background}"
BackgroundSizing="{TemplateBinding BackgroundSizing}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTransitions="{TemplateBinding ContentTransitions}"
CornerRadius="{TemplateBinding CornerRadius}">
<ContentPresenter.BackgroundTransition>
<BrushTransition Duration="0:0:0.083" />
</ContentPresenter.BackgroundTransition>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="PointerOver" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Pressed" />
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SubtleButtonForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
<VisualState.Setters>
<!-- DisabledVisual Should be handled by the control, not the animated icon. -->
<Setter Target="ContentPresenter.(AnimatedIcon.State)" Value="Normal" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</ContentPresenter>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="HyperlinkButtonStyle" TargetType="HyperlinkButton" />
<Style x:Key="TextButtonStyle" TargetType="ButtonBase">
<Setter Property="Background" Value="{ThemeResource HyperlinkButtonBackground}" />
<Setter Property="Foreground" Value="{ThemeResource HyperlinkButtonForeground}" />
<Setter Property="MinWidth" Value="0" />
<Setter Property="MinHeight" Value="0" />
<Setter Property="Margin" Value="0" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ButtonBase">
<Grid
Margin="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"
CornerRadius="4">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonForegroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBackgroundPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBorderBrushPointerOver}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonForegroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBackgroundPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBorderBrushPressed}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBackgroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource HyperlinkButtonBorderBrushDisabled}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter
x:Name="Text"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
FontWeight="SemiBold" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="RightAlignedCompactToggleSwitchStyle"
BasedOn="{StaticResource DefaultToggleSwitchStyle}"
TargetType="ToggleSwitch">
<Style.Setters>
<Setter Property="MinWidth" Value="0" />
<Setter Property="Height" Value="36" />
<Setter Property="HorizontalContentAlignment" Value="Right" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ToggleSwitch">
<Grid VerticalAlignment="Center"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="Stroke">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchStrokeOff}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchFillOff}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOff}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOn}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchFillOn}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Stroke">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchStrokeOn}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchAreaGrid"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchContainerBackground}" />
</ObjectAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchStrokeOffPointerOver}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchFillOffPointerOver}" />
</ColorAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOffPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOnPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchFillOnPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Stroke">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchStrokeOnPointerOver}" />
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="SwitchAreaGrid"
Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchContainerBackgroundPointerOver}" />
</ColorAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="14" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="14" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="14" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="14" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<VisualState.Setters>
<Setter Target="SwitchKnobOn.HorizontalAlignment" Value="Right" />
<Setter Target="SwitchKnobOn.Margin" Value="0,0,3,0" />
<Setter Target="SwitchKnobOff.HorizontalAlignment" Value="Left" />
<Setter Target="SwitchKnobOff.Margin" Value="3,0,0,0" />
</VisualState.Setters>
<Storyboard>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchStrokeOffPressed}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchFillOffPressed}" />
</ColorAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchFillOnPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Stroke">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchStrokeOnPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOffPressed}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOnPressed}" />
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="SwitchAreaGrid"
Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchContainerBackgroundPressed}" />
</ColorAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="17" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="14" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="17" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="14" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="HeaderContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchHeaderForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OffContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchContentForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OnContentPresenter"
Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchContentForegroundDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="(Shape.Stroke).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchStrokeOffDisabled}" />
</ColorAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="(Shape.Fill).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchFillOffDisabled}" />
</ColorAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchFillOnDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Stroke">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchStrokeOnDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOffDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Background">
<DiscreteObjectKeyFrame KeyTime="0"
Value="{ThemeResource ToggleSwitchKnobFillOnDisabled}" />
</ObjectAnimationUsingKeyFrames>
<ColorAnimationUsingKeyFrames Storyboard.TargetName="SwitchAreaGrid"
Storyboard.TargetProperty="(Panel.Background).(SolidColorBrush.Color)">
<LinearColorKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="{ThemeResource ToggleSwitchContainerBackgroundDisabled}" />
</ColorAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlNormalAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlNormalAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Width">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlNormalAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames EnableDependentAnimation="True"
Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Height">
<SplineDoubleKeyFrame KeySpline="{StaticResource ControlFastOutSlowInKeySpline}"
KeyTime="{StaticResource ControlNormalAnimationDuration}"
Value="12" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ToggleStates">
<VisualStateGroup.Transitions>
<VisualTransition x:Name="DraggingToOnTransition"
GeneratedDuration="0"
From="Dragging"
To="On">
<Storyboard>
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobCurrentToOnOffset}"
TargetName="SwitchKnob" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
<VisualTransition x:Name="OnToDraggingTransition"
GeneratedDuration="0"
From="On"
To="Dragging">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="0"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="0"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="0"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
<VisualTransition x:Name="DraggingToOffTransition"
GeneratedDuration="0"
From="Dragging"
To="Off">
<Storyboard>
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobCurrentToOffOffset}"
TargetName="SwitchKnob" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="1" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
<VisualTransition x:Name="OnToOffTransition"
GeneratedDuration="0"
From="On"
To="Off">
<Storyboard>
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobOnToOffOffset}"
TargetName="SwitchKnob" />
</Storyboard>
</VisualTransition>
<VisualTransition x:Name="OffToOnTransition"
GeneratedDuration="0"
From="Off"
To="On">
<Storyboard>
<RepositionThemeAnimation FromHorizontalOffset="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.KnobOffToOnOffset}"
TargetName="SwitchKnob" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualTransition>
</VisualStateGroup.Transitions>
<VisualState x:Name="Dragging" />
<VisualState x:Name="Off" />
<VisualState x:Name="On">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="KnobTranslateTransform"
Storyboard.TargetProperty="X"
To="20"
Duration="0" />
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobBounds"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="OuterBorder"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOn"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="SwitchKnobOff"
Storyboard.TargetProperty="Opacity">
<LinearDoubleKeyFrame KeyTime="{StaticResource ControlFasterAnimationDuration}"
Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="ContentStates">
<VisualState x:Name="OffContent">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="OffContentPresenter"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OffContentPresenter"
Storyboard.TargetProperty="IsHitTestVisible">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<x:Boolean>True</x:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="OnContent">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="OnContentPresenter"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="OnContentPresenter"
Storyboard.TargetProperty="IsHitTestVisible">
<DiscreteObjectKeyFrame KeyTime="0">
<DiscreteObjectKeyFrame.Value>
<x:Boolean>True</x:Boolean>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="HeaderContentPresenter"
Grid.Row="0"
Margin="{ThemeResource ToggleSwitchTopHeaderMargin}"
VerticalAlignment="Top"
AutomationProperties.AccessibilityView="Raw"
x:DeferLoadStrategy="Lazy"
Content="{TemplateBinding Header}"
ContentTemplate="{TemplateBinding HeaderTemplate}"
Foreground="{ThemeResource ToggleSwitchHeaderForeground}"
IsHitTestVisible="False"
TextWrapping="Wrap"
Visibility="Collapsed" />
<Grid Grid.Row="1"
HorizontalAlignment="Right"
VerticalAlignment="Top">
<Grid.RowDefinitions>
<RowDefinition Height="{ThemeResource ToggleSwitchPreContentMargin}" />
<RowDefinition Height="Auto" />
<RowDefinition Height="{ThemeResource ToggleSwitchPostContentMargin}" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="12"
MaxWidth="12" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid x:Name="SwitchAreaGrid"
Grid.RowSpan="3"
Grid.ColumnSpan="3"
Margin="0,5"
Background="{ThemeResource ToggleSwitchContainerBackground}"
Control.IsTemplateFocusTarget="True"
CornerRadius="{TemplateBinding CornerRadius}" />
<ContentPresenter x:Name="OffContentPresenter"
Grid.RowSpan="3"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw"
Content="{TemplateBinding OffContent}"
ContentTemplate="{TemplateBinding OffContentTemplate}"
Foreground="{TemplateBinding Foreground}"
IsHitTestVisible="False"
Opacity="0" />
<ContentPresenter x:Name="OnContentPresenter"
Grid.RowSpan="3"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
AutomationProperties.AccessibilityView="Raw"
Content="{TemplateBinding OnContent}"
ContentTemplate="{TemplateBinding OnContentTemplate}"
Foreground="{TemplateBinding Foreground}"
IsHitTestVisible="False"
Opacity="0" />
<Rectangle x:Name="OuterBorder"
Grid.Row="1"
Grid.Column="2"
Width="40"
Height="20"
Fill="{ThemeResource ToggleSwitchFillOff}"
RadiusX="10"
RadiusY="10"
Stroke="{ThemeResource ToggleSwitchStrokeOff}"
StrokeThickness="{ThemeResource ToggleSwitchOuterBorderStrokeThickness}" />
<Rectangle x:Name="SwitchKnobBounds"
Grid.Row="1"
Grid.Column="2"
Width="40"
Height="20"
Fill="{ThemeResource ToggleSwitchFillOn}"
Opacity="0"
RadiusX="10"
RadiusY="10"
Stroke="{ThemeResource ToggleSwitchStrokeOn}"
StrokeThickness="{ThemeResource ToggleSwitchOnStrokeThickness}" />
<Grid x:Name="SwitchKnob"
Grid.Row="1"
Grid.Column="2"
Width="20"
Height="20"
HorizontalAlignment="Left">
<Border x:Name="SwitchKnobOn"
Width="12"
Height="12"
Margin="0,0,3,0"
HorizontalAlignment="Right"
Background="{ThemeResource ToggleSwitchKnobFillOn}"
BackgroundSizing="OuterBorderEdge"
BorderBrush="{ThemeResource ToggleSwitchKnobStrokeOn}"
CornerRadius="7"
Opacity="0"
RenderTransformOrigin="0.5, 0.5">
<Border.RenderTransform>
<CompositeTransform />
</Border.RenderTransform>
</Border>
<Rectangle x:Name="SwitchKnobOff"
Width="12"
Height="12"
Margin="3,0,0,0"
HorizontalAlignment="Left"
Fill="{ThemeResource ToggleSwitchKnobFillOff}"
RadiusX="7"
RadiusY="7"
RenderTransformOrigin="0.5, 0.5">
<Rectangle.RenderTransform>
<CompositeTransform />
</Rectangle.RenderTransform>
</Rectangle>
<Grid.RenderTransform>
<TranslateTransform x:Name="KnobTranslateTransform" />
</Grid.RenderTransform>
</Grid>
<Thumb x:Name="SwitchThumb"
Grid.RowSpan="3"
Grid.ColumnSpan="3"
AutomationProperties.AccessibilityView="Raw">
<Thumb.Template>
<ControlTemplate TargetType="Thumb">
<Rectangle Fill="Transparent" />
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style.Setters>
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,32 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style
x:Key="OobeSubtitleStyle"
TargetType="TextBlock">
<Setter Property="Margin" Value="0,16,0,0" />
<Setter Property="Foreground" Value="{ThemeResource DefaultTextForegroundThemeBrush}" />
<Setter Property="AutomationProperties.HeadingLevel" Value="Level3" />
<Setter Property="FontFamily" Value="XamlAutoFontFamily" />
<Setter Property="FontSize" Value="{StaticResource BodyTextBlockFontSize}" />
<Setter Property="FontWeight" Value="SemiBold" />
<Setter Property="TextTrimming" Value="CharacterEllipsis" />
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="LineStackingStrategy" Value="MaxHeight" />
<Setter Property="TextLineBounds" Value="Full" />
</Style>
<x:Double x:Key="SecondaryTextFontSize">12</x:Double>
<Style x:Key="SecondaryTextStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="{StaticResource SecondaryTextFontSize}" />
<Setter Property="Foreground" Value="{ThemeResource TextFillColorSecondaryBrush}" />
</Style>
<x:Double x:Key="HeaderTextFontSize">12</x:Double>
<Style x:Key="HeaderTextStyle" TargetType="TextBlock">
<Setter Property="FontSize" Value="{StaticResource HeaderTextFontSize}"/>
<Setter Property="Foreground" Value="{ThemeResource TextFillColorSecondaryBrush}"/>
<Setter Property="FontWeight" Value="Bold" />
</Style>
</ResourceDictionary>

View File

@@ -0,0 +1,36 @@
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush
x:Key="InfoBarInformationalSeverityBackgroundBrush"
Color="#FF34424d" />
<Color x:Key="InfoBarInformationalSeverityIconBackground">#FF5fb2f2</Color>
<SolidColorBrush
x:Key="SolidBackgroundBrush"
Color="Black" />
</ResourceDictionary>
<ResourceDictionary x:Key="Light">
<SolidColorBrush
x:Key="InfoBarInformationalSeverityBackgroundBrush"
Color="#FFd3e7f7" />
<Color x:Key="InfoBarInformationalSeverityIconBackground">#FF0063b1</Color>
<SolidColorBrush
x:Key="SolidBackgroundBrush"
Color="White" />
</ResourceDictionary>
<ResourceDictionary x:Key="HighContrast">
<SolidColorBrush
x:Key="InfoBarInformationalSeverityBackgroundBrush"
Color="#FF34424d" />
<SolidColorBrush
x:Key="SolidBackgroundBrush"
Color="Black" />
<Color x:Key="InfoBarInformationalSeverityIconBackground">#FF5fb2f2</Color>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>

View File

@@ -0,0 +1,8 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="ms-appx:///SettingsXAML/Controls/SettingsGroup/SettingsGroup.xaml" />
<ResourceDictionary Source="ms-appx:///SettingsXAML/Controls/IsEnabledTextBlock/IsEnabledTextBlock.xaml" />
<ResourceDictionary Source="ms-appx:///SettingsXAML/Controls/FlyoutMenuButton/FlyoutMenuButton.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>

View File

@@ -0,0 +1,154 @@
<Page
x:Class="Microsoft.PowerToys.Settings.UI.Views.AlwaysOnTopPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Microsoft.PowerToys.Settings.UI.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:labs="using:CommunityToolkit.Labs.WinUI"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:ui="using:CommunityToolkit.WinUI.UI"
AutomationProperties.LandmarkType="Main"
mc:Ignorable="d">
<controls:SettingsPageControl
x:Uid="AlwaysOnTop"
IsTabStop="False"
ModuleImageSource="ms-appx:///Assets/Settings/Modules/AlwaysOnTop.png">
<controls:SettingsPageControl.ModuleContent>
<StackPanel Orientation="Vertical" ChildrenTransitions="{StaticResource SettingsCardsAnimations}">
<labs:SettingsCard
x:Uid="AlwaysOnTop_EnableToggleControl_HeaderText"
HeaderIcon="{ui:BitmapIcon Source=/Assets/Settings/FluentIcons/FluentIconsAlwaysOnTop.png}"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured, Converter={StaticResource BoolNegationConverter}}">
<ToggleSwitch
x:Uid="ToggleSwitch"
IsOn="{x:Bind ViewModel.IsEnabled, Mode=TwoWay}" />
</labs:SettingsCard>
<InfoBar
x:Uid="GPO_IsSettingForced"
IsClosable="False"
IsOpen="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}"
IsTabStop="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabledGpoConfigured}"
Severity="Informational" />
<controls:SettingsGroup
x:Uid="AlwaysOnTop_Activation_GroupSettings"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<labs:SettingsExpander
x:Uid="AlwaysOnTop_ActivationShortcut"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
Glyph=&#xEDA7;}"
IsExpanded="True">
<controls:ShortcutControl
MinWidth="{StaticResource SettingActionControlMinWidth}"
HotkeySettings="{x:Bind Path=ViewModel.Hotkey, Mode=TwoWay}" />
<labs:SettingsExpander.Items>
<labs:SettingsCard ContentAlignment="Left">
<CheckBox
x:Uid="AlwaysOnTop_GameMode"
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.DoNotActivateOnGameMode}" />
</labs:SettingsCard>
</labs:SettingsExpander.Items>
</labs:SettingsExpander>
</controls:SettingsGroup>
<controls:SettingsGroup
x:Uid="AlwaysOnTop_Behavior_GroupSettings"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<labs:SettingsExpander
x:Uid="AlwaysOnTop_FrameEnabled"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
Glyph=&#xEB3C;}"
IsExpanded="True">
<ToggleSwitch
x:Uid="ToggleSwitch"
IsOn="{x:Bind Mode=TwoWay, Path=ViewModel.FrameEnabled}" />
<labs:SettingsExpander.Items>
<labs:SettingsCard
x:Uid="AlwaysOnTop_FrameColor_Mode"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.FrameEnabled}">
<ComboBox
MinWidth="{StaticResource SettingActionControlMinWidth}"
SelectedIndex="{x:Bind Mode=TwoWay, Path=ViewModel.FrameAccentColor, Converter={StaticResource BoolToComboBoxIndexConverter}}">
<ComboBoxItem x:Uid="AlwaysOnTop_Radio_Custom_Color" />
<ComboBoxItem x:Uid="AlwaysOnTop_Radio_Windows_Default" />
</ComboBox>
</labs:SettingsCard>
<labs:SettingsCard
x:Uid="AlwaysOnTop_FrameColor"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.FrameEnabled}"
Visibility="{x:Bind Mode=OneWay, Path=ViewModel.FrameAccentColor, Converter={StaticResource ReverseBoolToVisibilityConverter}}">
<controls:ColorPickerButton SelectedColor="{x:Bind Path=ViewModel.FrameColor, Mode=TwoWay}" />
</labs:SettingsCard>
<labs:SettingsCard
x:Uid="AlwaysOnTop_FrameThickness"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.FrameEnabled}">
<Slider
MinWidth="{StaticResource SettingActionControlMinWidth}"
LargeChange="5"
Maximum="30"
Minimum="1"
SmallChange="1"
Value="{x:Bind ViewModel.FrameThickness, Mode=TwoWay}" />
</labs:SettingsCard>
<labs:SettingsCard
ContentAlignment="Left"
Visibility="{x:Bind Mode=OneWay, Path=ViewModel.Windows11, Converter={StaticResource BoolToVisibilityConverter}}">
<CheckBox
x:Uid="AlwaysOnTop_RoundCorners"
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.RoundCornersEnabled}" />
</labs:SettingsCard>
</labs:SettingsExpander.Items>
</labs:SettingsExpander>
<labs:SettingsExpander
x:Uid="AlwaysOnTop_SoundTitle"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
Glyph=&#xE7F3;}"
IsExpanded="True">
<labs:SettingsExpander.Items>
<labs:SettingsCard ContentAlignment="Left">
<CheckBox
x:Uid="AlwaysOnTop_Sound"
IsChecked="{x:Bind Mode=TwoWay, Path=ViewModel.SoundEnabled}" />
</labs:SettingsCard>
</labs:SettingsExpander.Items>
</labs:SettingsExpander>
</controls:SettingsGroup>
<controls:SettingsGroup
x:Uid="ExcludedApps"
IsEnabled="{x:Bind Mode=OneWay, Path=ViewModel.IsEnabled}">
<labs:SettingsExpander
x:Uid="AlwaysOnTop_ExcludedApps"
HeaderIcon="{ui:FontIcon FontFamily={StaticResource SymbolThemeFontFamily},
Glyph=&#xECE4;}"
IsExpanded="True">
<labs:SettingsExpander.Items>
<labs:SettingsCard
HorizontalContentAlignment="Stretch"
ContentAlignment="Vertical">
<TextBox
x:Uid="AlwaysOnTop_ExcludedApps_TextBoxControl"
MinWidth="240"
MinHeight="160"
AcceptsReturn="True"
ScrollViewer.IsVerticalRailEnabled="True"
ScrollViewer.VerticalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollMode="Enabled"
Text="{x:Bind Mode=TwoWay, Path=ViewModel.ExcludedApps, UpdateSourceTrigger=PropertyChanged}"
TextWrapping="Wrap" />
</labs:SettingsCard>
</labs:SettingsExpander.Items>
</labs:SettingsExpander>
</controls:SettingsGroup>
</StackPanel>
</controls:SettingsPageControl.ModuleContent>
<controls:SettingsPageControl.PrimaryLinks>
<controls:PageLink
x:Uid="LearnMore_AlwaysOnTop"
Link="https://aka.ms/PowerToysOverview_AlwaysOnTop" />
</controls:SettingsPageControl.PrimaryLinks>
</controls:SettingsPageControl>
</Page>

Some files were not shown because too many files have changed in this diff Show More